【问题标题】:Using __class__ to create instances使用 __class__ 创建实例
【发布时间】:2013-01-01 16:41:16
【问题描述】:

使用__class__ 在类中创建新实例是个好主意吗?

以下代码是这样做的示例:

from collections import namedtuple

_Position = namedtuple('Position', ['x', 'y'])
class Position(_Position):
    def __add__(self, other):
        return __class__(self.x + other.x, self.y + other.y)

对我来说,使用实际的类名听起来像是重复的代码。如果类的名称发生更改,我必须在所有情况下都更改它,即使现代 IDE 可以为您做到这一点。

顺便说一句。 __class__ 是什么变量?你不应该只能通过self. 访问它吗?

【问题讨论】:

  • 如果你要继承namedtuple,为什么不从头开始创建一个对象?
  • 这里有一个很好的解释:stackoverflow.com/questions/8060751/…
  • @Blender 这只是一个例子。我确实可以从头开始创建一个对象。

标签: python python-3.x code-duplication


【解决方案1】:

为了支持super() 的零参数形式,如果在类方法中使用__class__super(),编译器会添加对该类的隐式引用。见Creating the class object

您找到的示例代码 (ab) 在添加时使用这个小事实来创建 Position 的新实例。

就我个人而言,我会改用type(self),因为这是确定任何对象的类型或类的正确 API 方法。 type(self) 将在适当的地方使用 self.__class__

def __add__(self, other):
    return type(self)(self.x + other.x, self.y + other.y)

如果您想支持子类化,那一个好主意。 Position 的任何子类在相加时都将返回正确的子类类型。使用__class__不会这样做,因为它总是指向Position,即使是子类:

>>> class Foo:
...     def method(self):
...         print(__class__)
...         print(type(self))
... 
>>> class Bar(Foo):
...     pass
... 
>>> Bar().method()
<class '__main__.Foo'>
<class '__main__.Bar'>

当然,如果这是你一直以来的意图(绕过子类),我仍然更喜欢使用显式类名而不是使用__class__;显式优于隐式。

【讨论】:

  • 这是否意味着你也可以使用 self.__class__(...) 而不是 type(self)(...),这样会更快,对吧?
  • @Joschua:那是错误的优化。我仍然会使用type(self),因为您应该尽可能使用 API 方法而不是直接访问挂钩。
  • @Martijin Pieters 为什么要使用它们而不是其他的?
  • @Joschua:因为钩子是供 API 使用的,所以允许 API 将来扩展并在需要时使用其他钩子。
  • @Martijin Pieters:谢谢!
猜你喜欢
  • 1970-01-01
  • 2015-09-09
  • 2022-08-02
  • 2016-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-17
  • 1970-01-01
相关资源
最近更新 更多