稀有猿诉

十年磨一剑,历炼出锋芒,说话千百句,不如码二行。

Metaprogramming in Python

元编程是一种编写生成或者处理程序代码的技术,Python语言也支持元编程,今天就来好好的学习一下。我们先了解元编程的概念,然后再深入探讨在Python中如何实现元编程。

什么是元编程

元编程Metaprogramming就是编写元程序(Metaprograms)的过程。而元程序则是用于生成程序,或者处理的程序的程序。通俗一点的理来理解,元编程就是编写生成代码的代码。程序的处理对象一般是数据,比如从用户处得到输出数据,经过业务逻辑处理,再把输出数据反馈给用户,这是绝大多数程序所做的事情。而元程序处理的对象则是程序,编写元程序的过程就叫做元编程。

元程序的优势,或者我们元编程的目的在于复用和减少代码量,而且是用一种非常优雅的方式。

这么说确实比较抽象,其实元编程没那么复杂,甚至平时都或多或少的已经用到元编程了。比如像C/C++中的宏和模板函数,Java中的泛型,注解,反向和动态代理,代码模板(模板容易混淆,这里指的是boilerplate codes)等等,这些本质上都是元编程。

参考资料

在大Python中,实现元编程的方式主要是通过装饰器Decorators和元类Metaclasses。

装饰器Decorators

理解Decorator

Decorator本质上是高阶函数,最常用的就是用来修饰一个函数,形式上是一个@my_decorator加在一个函数定义的上面,如:

1
2
3
@my_decorator
def say_hello():
  print('Hello, world')

它等同于:

1
2
3
def say_hello():
  print('Hello, world')
my_decorator(say_hello)

Decorator是一个函数,它的输入参数是被修饰的函数,此例中即sya_hello。

Python的函数是一级对象,可以赋给变量,可以当作参数和返回值,而以函数为参数或者返回值的函数称为高阶函数。装饰器本质上就是一个高阶函数,只不过,以一种更为简洁的方式来书写@my_decorator。所以再次看到@时,不用害怕,把它看成高阶函数调用即可。

自定义Decorator

装饰器本质上就是高阶函数,它的输入是一个函数,所以定义一个高阶函数,即可当作decorator使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def my_decorator(func):
  def wrapper():
      print('Before func is called')
      func()
      print('After func is called')
  return wrapper

@my_decorator
def say_hello():
  print('Hello, world')

say_hello()
#Output:
#Before func is called
#Hello, world
#After func is called

这就实现了一个非常简单的自定义decorator。

装饰器的作用

装饰器就是高阶函数,所以通常用于对函数产生一些副作用,比如打印日志,性能测试等等,其与设计模式中装饰模式的思想是一致的,通俗来理解就是套娃。

模块functools定义了很多高阶函数,都可以直接当作decorator使用。用好Decorator可以写出很简洁和易于维护的代码。

参考资料

元类Metaclasses

Decorator可以非常方便的修饰一个函数,但如果我们有很多个方法(属于类的函数,称为方法),难道要一个一个的去添加@吗?或者想对类的属性也搞些操作,咋办?如果是一个类,倒也可以手动加一加,如果想给整个类的继承体系内的所有类都施加某种副作用影响呢?这时就会用到Metaclasses。

Metaclasses可以理解为类的基类,也就是用于定义每个类(class)时使用的类,Metaclass中可以定义一些高阶函数用于在创建对象时,实始化对象时,调用属性时和调用方法时施加副作用影响。可以在定义类的时候通过metaclasses来指定使用的Metaclasses,并且会在继承体系中得到继承。

Metaclasses可以对类施加一些额外影响,比如说Python并非强OO的,像abstract没有直接的支持,这时就可以用Metaclasses来定义额外的限制,比如当基类是abstract时,如果子类没有实现一些abstract方法,就报错等等。

参考资料

参考资料

Comments