python学习记录六
返回函数
def calc_sum(*args): ax = 0 for n in args: ax = ax + n return ax
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
返回的不是求和结果,而实求和函数
>>> f = lazy_sum(1,3,5,7,9) >>> f <function lazy_sum.<locals>.sum at 0x101c6ed90> >>> f() 25
当我们调用lazy_sum()
时,每次调用都会返回一个新的函数,即使传入相同的参数:
>>> f1 = lazy_sum(1, 3, 5, 7, 9) >>> f2 = lazy_sum(1, 3, 5, 7, 9) >>> f1==f2 False
f1()
和f2()
的调用结果互不影响。
def count(): fs = [] for i in range(1, 4): def f(): return i*i fs.append(f) return fs f1, f2, f3 = count() 在上面的例子中,每次循环,都创建了一个新的函数,然后,把创建的3个函数都返回了。 你可能认为调用f1(),f2()和f3()结果应该是1,4,9,但实际结果是: >>> f1() 9 >>> f2() 9 >>> f3() 9 全部都是9!原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9。 返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
可以这么写试试
def count():
def f(j):
def g():
return j*j
return g
fs = []
for i in range(1, 4):
fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
return fs
匿名函数
>>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])) [1, 4, 9, 16, 25, 36, 49, 64, 81] 我们可以看出 lambda x: x * x 实际上都是: def f(x) return x * x
关键字lambda
表示匿名函数,冒号前面的x
表示函数参数。
匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:
装饰器
由于函数也是一个对象 而且函数对象可以被赋值给变量 通过变量也可以调用函数
>>> def now(): ... print('2015-3-25') ... >>> f = now >>> f() 2015-3-25
函数对象有一个__name__
属性,可以拿到函数的名字:
>>> now.__name__
'now'
>>> f.__name__
'now'
偏函数
int()函数还提供额外的base参数 默认值为10,如果传入base参数,就可以做进制的转换
>>> int('12345', base=8) 5349 >>> int('12345', 16) 74565
def int2(x, base=2): return int(x, base)
那么转换二进制就非常方便了
>>> int2('1000000')
64
>>> int2('1010101')
85
>>>functools.partial 就是帮助我们创建一个偏函数的,不需要我们自己定义int2() 可以直接使用下面的代码创建一个新的函数int2: >>>import functools >>>int2 = functools.partial(int,base=2) >>>int2('1000000') 64 >>>int2('1010101') 85 简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
作用域
正常的函数和变量名是公开的(public),可以被直接引用,比如:abc
,x123
,PI
等;
类似__xxx__
这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的__author__
,__name__
就是特殊变量,hello
模块定义的文档注释也可以用特殊变量__doc__
访问,我们自己的变量一般不要用这种变量名;
类似_xxx
和__xxx
这样的函数或变量就是非公开的(private),不应该被直接引用,比如_abc
,__abc
等;
之所以我们说,private函数和变量“不应该”被直接引用,而不是“不能”被直接引用,是因为Python并没有一种方法可以完全限制访问private函数或变量,但是,从编程习惯上不应该引用private函数或变量。