1

我正在尝试拼凑一些示例代码,但遇到了一些对我来说不太有意义的问题。在不包括整个源代码的情况下,我将尝试针对我认为重要的部分,希望我能全部了解。

在这里,他声明了一个自定义 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)

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

事实证明,这两个属性具有全面的独特价值。这是否与子类化字典有关?值是否被复制而不是被引用(所以从技术上讲,它们是类变量,但由于它们被复制,它们继续保持唯一)。

就在我以为我理解了简单的 OO 机制时,这让我……

4

2 回答 2

4

在下面的:

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

你没有改变payment.customerand的值payment.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继续引用同一个列表。

于 2013-03-12T10:17:49.460 回答
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.

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

还有一些翻译乐趣:

>>> 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

出于某种原因,作者可能更喜欢“声明”这些属性,但在这种情况下,没有必要(并且可能会混淆)将它们放在那里。

于 2013-03-12T10:33:08.417 回答