1,函数名的运用:
函数名(func())是一个变量,和变量由相同点和异同点,相同点:变量的命名规则同样适用于函数名,同样能进行赋值操作,异同点:函数名不能进行逻辑运算.
1>函数名的内存地址,函数名是有内存地址的,用print(func)可以查找出来
列如:def func():
print("呵呵")
print(func).......................此时打印的结果是:<function func at 0x00000266D9203158>是一个在内存的地址
变量:a = 10
print(id(a))........................此时打印的结果是:1954966832也是一个内存地址
二者在查找内存地址的时候变量需要引入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()......................................此时打印的是:"哈哈" "\n" "呵呵" "\n" "啊啊" "\n" "嗯嗯"
4>函数名可以当做函数的参数(实参),很灵活.
列如:def func():
print("呵呵呵")
def func1(fn):....................2调用函数func1()
print("哈哈哈").............3,打印"哈哈哈"
fn()................................4,此时的fn = func,当fn(),其实就是调用func()函数
func1(func)..........................运行结果是:"呵呵呵" "哈哈哈" "呵呵呵", .........1先调用func1
5>函数名可以当做函数的返回值, return func
列如:def func_1():
print("这里是函数1")
def func_2():
print("这里是函数2")
print("这里是函数1") #2,第二步打印"这里是函数1"
return func_2 #3返回func_2此时返回的是一个函数名(无任何意义)只是返回一个值
fn = func_1() #1,第一步:先执行函数func_1()打印"这里是函数1" ..........4,第四步此时func_2赋值给fn
fn() #5第五步,在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():
gloable name...........................把全局变量弄到到局部来引用
name = "呵呵"
print(name)
abc()
我们可以用 .__closure__来判断此函数是不是闭包
列如:def func1():
name = "alex"
def func2():
print(name) # 闭包
func2()
print(func2.__closure__) # (<cell at 0x10c2e20a8: str object at 0x10c3fc650>,)出来的是一个内存地址如果没有就是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 dir(s)).................................此时打印结果是:True,说明s是可迭代的
print(dir(s))是判断s里边的所有内容
****模拟for循环:
lst = ["皇阿玛","皇额娘","容么么","紫薇"]
it = lst.__iter__() ....................................获取迭代器
whlie 1:...................................................while循环,是把lst中的每一项都循环出来
try:........................................................尝试
name = it.__next__()..........................去拿下一项
except StopIteration................................拿不到的时候
break..............................................循环终止(只有在循环的时候才能用break)
#isinstance(对象,类型) 判断***对象是否是***类型的
print(isinstance(lst.Iterable))........................True判断是否是可迭代的,迭代器一定是可迭代的.可迭代的不一定是迭代器
print(isinstance(lst.Iterator))..........................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__()).......................开始往出拿第二项元素