如何在没有实例化的情况下复制类属性



我正在尝试将类属性从一个类复制到另一个类

d = {1:'one', 2:'two'}
class X(object):
    a = 1
    b = 2

我需要定义y类,以使以下内容为真: assert Y.a =='one' and Y.b=='two'

实现这一目标的一种方法是:

attrDict = {attr:d[getattr(X,attr)] for attr in dir(X) if isinstance(getattr(X,attr), int)}
# attrDict is {'a':'one', 'b':'two'}
class Y(X):
    def __init__(self):
        self.copyOver()
    @classmethod
    def copyOver(klass):
        [setattr(klass, k,v) for k,v in attrDict.iteritems()]
y = Y()  # Y.a = 1 unless this runs
assert Y.a == 'one' and Y.b == 'two'

但是,实例化在真实应用中可能很昂贵:如果没有?

换句话说,我使用什么内置来更新类属性,而无需实例化

class Y(X):
    #TODO: setattr all key value pairs in attrDict on the class Y, not on instances of it.
    #TODO: Do it without requiring to instantiate an object of class Y

与您拥有的相似,但没有在之间创建字典:

In [120]: d = {1:'one', 2:'two'}
     ...: class X(object):
     ...:     a = 1
     ...:     b = 2
     ...:
In [121]: class Y(X):
     ...:     @classmethod
     ...:     def change_me(cls):
     ...:         for k, v in X.__dict__.items():
     ...:             if v in d:
     ...:                 setattr(cls, k, d[v])
     ...:
In [122]: Y.a
Out[122]: 1
In [123]: Y.change_me()
In [124]: Y.a
Out[124]: 'one'
In [125]: X.a
Out[125]: 1

这是一个使用 metaclasses 的版本,它解决了您必须明确运行 classmethod (假设Python3(的关注点:

In [145]: d = {1:'one', 2:'two'}
     ...: class X(object):
     ...:     a = 1
     ...:     b = 2
     ...:
     ...:
In [146]: class ChangeOnCreation(type):
     ...:     def __init__(cls, name, bases, attr_dict):
     ...:         super().__init__(name, bases, attr_dict)
     ...:         for subs in bases:
     ...:             for k, v in subs.__dict__.items():
     ...:                 if v in d:
     ...:                     setattr(cls, k, d[v])
     ...:
In [147]: class Y(X, metaclass=ChangeOnCreation):
     ...:     pass
     ...:
In [148]: Y.a
Out[148]: 'one'
In [149]: X.a
Out[149]: 1

是什么阻止您直接在类型(类(上分配值?例如:

class X(object):
    a = 1
    b = 2
d = {1: 'one', 2: 'two'}
class Y(X): pass
for k in dir(Y):
    val = getattr(Y, k)
    try:
        if val in d:
            setattr(Y, k, d[val])
    except TypeError:
        pass  # ignore the types that cannot be in our `d`
assert Y.a == "one" and Y.b == "two"

相关内容

最新更新