python装饰器及魔法函数
一. 装饰器
python的装饰器其实就是在某个函数外面再嵌套一个函数,用以达到增强该函数功能的效果。其实就是套娃。
特点:
- 装饰器输入参数:函数
- 装饰器输出:函数
- 装饰器能使代码使用上更加简洁
比如下面的例子:
def wrapper(f):
def a(*args, **kwargs):
print(*args, **kwargs)
f(*args, **kwargs)
return a
# 1. 未使用装饰器情况下
def call(name):
print(f'name:{name}')
wrapper(call('张三'))
# 2. 使用装饰器
@wrapper
def call(name):
print(f'name:{name}')
call('张三')
1.1 classmethod装饰器
一般来说,使用一个类的方法,必须先实例化该类,再调用方法。但是@staticmethod则可以直接使用类名.方法()。
特点:
- 方法内部参数不能有self。
- 类的其他方法调用本方法需要加入self.方法()
- 在方法内部调用类其他属性为 类名.属性,调用方法则需要先实例化。
class A:
c = 'c'
@staticmethod
def a(a = 1):
print(a)
print(A.c)
A().cc() # 需要实例化
def b(self):
self.a() # 正常调用
def cc(self):
print(self.c)
A.a() # 不用实例,即可外部调用
1.2 classmethod装饰器
和staticmethod一样,可以不需要实例,直接直接使用类名.方法()。
特点:
- classmethod没有类实例化对象的self参数,而是指代类本身的cls参数。
- 类的其他方法调用本方法需要加入self.方法()
- 在方法内部调用类其他属性为 cls.属性,调用方法则需要先实例化 cls.方法()。
class A:
c = 'c'
@classmethod
def a(cls,a = 1):
print(a)
print(cls.c)
cls().cc() # 需要实例化
def b(self):
self.a() # 正常调用
def cc(self):
print(self.c)
A.a()
1.3 property 装饰器
作用: 修饰方法,将方法当作类的只读属性一样访问,能防止属性被修改。
class A:
aaa = 1
@property
def a(self):
return self.aaa
def b(self):
return self.aaa
a = A()
print(a.a)
print(a.b())
二. 魔法函数
2.1 __new__函数
场景:一般需要使用单例模式下(比如数据库连接等),需要确保只有单个对象被创建情况下,都需要用到new函数
class A:
_instance = None
def __new__(cls, *args, **kwargs):
print('__new__')
# 单例模式下,先判断是否存在实例,没有则创建
if cls._instance is None:
cls._instance = object.__new__(cls)
return cls._instance
def __init__(self):
print('__init__')
# 仅允许一个实例被创建,就算创建其他实例,本质指向的还是同一个实例
a = A()
b = A() # a ==> b
# 打印结果:先是 __new__ 后是__init__。说明new是在实例创建之前,而init则是在实例创建之后
2.2 __call__函数
场景:将一个类当作一个函数进行使用,在流水线式的数据处理时可以更好的进行封装。
class A:
def __call__(self, *args, **kwargs):
return self.compute(*args, **kwargs)
def a1(self,a,b):
return a + b
def a2(self,a,b):
return a * b
def compute(self,a,b,c):
return self.a1(a,c) + self.a2(a,b)
a = A()
rs = a(1,2,3) # 首先需要实例化,之后可以直接像函数一样使用
2.3 属性操作__add__
场景: 需要对2个实例进行运算操作时
class A:
def __init__(self, a) :
self.a = a
def __add__(self, other_a):
return self.a + other_a.a
a1 = A(1)
a2 = A(2)
aa = a1 + a2