python2.7 模块全局__metaclass__

2019-04-14 18:25发布

metaclass概述

metaclass 像一个魔法盒,可以动态修改python 类对象 的属性及方法等。没错,我这里暂且称之为类对象, 因为它以对象的方式来表示一个类(比如 class Myclass:pass);在python中,一切皆对象。 本文主要介绍在python2.7的环境下,如何增加模块级的__metaclass__。 对于不清楚metaclass的同学,可以参考这篇文章:
深刻理解 Python 中的元类(metaclass)

采用函数方法增加模块metaclass

代码如下: # metaclass函数 def upper(cls_name, cls_parents, cls_attr): """ Make all class attributes uppper case """ attrs = ((name, value) for name, value in cls_attr.items() if not name.startswith('__')) upper_atts = dict((name.upper(), value) for name, value in attrs) return type(cls_name, cls_parents, upper_atts) __metaclass__ = upper #module level class Foo: foo = 1 class Bar: bar = 1 此时,Foo类中的的foo属性变成了Foo,Bar类中的的bar属性变成了BAR。如果只需要对某个类增加metaclass属性,则只需要在该类中增加 metaclass = upper。 注意:在python3.5中,不支持这种方式来定论模块metaclass属性。

采用OPP方式增加模块metaclass

一开始开心地以为可以直接采用类似函数的方式来实现模块级metaclass,代码如下: class UpperAttrMetaclass(type): def __new__(cls, name, bases, dct): attrs = ((name, value) for name, value in dct.items() if not name.startswith('__')) uppercase_attr = dict((name.upper(), value) for name, value in attrs) return super(UpperAttrMetaclass, cls).__new__(cls, name, bases, uppercase_attr) __metaclass__ = UpperAttrMetaclass class Foo(object): foo = 1 def __init__(self, foo1): self.foo1 = foo1 此时还高兴的以为Foo增加了metaclass属性,将foo属性变成了FOO; 而实际上并没有。多么痛的领悟啊!那怎么办呢?经过各种查,找到了一个解决方法,可以采用继承的方式来实现metaclass属性,而且这各方式还可以灵活的选择所要继承的metaclass
代码如下: class UpperAttrMetaclass(type): def __new__(cls, name, bases, dct): attrs = ((name, value) for name, value in dct.items() if not name.startswith('__')) uppercase_attr = dict((name.upper(), value) for name, value in attrs) return super(UpperAttrMetaclass, cls).__new__(cls, name, bases, uppercase_attr) class Up(object): __metaclass__ = UpperAttrMetaclass class Foo(Up): foo = 1 def __init__(self, foo1): self.foo1 = foo1 该方法可以解决python3.5中不支持 函数式metaclass 的问题 也许还有更好的方法,望大神们指正与探讨!!!