Python与语法糖
对于python而言,所谓的语法糖的关键目的是对一串代码进行简化,对于初学者而言,接触的第一个语法糖应该是以下代码:
a,b = b,a
这个语法糖实现的是对变量的引用内容交换,如果学习了解过c语言应该知道,如果希望在c语言的情况下进行交换,需要声明第三个变量:
int a =5;
int b = 5;
//开始交换
int c;
c = a;
a=b;
b=c;
//实现交换
其实,对于python而言,Python的a, b = b, a 通过元组打包和解包实现,等价于 temp = (b, a); a = temp[0]; b = temp[1],但无需用户手动处理临时变量
为了简化代码实现pythonic,所以提供语法糖来简化代码。
装饰器
对于python中可能最实用的语法糖要属装饰器了。
装饰器出现的根本目的是为了实现在不修改原来函数的代码情况下,为函数增加功能,这样的好处是对于公司来说可以方便管理以及实现代码复用。
闭包
在理解装饰器前,首先要了解什么是函数的闭包。
def out_func(a):
def in_func():
print('a')
return in_func
上面代码就是一个闭包实例,其实闭包的根本逻辑是,python的名与地址的关系,在之前的博客中讲解过,变量名与地址的关系,其实函数也可以认为是一个“变量”。因为,函数也是把函数逻辑存储在内存中,调用逻辑需要一个地址去指向这个内存存储空间。
函数名与地址的关系
def print_hello_world():
print("hello world")
a = print_hello_world
a()
#打印hello world
之前讲解过,python的引用机制,这里的逻辑其实还是一样,依赖于引用机制,让变量a也可以引用这个函数。然后通过a()来实现对函数的调用。
nonlocal关键字
对于闭包中变量的作用域,Python提供了nonlocal关键字来解决内部函数访问外部变量的问题。
def out_func(a):
def in_func():
nonlocal a
print(a)
a = 5
print(a)
return in_func
func = out_func(2)
func()
#打印2 5
装饰器的实现
def out_func(func):
def in_func():
print('hello---我是被增加的功能')
func()
return in_func
@out_func
def print_hello_world():
print("hello world")
if __name__ == '__main__':
print_hello_world()
#打印
#hello---我是被增加的功能
#hello world
这里的装饰器其实是在定义的函数的下一行加入了一个代码,也就是说有以下等价形式:
@out_func
def print_hello_world():
print("hello world")
def print_hello_world():
print("hello world")
print_hello_world = out_func(print_hello_world)
类装饰器
除了函数装饰器,还可以使用类来实现装饰器:
class add_func:
def __init__(self,func):
self.func = func
def __call__(self, *args, **kwds):
print("__call__被调用")
self.func()
@add_func
def print_hello_world():
print("hello world")
if __name__ == '__main__':
print_hello_world()
装饰器工厂
装饰器工厂可以接收参数,增加装饰器的灵活性:
def layer_1_func(b):
def layer_2_func(func):
def layer_3_func():
print('我是layer3',b)
func()
return layer_3_func
return layer_2_func
@layer_1_func(1)
def print_hello_world():
print("hello world")
if __name__ == "__main__":
print_hello_world()
#打印
#我是layer3 1
#hello world
多层装饰器
def out_func_1(func):
print('1111')
def in_func_1():
print('4444')
func()
return in_func_1
def out_func_2(func):
print('2222')
def in_func_2():
print('3333')
func()
return in_func_2
@out_func_2
@out_func_1
def print_run():
print('5555')
if __name__ == '__main__':
print_run()
#打印
#1111
#2222
#3333
#4444
#5555
with上下文管理
另一个比较常见的语法糖就是with上下文管理工具,其实还是比较简单,就是调用了两个魔术方法,或者通过装饰器利用yield特性实现。
class with_func:
def __init__(self):
pass
def __enter__(self):
print('frist use')
def __exit__(self,exc_type,exc_val,exc_tb):
print("third use")
with with_func():
print("second use")
#打印
#frist use
#second use
#third use
通过利用yield也可以实现这个功能:
from contextlib import contextmanager
@contextmanager
def with_func():
print('frist use')
yield
print('third use')
with with_func():
print("second use")