技术交流QQ群:1027579432,欢迎你的加入!
- 元编程:是编写出可以操作的代码的行为,即用代码来操作另一个代码。
- Python中的元编程:一种构建函数和类的行为,这些函数和类可以通过修改、包装现有代码或生成代码来进行操纵。
- Python中元学习的实现方法:
- 装饰器
- 元类
1.装饰器
- 装饰器是一种不用修改原始代码结构来为现有函数增加新的功能的一种方法。
- 请看下面的几个函数实例:
def add(x, y): return x + y def sub(x, y): return x - y def mul(x, y): return x * y
- 需求:现在为上面的三个函数各自增加一条打印语句,我们需要在每个函数体的内部重复执行增加语句操作。
def add(x, y): print("add is called with parameter {0},{1}".format(x,y)) return x + y def sub(x, y): print("sub is called with parameter {0},{1}".format(x,y)) return x - y def mul(x, y): print("mul is called with parameter {0},{1}".format(x,y)) return x * y
- 上面的实现方法虽然可以,但是过程太过于繁琐。有没有什么比较好的方法可以来实现?我们可以通过写一个装饰器函数来实现,而不用直接对原始函数的函数体部分进行直接修改。
def my_decorator(func): def wrapper_function(*args): print("{0} is called with parameter {1}".format(func.__name__,args)) return func(*args) return wrapper_function @my_decorator def add(x,y): return x + y @my_decorator def sub(x,y): return x - y @my_decorator def mul(x,y): return x * y
- 上面的my_decorator就是一个装饰器函数,我们使用@my_decorator来对三个函数进行装饰。同时,我们也不需要对原有的三个函数的函数体进行直接的修改。
- 因此,装饰器是一个更高级别的函数,它将一个函数作为参数然后返回另外一个参数。正如上例所示,my_decorator从外界接收一个函数(即func),然后返回一个wrapper_function函数作为返回值。注意,需要在函数wrapper_function中增加打印的功能。
2.元类
在Python中,元类是一种特殊类型的类,它与普通的类是不同的。一般,在普通类中会定义它自己实例的行为,而一个元类不仅可以定义一个普通类的行为也可以它自己实例的行为。
-
一个元类可以给一个普通类增加或删除一个方法或者属性,在python中有一个特殊的元类即type,所有自定义的类都是从type类中继承出来的。例如,你已经定义了一个Calc类,该类具有三个方法,如下所示。我们想要通过元类的方式给三个已有方法增加调试功能,具体可进行如下操作:
class Calc(): def add(self, x, y): return x + y def sub(self, x, y): return x - y def mul(self, x, y): return x * y
-
首先,我们需要创建一个元类MetaClassDebug,该类具有代码调试功能的方法,同时让Calc继承自MetaClassDebug。然后,我们可以调用来自Calc类的所有方法,它将与我们定义好的debug_function方法联系在一起。
def debug_function(func): def wrapper(*args, **kwargs): print("{0} is called with parameter {1}".format(func.__qualname__, args[1:])) return func(*args, **kwargs) return wrapper def debug_all_methods(cls): for key, val in vars(cls).items(): if callable(val): setattr(cls, key, debug_function(val)) return cls class MetaClassDebug(type): def __new__(cls, clsname, bases, clsdict): obj = super().__new__(cls, clsname, bases, clsdict) obj = debug_all_methods(obj) return obj class Calc(MetaClassDebug): def add(x,y): return x + y def sub(x,y): return x - y def mul(x,y): return x * y calc = Calc() print(calc.add(2, 3)) print(calc.sub(2, 3)) print(calc.mul(2, 3))