子类化Dict,类变量

时间:2013-03-12 10:13:56

标签: python

我正在尝试拼凑一些示例代码,我遇到了一些对我来说没有意义的东西。如果不包括整个来源,我将尝试针对我认为重要的部分,并希望我能够完成所有这些。

在这里,他声明了一个自定义的dict子类,我认为它应该是类变量'customer'和'film'。 (如在一个类中设置这些,应该在所有实例中更新它们,是吗?)

class Payment(dict):
    customer = film = None

这是他使用付款的地方......

columns = [item[0] for item in cursor.description]
payments = []
for row in cursor.fetchall():
    payment = Payment(zip(columns, row)) #I believe this is where he loads dict items
    payment.customer = customers[payment["customer_id"]] #This is where he assigns 'class variable'
    payment.film = films[payment["film_id"]]
    payments.append(payment)

在最终列表中,不应该所有“付款”都具有相同的值(原来是另一个字典)?这就是我的困惑所在。

事实证明,这两个属性具有全面的独特价值。这与子类化Dict有关吗?值是复制而不是引用(因此从技术上讲它们是类变量,但由于它们被复制,它们仍然是唯一的。)

就在我以为我理解简单的OO机制时,这就引发了我......

2 个答案:

答案 0 :(得分:4)

以下内容:

payment.customer = customers[payment["customer_id"]] #This is where he assigns 'class variable'
payment.film = films[payment["film_id"]]

您没有更改payment.customerpayment.film的值。相反,您重新绑定它们,使它们特定于该类的实例

考虑以下示例:

class X(object):
  val = ['orig']

x1 = X()
x2 = X()
x3 = X()
x1.val = ['rebound']      # rebind
x2.val[0] = 'modified'    # modify in place
print x1.val, id(x1.val)
print x2.val, id(x2.val)
print x3.val, id(x3.val)

打印

['rebound'] 2907552
['modified'] 2771544
['modified'] 2771544

观察x1.val在反弹后如何成为完全独立的变量,而x2.valx3.val继续引用相同的列表。

答案 1 :(得分:2)

当Python在对象上查找属性时,它首先查看实例,然后查看类,然后查看超类。

在此之后

payment = Payment(zip(columns, row)) #I believe this is where he loads dict items

您可以检查payment.__dict__没有customerfilm

的条目

如果您尝试访问(getattr)payment.film,由于该实例没有film属性,您将获得payment.__class__.film

始终分配属性(除非它是描述符)将在实例dict中创建条目,因此它与所有其他实例隔离。

还有一些翻译乐趣:

>>> class C(dict):
...  foo = "class foo"
... 
>>> c = C()
>>> c.__dict__
{}
>>> c.foo
'class foo'
>>> c.foo = "instance foo"
>>> c.__dict__
{'foo': 'instance foo'}
>>> c.foo
'instance foo'
>>> del c.foo
>>> c.foo
'class foo'

顺便说一下,由于示例中的代码无法访问这些类属性,因此这也可以正常工作:

class Payment(dict):
    pass

作者可能更喜欢"声明"这些属性由于某种原因,但在这种情况下将它们放在那里是不必要的(并且可能令人困惑)。