MyClass.attr VS类型(self).attr VS单独的@classmethod

时间:2019-02-10 13:55:25

标签: python class attributes

说我的类中有一个(正态绑定)方法,该方法必须访问类变量(例如__init__中的计数器)。如果要修改类变量,我看到三种可能性:

  1. 使用type(self)self.__class__(在阅读this之后,我选择了type而非__class__,因为我使用的是Python 3 “课程不适用)
  2. 使用类的名称。除非名称是反弹,否则此方法效果很好。
  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

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

1 个答案:

答案 0 :(得分: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的最后一种方法非常相似。一件不起作用的事情是尝试创建一个引用类的 dictionary 的函数,因为出于优化原因而对其进行了保护。