python中,定义了一些有用的特性帮助编程人员丰富功能的处理过程
装饰器
在 类设计思想中 有一条开闭原则 “对扩展开放,对修改关闭”。 在前面的内容中,我们已经讨论过一些 python对于封装特性的处理。 这里的装饰器就是用于对已定义类进行功能扩展的一种方法。
如property 通过为方法装饰property,可以将方法伪装成属性调用,而不是直接对类中的属性进行操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class person : def __init__(self,name): self.__name = name
@property def name(self): return self.__name @name.setter def name(self,name): self.__name = name preson1 = person("wang") print(preson1.name)
preson1.name = "zhao" print(preson1.name)
|
由这个例子可以看出,通过@property ,并未对原始类进行修改,但是对它最终行为产生了影响
如何定义一个装饰器
装饰器的本质是定义一个函数 接收一个函数作为参数, 并在函数内部再定义一个函数,将接收进来的参数在该函数内执行,最终返回该函数
因为之前讨论过 “__call__” 方法在接收参数这方面和函数一致,所以有两种定义方法
装饰器的基础定义 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| def add_hello(func): def wapper(*args ,**kwargs) : print("hello user") func(*args ,**kwargs) print("goodbye user") return wapper
@add_hello def base_function(parameter): print(f"this is a parmeter {parameter}") print("this is a base function")
base_function("hello")
|
扩展1 : 装饰器本身也可以接收参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| def add(*outter_args,**outter_kwargs): def add_hello(func): def wapper(*args ,**kwargs) : print(outter_args[0]) print("hello user") func(*args ,**kwargs) print("goodbye user") return wapper return add_hello
@add("hi") def base_function(parameter): print(f"this is a parmeter {parameter}") print("this is a base function")
base_function("hello")
|
扩展2:装饰器装饰在类上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| def add(*outter_args,**outter_kwargs): def add_hello(func): def wapper(*args ,**kwargs) : print(outter_args[0]) print("hello user") m = func(*args ,**kwargs) print("goodbye user") return m return wapper return add_hello
@add("hi") class person : def __init__(self): print("class person is on initing") pass def __call__(self,message): print(message)
p = person() p("hello")
|
装饰器是一种语法糖,其本质是通过多层嵌套函数实现的运行时函数增强机制。
顺序是 定义函数传入装饰器参数-定义函数传入函数-定义函数传入原函数参数-定义函数传入原函数。然后再逐层返回,另外就是用到了python的作用域机制,即定义的内部函数对外部的局部变量是可以访问的
扩展3 :使用类定义装饰器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class add : def __init__(self,name): self.name = name def __call__(self,func): def wapper(*args,**kwargs): print(self.name) print("hello user") func(*args) print("goodby user") return wapper
@add("codfish") def base_function(parameter): print(f"this is a parmeter {parameter}") print("this is a base function")
base_function("base_parameter")
|
可以看到以类作为装饰器的大体逻辑是一致的 无非就是 函数和参数传入位置发生了变化
迭代器
迭代器是一种让创建的实例获得如列表或者元组等结构一样,允许使用for 循环遍历整个数据结构中的元素的特性。其本质是通过实现两个魔术方法实现的 “__iter__” 和 “__next__”
“__iter__” 会返回一个可迭代对象
“__next__” 则是会获取可迭代对象中的下一个值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class num_group : def __init__(self): self.num = 0
def __iter__(self): return self def __next__(self): self.num+=1 if self.num > 10 : raise StopIteration return self.num
a = num_group() print(next(a)) for i in a: print(i)
|
生成器
与 通过列表中查询数据不同,Python 还提供了一个组件 yield来生成数据。
在一个函数中定义了yield关键字后,该函数被称为生成器。
当执行到该函数时,会返回一个生成器对象。这个生成器对象会保留其执行所使用的栈帧结构。
当运行到yield关键字时,会将值返回,生成器对象暂停,并完整保留当前的执行状态。当生成器对象的代码执行完毕后,生成器对象会退出等待GC回收。
1 2 3 4 5 6 7 8 9 10 11
| def count(num=0): while True : yield num if num > 10 : return 100 num+=1 b = count()
for i in b : print(i)
|
内建的作用域设置函数 setattr,getattr,delattr
在python中命名空间决定了一个对象都可以访问哪些对象,而通过setattr,getattr和delattr 可以直接对对象的命名空间进行操作,来修改对象的访问权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class person: def __init__(self,name): self.name = name
delattr(person,"__init__") someone = person()
class person: pass
def __init__(self,name): self.name = name setattr(person,"__init__",__init__) c = person("wang") print(c.name)
|
从这里我们可以看出 python中的类和方法的关系是松散绑定的。
并且还是实时的
1 2 3 4 5 6 7 8
| class person: pass person1 = person("wang") def __init__(self,name): self.name = name setattr(person,"__init__",__init__) person2 = person("wang") print(c.name)
|
由此我们也可以看出python 在执行阶段是逐行解释的
利用这个特性,可以对python的代码进行流程控制等操作