小结Python中的元类Metaclass

关于metaclass,不用把它想的很复杂,只要和函数的装饰器做类比就好。通俗的说,装饰器是对函数参数的预处理,metaclass是对类属性的预处理。
下面拿一段代码来做解释:

1
2
3
4
5
6
7
8
9
10
11
12
13
class UpperAttrMetaClass(type): # to uppercase all attrs
def __new__(mcs, class_name, class_parents, class_attr):
attrs = {name if name.startswith('__') else name.upper(): value for name, value in class_attr.items()}
return super().__new__(mcs, class_name, class_parents, attrs)

class Base(metaclass=UpperAttrMetaClass):
bar = 1
def __init__(self, params):
super().__init__()
self.params = params
base = Base(1)
print(base.BAR)
print(base.bar)

这个UpperAttrMetaClass的功能就是把目标类中的所有类属性(不包含__开头的)全部转换为大写。

执行上面的代码,可以看到最后访问base.BAR会返回1,访问base.bar会报错。
就是这么简单!
另外多说一句,上述代码是在python3以上执行的,如果是python2,需要这么写:

1
2
3
4
5
6
class Base():
__metaclass__ = UpperAttrMetaClass
bar = 1
def __init__(self, params):
super(Base,self).__init__()
self.params = params

可以对比下区别,如果想兼容python2,python3的metaclass写法,需要引入six库,将上面两种写法合并为

1
2
3
import six
class Base(six.with_metaclass(UpperAttrMetaClass)):
# todo

参考链接
https://stackoverflow.com/questions/49066476/python-metaclass-pass-init-params