假设我的班级中有一个(普通绑定)方法,该方法必须访问类变量(如__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
的最后一种方法非常相似。一件不起作用的事情是尝试创建一个引用类字典的函数,因为这些字典是出于优化原因而受到保护的。