python的返回函数(对象)与decorator装饰器

Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 07:18:10) [MSC v.1900 32 bit (Intel)] on win32
Type “copyright”, “credits” or “license()” for more information.

#返回函数
def lazy_sum(*args):
def sum():
ax=0
for n in args:
ax=ax+n
return ax
return sum

lazy_sum([1,2,3,4,5,6])()
Traceback (most recent call last):
File “<pyshell#4>”, line 1, in
lazy_sum([1,2,3,4,5,6])()
File “<pyshell#2>”, line 5, in sum
ax=ax+n
TypeError: unsupported operand type(s) for +: ‘int’ and ‘list’

lazy_sum(1,2,3,4,5,6)
<function lazy_sum..sum at 0x037C28E8>

lazy_sum(1,2,3,4,5,6)()
21

#可以看到返回值是函数,只有调用这个函数,才会进行求和运算。
。。。。。。。

###多重循环的顺序

for i in (1,2,3,4,5,6):
print (“r”)
for k in (“a”,“b”,“c”):
print (k)

r
a
b
c
r
a
b
c
r
a
b
c
r
a
b
c
r
a
b
c
r
a
b
c

per={}
vec=[(“character_A”,[“A1”,“A2”,“A3”]), (“character_B”,[“B1”,“B2”,“B3”])]
for name in vec:
per[name[0]] = {}
for value in name[1]:
print (value)

A1
A2
A3
B1
B2
B3

#返回函数
def lazy_sum(*args):
def sum():
ax=0
for n in args:
ax=ax+n
return ax
return sum

lazy_sum([1,2,3,4,5,6])
<function lazy_sum..sum at 0x03589228>

lazy_sum([1,2,3,4,5,6])()
Traceback (most recent call last):
File “<pyshell#30>”, line 1, in
lazy_sum([1,2,3,4,5,6])()
File “<pyshell#28>”, line 5, in sum
ax=ax+n
TypeError: unsupported operand type(s) for +: ‘int’ and ‘list’

lazy_sum(1,2,3,4,5,6)
<function lazy_sum..sum at 0x037C29C0>

lazy_sum(1,2,3,4,5,6)()
21

#可以看到返回值是函数,只有调用函数,才会进行求和运算。
#闭包
#返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用。

#lazy_sum函数返回了一个函数sum后,每次调用lazy_sum()函数,返回的都是一个新的函数,内部的局部变量args还被新函sum数引用。
#另一个问题是返回的函数并没有马上被执行。
def count():
fs=[]
for i in range(1,4):
def f():
return i*i
fs.append(f)
return fs

f1,f2,f3=count()
f1()
9

f2()
9

f3()
9

def count():
fs=[]
for i in range(1,4):
print (i)
def f():
return i*i
fs.append(f)
return fs

f1,f2,f3=count()
1
2
3

f1()
9

def count():
fs=[]
for i in range(1,4):
print (i)
def f():
print (“kk”)###加入一个测试。可见不动
return i*i
fs.append(f)
return fs

f1,f2,f3=count()
1
2
3

#返回是fs这个函数

#为什么f1()、f2()、f3()不是返回1、4、9,而是全部返回9?原因就在于返回的函数f()引用了变量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

f1,f2,f3=count()
f1()
1

f2()
4

f3()
9

#f(j)调用了g()。原来的是count()调用了f()

。。。。。。。。。。。。。。。。

#关键字lambda表示匿名函数,冒号前面的x表示函数参数
list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
[1, 4, 9, 16, 25, 36, 49, 64, 81]

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

#装饰器
#由于函数也是一对象,函数对象可以被赋给变量。所以通过变量也可以调用该函数。

#函数对象有一个__name__属性,可以拿到函数的名字,这应该属于面向对象的范围了。

def now():
print(‘2019-6.18’)

f=now
f()
2019-6.18

now.name
‘now’

f.name
‘now’

#假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。

def log(func):
def wrapper(*args,**kw):#分解func
print(‘call %s():’ % func.name)#增加功能
return func(*args,**kw)#调用原来函数的功能
return wrapper#打包返回新函数

#然后要借助Python的 @语法,把decorator置于函数的定义处。

@log
def now():
print(‘2019-6.18’)

now()
call now():
2019-6.18

#如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,写出来会更复杂。
def log(text):
def decorator(func):
def wrapper(*args,**kw):
print(’%s %s():’ % (text, func.name))
return func(*args,**kw)
return wrapper
return decorator

@log(‘hell0’)
def now():
print(‘2019-6.18’)

now()
hell0 now():
2019-6.18

log(‘execute’)(now)
<function log..decorator..wrapper at 0x037C2A50>

log(‘execute’)(now)()
execute wrapper():###这个费解
hell0 now():
2019-6.18

log(‘hello’)(now)
<function log..decorator..wrapper at 0x037C2AE0>

log(‘hello’)(now)()
hello wrapper():
hell0 now():
2019-6.18

#但是如上面的写法有一个问题,也就是最后的函数名称其实并不是now,而是wrapper。需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。
import functools
def log(func):
@functools.wraps(func) #保证函数还是原来的名称
def wrapper(*args,**kw):
print(‘call %s():’ % func.name)
return func(*args,**kw)
return wrapper

@log
def now():
print(‘2019-6.18’)

now()
call now():
2019-6.18

。。。。。

log(now)
<function now at 0x037C2CD8>

log(now)()
call now():#费解
call now():
2019-6.18

#或者带参数的写法
def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args,**kw):
print(’%s %s():’ % (text, func.name))
return func(*args,**kw)
return wrapper
return decorator

@log(‘hell0’)
def now():
print(‘2019-6.18’)

now()
hell0 now():
2019-6.18

log(‘execute’)(now)()
execute now():#费解
hell0 now():
2019-6.18

log(‘execute’)(now)()
execute now():
hell0 now():
2019-6.18

猜你喜欢

转载自blog.csdn.net/qq_39306047/article/details/91537536