1.函数
题外话:列表生成式中元素对象可以是函数返回值、类实例化对象
正题开始
[ callable(i) for i in (str, 11, int)]
判断对象是否能调用,callable() 函数
结论: 具体值不能,类型则可以
2.用户定义的可调用类型
任何Python对象都可以表现得像函数,为此,只需实现实例方法 call
class Test(object):
def __init__(self, item):
self.item = list(item)
def __call__(self, *args, **kwargs):
return self.post()
def get(self):
return self.item.pop()
def post(self):
return 'hello'
obj = Test('123')
print(obj.get())
print(obj())
输出为 3 hello
由此,我们可以断定将对象当函数调用,默认会调用其 __call__ 方法
__call__ 函数实现了可调用对象协议
3.小知识
from functools import reduce
from operator import mul
reduce(mul, range(x, y+1))
实现 x到y的阶乘, mul代替了匿名函数
all([],{},[]) all函数,参数为空列表,元组,字典等返回 True
4.装饰器基础知识
简介
装饰器是可调用对象,其参数是另一个函数(被装饰的函数)
本质是函数的替换
代码展示
def hello(func):
print(func())
@hello
def tar():
return ('no')
输出为 no
函数上加 @hello == hello(tar) ; 装饰器的参数为函数名
再次展示
def hello(func):
print('hello')
@hello
def tar():
print('hi')
输出为 hello ,此时输出装饰器返回值
def hello(func):
def inner():
print('hello')
return inner
@hello
def tar():
print('hi')
tar()
输出为 hello
装饰器内封装函数实现的是对原函数的替换
装饰器内有函数则需调用-->tar()
装饰器的两大特性:
能把被装饰的函数替换成可调用对象或其他函数;
装饰器在加载模块时立即执行
5.变量作用域规则
Python规定在函数体内定义的变量为局部变量,函数体外为全局变量
要在函数体内修改全局变量值则需要用 global 关键字,不使用会报错
b = 6 声明全局变量
def f(a):
global b
print(a)
print(b)
b = 9 修改全局变量
f(3)
此时已完成修改
f(3)
输出为 3 6 3 9
函数调用一次后完成修改
第一次输出还未修改 b ;第二次已完成修改
6.闭包
闭包指延伸了作用域的函数,通常适用于嵌套函数
闭包实现
def make_av():
s = []
def aver(value):
s.append(value)
total = sum(s)
return total/len(s)
return aver
obj = make_av()
print(obj(10))
print(obj(12))
输出为 10 11
实质:子函数调用父函数的变量 s
那么如果要修改 s 的值呢,我们用 nonlocal 关键字实现
def make():
count = 0
total = 0
def aver(new):
nonlocal count, total
count += 1
total += new
return total / count
return aver
obj = make()
print(obj(10))
输出为 10
不使用此关键字会报错(局部变量与全局变量)
实质:变量在嵌套函数内的定义。
nonlocal 使内层函数可以调/使用外层函数的变量
而 global 可以在函数内部使用全局变量
7.functools.lru_cache缓存
功能:相同的计算做缓存,避免浪费时间
多用于迭代算法上,能节约很多时间
使用方法: @functools.lru_cache() 实现装饰
要求: 此装饰器实现字典存储结果,所以其参数必须可散列
8.参数化装饰器
创建一个装饰器工厂函数-----将真正的装饰器封装在此函数内
series = set()
def register(active=True):
def decore(func):
if active:
series.add(func)
else:
series.discard(func)
return func
return decore
@register()
def f1():
print('hi')
@register(active=False)
def f2():
print(series)
f2()
注意:此工厂函数必须作为函数调用
当我们在外面调用 f2()时,才会触发执行被修饰的函数 f2(),否则不执行
但真正装饰器 decore() 函数一定会执行