2011-05-23 59 views
1

给定任意对象:帮助与Python继承

class Val(object): 
    def __init__(self): 
     this_val = 123 

我想创建具有是属性的抽象基类Val()

class A(object): 
    foo = Val() 

我希望,当我的孩子继承该类,他们将获得Val()的副本。例如:

class B(A): 
    pass 
class C(A): 
    pass 

我希望以下行为:

>>> b = B() 
>>> c = C() 
>>> c.foo.this_val = 456 
>>> b.foo.this_val 
123 

而是我得到:

>>> b.this_val 
456 

我明白,我可能只是self.foo = Val()INIT实现该行为,但我有一个要求,即foo仍然是一个属性(它是在Django的模型管理器)。任何人都可以为此提出解决方法吗?

编辑:我真正需要的是能够访问该值作为一个类的属性,所以我期望的行为是:

>>> C.foo.this_val = 456 
>>> B.foo.this_val 
123 

回答

2

也许使用descriptor会满足您的要求:

class Val(object): 
    def __init__(self): 
     self.this_val = 123 

class ValDesc(object): 
    def __init__(self): 
     self.cls_lookup = {} 

    def __get__(self, obj, objtype=None): 
     return self.cls_lookup.setdefault(objtype, Val()) 

class A(object): 
    foo = ValDesc() 

class B(A): 
    pass 
class C(A): 
    pass 

现在,只要你确保你没有设置实例属性您的任何物体的“富”,他们将有一类属性是个体对每个子类:

b = B() 
c = C() 
cc = C() 
c.foo.this_val = 456 
print c.foo.this_val # 456 
print cc.foo.this_val # 456 
print b.foo.this_val # 123 

编辑:随着我几个小时前做出的修改,改变tr他在__get__关键是objtype而不是obj.__class__,访问类时直接属性,这也适用:

print B.foo.this_val # 123 
print C.foo.this_val # 456 
0

一举两得。

使其成为类属性,还将其初始化为__init__函数中的新实例。这样存储的参考文献就不是共享的参考文献。

+0

我需要引用它的属性,虽然。我想做'C.foo.this_val'和'B.foo.this_val'并得到不同的结果。对不起,如果不明确。我没有实例:( – Bacon 2011-05-23 06:43:40

+0

然后在个别类定义中覆盖它呢? – Amber 2011-05-23 06:47:47

+0

我真的很希望不要这样做。必须有一些模糊的python私有方法,我可以重写以达到这个目的? – Bacon 2011-05-23 06:50:15

4

属性foo只有存在于A。您将不得不使用元类为每个类添加一个新的Val

class Val(object): 
    def __init__(self): 
     self.this_val = 123 

class MC(type): 
    def __init__(self, name, bases, d): 
    super(MC, self).__init__(name, bases, d) 
    self.foo = Val() 

class A(object): 
    __metaclass__ = MC 

class B(A): 
    pass 

B.foo.this_val = 456 
print A.foo.this_val 
print B.foo.this_val