python:具有多态性的类属性/变量继承?

标签 python class singleton

在我作为 python 学徒的努力中,如果我尝试使用类属性,我最近会遇到一些奇怪的(从我的角度来看)行为。我不是在提示,但希望能提供一些有用的评论来阐明这个问题。

为了将一个复杂的问题简化为一个更简洁的问题,我会这样表述:

确保类属性的行为更像继承树中的静态变量的“pythonic”方法是什么?

在我看来,类属性的行为类似于具有多态特征的“读取时复制”默认值。只要我做“只读”操作,它就会保持“单例”状态, 但是一旦我通过派生类或实例通过赋值访问类属性,它就会变成一个新的引用,从而失去与继承的基引用的关系。

(它肯定有一些有趣的功能的潜力,但你必须了解它才能 接受它,因此非常感谢一些见解。)

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

产生以下内容:

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.classvar 或通过 self.__class__.classvar 进行调解与 BASECLASS.classvar 不同>.

这是范围问题还是完全不同的问题。

期待您的回答并在此表示感谢。 :-)


编辑:在很短的时间内有一个答案建议使用类描述符,例如: How to make a class property? .

不幸的是,这似乎不起作用:

class Hotel(Bar):
    def __init__(self):        
        Hotel.bar += 1

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

第二个断言失败了! hotel.bar 没有引用与 foo.bar 相同的对象,hotel.bar 引用了 Hotel.bar 以外的对象!


第二次编辑:我很清楚单例被认为是一种“反模式”,我不打算(广泛地)使用它们。因此我没有在问题标题中提及它们。即使如此,有许多解决方案讨论和提供关于单例的解决方案,但我的问题仍然存在:为什么类变量可以如此轻松地分离它的引用? Ruby 的行为更符合我的感觉:http://snippets.dzone.com/posts/show/6649

最佳答案

a1.classvar = 'aaa'

不是对类变量的“引用”。

这是对象“a1”中的一个新实例变量。

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

a.classvar 这样的表达式是通过搜索对象的命名空间来解析的。当这是一个“阅读”引用时,将搜索对象和类(以及父类(super class))。

当 this 出现在赋值的左侧时,实例变量(“classvar”)只是在引用对象(“a”)上创建。无需通过父 namespace 搜索来解析名称,因为没有什么可解析的。正在创建中。

关于python:具有多态性的类属性/变量继承?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8576620/

相关文章:

python - 具有动态映射和复杂对象查询的 sqlalchemy

c++ - 手动对象构造函数调用

c++ - 在 vector 中访问类中的 vector

java - 单例类的优势是什么?

python - Pygame:显示没有组的 Sprite

python - 如何处理子进程异常终止?

c++ - 在 C++ 的类中使用管道

java - 如果 @Singleton bean 中有一个 @Stateless 字段会发生什么?

java - 使用双重检查阻塞方法实例化单例

python - pandas groupby 中两个系列的最大值和最小值