python:类属性/变量继承与多态?

python:class attribute/variable inheritance with polymorphism?

在我的endeavours as a Python学徒recently at some奇迷住了我(我从点视图)的行为,如果我工作与类的属性。我会complaining not,but to some一些帮助意见appreciate"这个问题的光网络。P></

为减少在复合物更简明的问题:它会制定这样P></

"语言"是is the Way to确保类的属性,类静态变量behaves黑莓在继承树中安?P></

我似乎像一个behaves级属性默认值"copy with polymorphic在线读"的特点。"只要我只读存储器的操作","单身"stays恩but as the快,当接入级属性指派一类与安审茶源或在它morphed into the reference to the inherited松关系的基本参考。P></

它有潜在的(和有些有趣的特点,but it to You have to理解拥抱它,我知道appreciated is some Insight)高度。P></

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class A(object):
    classvar = 'A'
    def setclassvar(self, value):
        A.classvar = value                  
    def __str__(self):
        return"%s id(%s)" %(A.classvar, hex(id(A.classvar))[2:-1].upper())

class A1(A):
    pass

class B(object):
    classvar = 'B'
    def setclassvar(self, value):
        self.__class__.classvar = value            
    def __str__(self):
        cvar = self.__class__.classvar
        return"%s id(%s)" %(cvar, hex(id(cvar))[2:-1].upper())

class B1(B):
    def setclassvar(self, value):
        self.__class__.classvar = value

a, a1 = A(), A1()
a1.setclassvar('a')
print"new instance A: %s" %a
print"new instance A1: %s" %a

b, b1 = B(), B1()
b1.setclassvar('bb')
print"new instance B: %s" %b
print"new instance B1: %s" %b1

a1.setclassvar('aa')
print"new value a1: %s" %a
print"new value a: %s" %a

a1.classvar = 'aaa'
print"direct access a1: %s id(%s)" %(a1.classvar, hex(id(a1.classvar))[2:-1].upper())
print"method access a1: %s" %a1
print"direct access a: %s" %a

produces下面:P></

1
2
3
4
5
6
7
8
9
new instance A: a id(B73468A0)
new instance A1: a id(B73468A0)
new instance B: B id(B73551C0)
new instance B1: bb id(AD1BFC)
new value a1: aa id(AD1BE6)
new value a: aa id(AD1BE6)
direct access a1: aaa id(A3A494)
method access a1: aa id(AD1BE6)
direct access a: aa id(AD1BE6)

我知道(或者直接接入object.classvarthe assigning)或导通BASECLASS.classvarself.__class__.classvarare not the same as。P></

这是在不同的问题totaly扫帚或东西。P></

谢谢你的答案,看在前馈和前馈。:-)P></

编辑:there was an回答的很短的时间suggesting for the of descriptors类使用类:如何使类的属性?。P></

我不unfortunatly似乎工作:P></

1
2
3
4
5
6
7
class Hotel(Bar):
    def __init__(self):        
        Hotel.bar += 1

hotel = Hotel()
assert hotel.bar == 51
assert hotel.bar == foo.bar

在第二assertion失败!不hotel.bar the same as foo.bar参考对象和其他东西,那么hotel.bar hotel.barreferences。P></

2编辑:我是单身,那么事情考虑感知安"antipattern"和不打算使用them to(广泛)。值得一提的therefore them in the question不-题目。即使我有许多discussing提供解决方案和解决方案是与单身和about,我的问题:为什么我在stays级变量的参考easily detach知道吗?红宝石behaves黑莓什么感觉自然的方式对我snippets.dzone.com:http://///6649 show postsP></


1
a1.classvar = 'aaa'

这不是对类变量的"引用"。

这是对象"a1"中的新实例变量。

A.classvar这样的表达式是类变量。类对象(及其超类)都有一个类级字典(A.__dict__),其中定义了类级对象。名称解析通过检查类,然后检查方法解析顺序(MRO)中的所有超级类来工作。

A.classvar这样的表达式是通过搜索对象的名称空间来解析的。当这是"读取"引用时,将搜索对象和类(以及超类)。

当它出现在赋值的左侧时,实例变量("classvar")只在引用的对象("a")上创建。没有通过父命名空间搜索来解析名称,因为没有要解析的内容。它正在被创建。


如果实现很难解释,那是个坏主意。

在本例中,为了复杂起见,我将包含一个实现,因为这是我在Python中喜欢的一种棘手的事情。

因此,下面的代码片段在某种程度上滥用了闭包来设计一个满足O.P.需求的类修饰器:一个在派生类中读写时保持"统一"的类变量。

另外,作为一个额外的好处,我将属性包装在一个描述符中,这使得属性在实例中是不可更改的——所以每当写入属性时——在原始类的子类或子类的实例中,类属性都会得到适当的更新。

正如python的zen所说:"如果实现很难解释,那是一个坏主意"——我认为我不可能遇到更困难的事情——我们这里讨论的是范围动态生成的元类。它将起作用,但它释放了这是"非对称"代码,因为由于类、元类、闭包和描述符机制的大量使用,它非常神秘。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
def SingletonAttrs(**names):
    keys = names.keys()
    def class_decorator(cls):
        class Meta(type):
            def __getattribute__(cls, attr):
                if attr in keys:
                    return type.__getattribute__(owner_cls,  attr)
                return type.__getattribute__(cls, attr)
            def __setattr__(cls, attr, value):
                if attr in keys:
                    class Wrapper(object):
                        def __init__(self, value):
                            self.__set__(None, value)
                        __set__ = lambda self, instance, value: setattr(owner_cls,"__" +  attr, value)
                        __get__ = lambda self, instance, owner: type.__getattribute__(owner_cls,"__" + attr)
                    return type.__setattr__(owner_cls,  attr, Wrapper(value))
                return type.__setattr__(cls, attr, value)
        owner_cls = Meta(cls.__name__, cls.__bases__, cls.__dict__.copy())
        for key in keys:
            setattr(owner_cls, key, names[key])
        return owner_cls
    return class_decorator

if __name__ =="__main__":

    @SingletonAttrs(a="value 1", b="value 2")
    class Test(object):
        pass

    class TestB(Test):
        pass

    t = Test()
    print t.a
    print t.b
    tb = TestB()
    tb.a ="value 3"
    print Test.a