假设我的班级中有一个(普通绑定)方法,该方法必须访问类变量(如__init__中的计数器)。如果要修改类变量,我看到三种可能性:


使用type(self)self.__class__(在阅读this之后,我选择了type而不是__class__,因为我正在使用Python 3,因此“旧式”类不适用)
使用类的名称。除非名称是反弹,否则此方法效果很好。
专门为更改类变量编写一个@classmethod。这是最复杂但也是最清晰的(IMO)方法。


这三种方法将这样编写:

class MyClass:
    counter = 0

    def f1(self):
        type(self).counter += 1

    def f2(self):
        MyClass.counter += 1

    def f3(self):
        self._count()
    @classmethod
    def _count(cls):
        cls.counter += 1


是否有一个明确的“最佳”选项,是哪个选项,或者它们或多或少是等效的,而仅仅是“我最喜欢的”?继承会改变什么吗?

最佳答案

如果您从定义变量(可能是分配给变量的方法)的类派生类,请使用type(self)将属性(的新值)存储在对象的实际类中。这可能非常有用,但是在您的示例中是surely wrong

使用类方法是相同的,只是子类可以覆盖该方法:这可以使复杂的情况起作用,但不能解决简单的继承情况。

使用类的名称是简单,惯用的答案,并且避免子类造成任何混淆。在不必担心重新绑定该名称的情况下,即使没有任何继承也应将其作为默认值。如果这是一个问题,则可以通过两种不同的方式隐藏类对象:

class A:
  counter=0

  # use the magic behind super():
  def _count1(): __class__.counter+=1

  # inject the class object:
  @staticmethod
  def _count2(cls): cls.counter+=1
A._count2.__defaults__=A,

# inject via a closure:
def capture(cls):
  def _count(): cls.counter+=1
  return _count
A._count3=staticmethod(capture(A))


__class__技巧当然可以直接使用,而无需使用包装方法,但这有点丑陋;在内部,它与capture的最后一种方法非常相似。一件不起作用的事情是尝试创建一个引用类字典的函数,因为这些字典是出于优化原因而受到保护的。

09-10 08:46
查看更多