赞
踩
函数名是⼀个变量,但它是⼀个特殊的变量。与括号配合可以执⾏函数的变量
1. 做变量
def func():
print('呵呵')
a = func # 把函数当成变量赋值给另外一个变量
a() # 通过变量a调用函数
2. 做容器元素
def func1():
print('func1')
def func2():
print('func2')
def func3():
print('func3')
def func4():
print('func4')
list1 = [func1, func2, func3, func4]
for i in list1:
i()
3. 做参
def func1():
print('func1')
def func2(arg):
print('start')
arg() # 执行传递进来的arg
print('end')
func2(func1) # 把func1当成参数传递给func2
4. 做返回值
def func1():
print('这里是func1')
def func2():
print('这里是func2')
return func2 # 把func2当成返回值返回
ret = func1() # 调用func1,把返回值赋值给ret
ret() # 调用ret
**1、定义:**一个内层函数中,引用了外层函数(非全局)的变量,这个内层函数就可以成为闭包。在Python中,我们可以使用__closure__来检测函数是否是闭包。
2、例子:
def print_msg(msg):
# 这是外层函数
def printer():
# 这是内层函数
print(msg)
return printer # 返回内层函数
func = print_msg("Hello") #返回printer变量
func() #实际上执行是printer()函数
现在我们进行如下操作:
>>> del print_msg
>>> func()
Hello
>>> print_msg("Hello")
Traceback (most recent call last):
...
NameError: name 'print_msg' is not defined
总结:
如果⼀个函数执⾏完毕,则这个函数中的变量以及局部命名空间中的内容都将会被销毁。在闭包中内部函数会引用外层函数的变量,而且这个变量将不会随着外层函数的结束而销毁,它会在内存中保留。也就是说,闭包函数可以保留其用到的变量的引用。
1、开放封闭原则是指对扩展代码的功能是开放的,但是对修改源代码是封闭的。这样的软件设计思路可以保证我们更好的开发和维护我们的代码。
2、利用闭包解释装饰器:
def c():
print('11111111')
def a(func):
def b():
print('aaaa')
func()
return b
c = a(c) # 运行步骤:a(c)=>func()=c() =>返回值赋值 c=b
c() #实际运行 b()=>打印aaa=>运行c()=>打印1111111
3、装饰器规范写法如下:
def a(func):
def b():
print(1111')
func()
return b
@a # 装饰器语法
def c():
print('cccccc!')
# 调用被装饰函数
c()
4、带参数的装饰器
def f1(func): # f1是我们定义的装饰器函数,func是被装饰的函数
def f2(*arg, **kwargs): # *args和**kwargs是被装饰函数的参数
func(*arg, **kwargs)
return f2
5、装饰器修复技术
**(1)**被装饰的函数最终都会失去本来的__doc__等信息, Python给我们提供了一个修复被装饰函数的工具。在装饰器内部加入 @wraps(func)进行修复
(2)例子:
def a(func):
@wraps(func) #可以将这个除去试试
def b():
print('洒点水')
func()
return b
@a # 装饰器语法糖
def create_people():
"""这是一个女娲造人的功能函数"""
print('女娲真厉害,捏个泥吹口气就成了人!')
create_people()
print(create_people.__doc__)
print(create_people.__name__)
6、多个装饰器修饰一个函数执行顺序为从下至上
7、类装饰器:
(1)基础知识:__init__和__call__分别为类中的初始函数和直接调用函数,都属于魔法函数(python内置的)
(2)实例:
class D(object): def __init__(self, a=None): #初始函数,调用类首先执行这个函数 self.a = a self.mode = "装饰" def __call__(self, *args, **kwargs): if self.mode == "装饰": self.func = args[0] # 默认第一个参数是被装饰的函数 self.mode = "调用" return self # 当self.mode == "调用"时,执行下面的代码(也就是调用使用类装饰的函数时执行) if self.a: print("欢迎来到{}页面。".format(self.a)) else: print("欢迎来到首页。") self.func(*args, **kwargs) @D() def index(name): print("Hello {}.".format(name)) if __name__ == '__main__': index('张三') #调用时调用类中的__call__函数
8、property属性方法
(1)我们把类中的一个只读属性定义为property属性方法,只有在访问它时才参与计算,一旦访问了该属性,我们就把这个值缓存起来,下次再访问的时候无需重新计算。
(2)例子:
class lazyproperty: def __init__(self, func): self.func = func def __get__(self, instance, owner): if instance is None: return self else: value = self.func(instance) setattr(instance, self.func.__name__, value) return value import math class Circle: def __init__(self, radius): self.radius = radius @lazyproperty def area(self): print('计算面积') return math.pi * self.radius ** 2 c1 = Circle(10) print(c1.area) print(c1.area)#执行这个会发现这一步只返回了值,没有重新执行函数。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。