函数 名的使用和第一类对象,闭包,迭代器

1,函数名的运用:

  • 函数名(func())是一个变量,和变量由相同点和异同点,相同点:变量的命名规则同样适用于函数名,同样能进行赋值操作,异同点:函数名不能进行逻辑运算.
  • 1>函数名的内存地址,函数名是有内存地址的,用print(func)可以查找出来

 

def func():
    print("呵呵")
print(func)  # <function func at 0x000001532CC83158>
a = 10
print(id(a))  # 1402039600
  • 二者在查找内存地址的时候变量需要引入id()内置函数,而函数在查找的时候不用
  • 2>函数名可以复制给其他变量,可以进行赋值操作
def func():
    print("哈哈")
a = func  # 把函数名赋值给变量a
a()  # a现在是一个函数名,当加()表示执行函数
  • 3>函数可以当容器类的元素,其实函数名就相当于一个句柄(自己理解)它把函数里边的东西封装起来,打包放在一个地方,函数名就行是一个药引子,当用的时候才会被调用(加(),)

 

# 函数名可以存放到容器中
def func1():
    print("哈哈")
def func2():
    print("呵呵")
def func3():
    print("啊啊")
def func4():
    print("嗯嗯")
lst = [func1, func2, func3, func4]
for i in lst:
    i()  # 分别执行函数
  • 4>函数名可以当做函数的参数(实参),很灵活.

 

def func():
    print("呵呵呵")


def func1(fn):  # 调用函数func1()
    print("哈哈哈")  # 打印"哈哈哈"
    fn()  # 此时运行的fn = func(),当fn(),其实就是调用你func函数
func1(func)  # 运行结果是 哈哈哈  呵呵呵
  • 5>函数名可以当做函数的返回值,     return   func

 

 

def func_1():
    print("这里是函数1")
    def func_2():
        print("这里是函数2")
    print("这里是函数1")  # 第二步打印的是"这里是函数1"
    return func_2  # 返回func_2,西施返回的是一个函数名(无任何意义),只是返回一个值
fn = func_1()  # 第一步:先执行函数func_1(),打印"这里是函数1", 在执行func_2赋值给fn
fn()  # 第五步,在fn后边加(),其实就是在func_2后边加(), 即是在调用函数func_2

 

2,闭包:闭包就是内层函数对外层函数的(非全局)变量的引用,叫做闭包,有点类似于nonlocal.

 

def func():
    name = "alex"  # 常驻内存,防止其他程序改变这个变量
    def inner():
        print(name)  # 内层函数inner访问外部函数的变量
    return inner  # 返回inner这个函数名(并且是谁调用这个函数,就返回给谁)
ret = func()
ret()  # 调用inner函数

# 列如:
name = "wusir"  # 把变量写在全局是极其不安全的,因为是谁都可以改变
def adc():
    global name  # 把全局变量弄到局部来
    name = "呵呵"
    print(name)
adc()
  • 我们可以用   .__closure__来判断此函数是不是闭包

 

def func1():
    name = "alex"
    def func2():
        print(name)  # 闭包
    func2()
    print(func2.__closure__)  # (<cell at 0x0000015C28358D38: str object at 0x0000015C2824C0D8>,)元组形式的内存地址
    # 如果不是就返回None
func1()
  • 2.1>外层函数调用内层函数:先拿到内层函数的地址(内层函数的函数名),在调用内层函数

 

def outer():
    name = "alex"  # 内部函数
    def inner():
        print(name)
    return inner
fn = outer()  # 访问外部函数,获取到外部函数的内存地址
fn()  # 访问内部函数
  • 闭包的好处:
    • 1>常驻内存
    • 2>防止其他程序对内层函数变量改变 

3,迭代器:迭代器就相当于引擎,为循环提供动力.

  • 可迭代对象:str,list,dict,set,tuple
  • 迭代器:句柄 f.
  • 可迭代的对象(Iterable):内部包含  .__iter__().因此可以用  .__iter__()来判断这个对象是不是可迭代.
  • 迭代器(Iterator):内部包含有  .__iter__()  和 .__next__()

 

s = "asdfg"
print("__iter__" in dirs(s))  # True, 说明s是可迭代的
print(dir(s))  # 是判断s里面所有的内容
  • ****模拟for循环:

 

lst = ["皇阿玛", "皇额娘", "容么么", "紫薇"]
it = lst.__iter__()  # 获取迭代器
while 1:  # while循环,是把lst中的每一项都循环出来
    try:  # 尝试
        name = it.__next__()  # 去拿下一项
    except StopIteration  # 那不到数据的时候
        break  # 终止循环(只有循环的时候才break用)
  • #isinstance(对象,类型)  判断***对象是否是***类型的

 

print(isinstance(lst.iterable))  # True,判断是否是可迭代的迭代器一定是可迭代的,可迭代的不一定是迭代器
print(isinstance(lst.iterable))  # False,迭代器里边有__next__().__iter__()
print("__iter__" in dir(lst))  # 确定是一个可迭代对象
print("__next__" in dir(lst))  # 确定不是一个迭代器(如果一个对象里边包含__next__就说明是迭代器)
  • **#迭代器的特点:
    • 1>节省内存
    • 2>惰性机制
    • 3>只能往前拿,不能反着拿

 

lst = ["哈哈", "呵呵"]
it = lst.__iter__()  # 确定类lst是一个可迭代对象
it.__next__()  # 确定lst里边包含__next__
print(it.__next__())  # 开始往出拿元素
print("我要吃黄瓜")
print(it.__next__())  # 开始往出拿第二个元素

 

posted @ 2018-07-18 20:21  帅爆太阳的男人  阅读(136)  评论(0)    收藏  举报