Python 子类化Dict,类变量

Python 子类化Dict,类变量,python,Python,我试图拼凑一些示例代码,但我遇到了一些对我来说不太有意义的问题。如果不包括整个来源,我会尝试把我认为重要的部分,希望我能得到所有。 在这里,他声明了一个定制的dict子类,我认为应该是类变量“customer”和“film”。如中所示,从一个类中设置这些,应该在所有实例中更新它们,是吗 class Payment(dict): customer = film = None 这是他使用付款的地方 columns = [item[0] for item in cursor.descript

我试图拼凑一些示例代码,但我遇到了一些对我来说不太有意义的问题。如果不包括整个来源,我会尝试把我认为重要的部分,希望我能得到所有。 在这里,他声明了一个定制的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吗?这就是我的困惑所在

事实证明,这两个属性在所有方面都具有独特的值。这与Dict的子类化有关吗?这些值是复制的而不是引用的,所以从技术上讲它们是类变量,但是由于它们是复制的,所以它们仍然保持唯一性

就在我认为我理解了简单的OO机制的时候,这让我想起了…

payment.customer = customers[payment["customer_id"]] #This is where he assigns 'class variable'
payment.film = films[payment["film_id"]]
您没有更改payment.customer和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.val和x3.val继续引用相同的列表。

如下所示:

payment.customer = customers[payment["customer_id"]] #This is where he assigns 'class variable'
payment.film = films[payment["film_id"]]
您没有更改payment.customer和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.val和x3.val继续引用同一个列表。

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

此后

payment = Payment(zip(columns, row)) #I believe this is where he loads dict items
您可以检查付款情况。dict没有客户或电影的条目

如果您尝试访问getattr payment.film,由于实例没有film属性,您将获得payment.\uuuuu class\uuuu.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

出于某种原因,作者可能更喜欢声明这些属性,但在这种情况下,将它们放在那里并不必要,也可能会造成混淆。

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

此后

payment = Payment(zip(columns, row)) #I believe this is where he loads dict items
您可以检查付款情况。dict没有客户或电影的条目

如果您尝试访问getattr payment.film,由于实例没有film属性,您将获得payment.\uuuuu class\uuuu.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

出于某种原因,作者可能更愿意声明这些属性,但在这种情况下,将它们放在那里并不必要,也可能会造成混淆。

我见过在创建实例并不总是初始化所有实例属性的情况下使用这种技术。在这种情况下,为实例属性提供默认值是一种有用的方法,该属性可以在实例中初始化,也可以不在实例中初始化。pyramid经常使用这种样式。NPE的答案很有帮助,但这一个更好地说明了属性查找。我想我很困惑,因为通常我的类变量从实例的访问是只读的。我只从staticmethod写入类变量。如果我真的想从实例中显式地将“foo”视为类变量,我是否需要从实例方法中使用C.foo?假设变量是一个integer@user2097818是的,但是你应该考虑对C的子类的行为。例如,So.Y.Sub类。FO会让你为子类的实例设置一个子集的属性。这通常是您真正想要的。我可能应该调用staticmethod,向所有实例返回相同的静态值引用,尽管在我看来,对于琐碎的整数查找来说,这似乎有些过分。我见过在创建实例并不总是初始化所有实例属性的情况下使用这种技术。在这种情况下,为实例属性提供默认值是一种有用的方法,该属性可以在实例中初始化,也可以不在实例中初始化。pyramid经常使用这种样式。NPE的答案很有帮助,但这一个更好地说明了属性查找。我想我很困惑,因为通常我的类变量
来自实例的访问通常是只读的。我只从staticmethod写入类变量。如果我真的想从实例中显式地将“foo”视为类变量,我是否需要从实例方法中使用C.foo?假设变量是一个integer@user2097818是的,但是你应该考虑对C的子类的行为。例如,So.Y.Sub类。FO会让你为子类的实例设置一个子集的属性。这通常是您真正想要的。我可能应该进行一个staticmethod调用,该调用将相同的静态值引用返回到所有实例,但在我看来,对于琐碎的整数查找来说,这似乎有些过分。