这是一个我多次试图回避的问题,但在最近的一个项目中,我最终还是无法回避这个问题。我尝试了各种解决方案,并决定使用其中之一,并愿意与您分享。互联网上的许多解决方案根本不起作用,我认为它可以帮助那些不太流利的人学习类和元类。你知道吗
我有类的层次结构,每个类都有一些在实例化对象时需要读取的类变量。但是,如果这些变量的格式为__variable
,则它们的名称将被覆盖或损坏。我可以很好地处理被损坏的变量,但是我不知道,绝对肯定地说,我应该在我的对象的名称空间中查找哪个属性。下面是我的定义,包括类变量。你知道吗
class BasicObject(object):
__attrs = 'size, quality'
...
class BasicDBObject(BasicObject):
__attrs = 'db, cursor'
...
class DbObject(BasicDBObject):
__attrs = 'base'
...
class Splits(DbObject):
__attrs = 'table'
...
我想在实例化Splits
类时收集每个类的__attrs
中存储的所有值。方法__init__()
只在类BasicObject
中定义,其他地方没有定义。不过,我需要扫描self.__dict__
以查找损坏的__attrs
属性。由于其他属性在这些对象中具有模式attrs
,因此我无法筛选出字典中所有具有模式__attrs
的内容!因此,我需要收集对象的类层次结构,并搜索所有这些类的损坏属性。你知道吗
因此,我将使用metaclass
来捕获每个类,这些类调用在加载模块时遇到class
定义时正在执行的__new__()
方法。通过在基类中定义我自己的__new__()
方法,我将能够在实例化每个类时捕获类(实例化class
,而不是对象实例化)。你知道吗
代码如下:
import collections
class BasicObject(object) :
class __metaclass__(type) :
__parents__ = collections.defaultdict(list)
def __new__(cls, name, bases, dct) :
klass = type.__new__(cls, name, bases, dct)
mro = klass.mro()
for base in mro[1:-1] :
cls.__parents__[name] = mro[1]
return klass
def __init__(self, *args, **kargs) :
"""
Super class initializer.
"""
this_name = self.__class__.__name__
parents = self.__metaclass__.__parents__
hierarchy = [self.__class__]
while this_name in parents :
try :
father = parents[this_name]
this_name = father.__name__
hierarchy.append(father)
except :
break
print(hierarchy)
...
我可以使用类定义获得访问属性,但是所有这些类都是在三个不同的模块中定义的,主模块(init.py
)对其他模块一无所知。你知道吗
这段代码在Python2.7中运行良好,也应该在Python3中运行。。但是,python3。有一些新特性,可能有助于为这种自省编写更简单的代码,但我还没有时间在python3.0中研究它。你知道吗
我希望这个简短的解释和例子能为您节省一些宝贵的时间:-)
是的,问题就是答案;只是因为我在网站上找不到除了“提问”按钮之外的任何东西。我错过什么了吗?你知道吗
相关问题 更多 >
编程相关推荐