为什么Python要显式地使用self关键字?

11

为什么Python在每个参数列表中都需要显式的self参数?

例如,文档中给出的Complex类就是一个例子。

class Complex: 

    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart

    def conjugate(self):
        self.i = -self.i


x = Complex(3.0, -4.5) # 2 instead of 3?
x.conjugate()          # No parameters?

起初我觉得很困惑,为什么__init__( )看起来需要3个参数,但是你却只使用2个参数调用了Complex( )

为什么self参数是显式的而不是隐式的?

4个回答

8

这里有一篇关于此问题的好文章,作者是GvR。它讲解了为什么明确的self引用必须保留。

以下是他提到的几点:

强化了等价性

foo.meth(arg) == C.meth(foo, arg)

能够动态地将方法附加到一个类中,这些方法可以从该类的所有新对象和现有对象中使用:
def meth(myself, arg):
   myself.val = arg
   return myself.val

# Poke the method into the class:
C.meth = meth

我鼓励您阅读本文的其余部分,它非常有趣。

2
foo.meth(arg) == C.meth(foo, arg) 这个在哪里需要用到? - Darek Nędza
2
@DarekNędza 如下一段所解释的那样,您可以通过向类添加一个带有self参数的函数来将其他方法添加到该类的所有对象中 C.newMethod = some_function_with_self - phant0m

2
那就是Python的对象实际上只是一些属性(属性)。 其中一些是常规值,但其他一些是函数。 它们除了是其实例的属性外,并没有与类的特殊绑定。方法调用语法只是一点糖,为您处理传递第一个参数。 实际上,方法只是普通函数,您可以像调用函数一样调用它们,明确地传递第一个参数。
我不知道为什么做出了这个选择,但我认为这与您可以将自由函数分配为现有对象的属性,然后作为方法调用它们有关; 没有显式的 self 参数,这会导致更多的混淆。
该机制类似于Javascript,只是在Javascript中,隐式传递的 this 参数总是引入为名为 this 的局部变量,没有明确的参数,而在Python中,您可以选择自己喜欢的名称通过显式的第一个参数- self 不是关键字,只是一个约定。 这种差异也意味着您可以更轻松地使用函数作为方法-使用 this 的javascript函数将在对象上下文之外(或者更准确地说,在默认对象上下文中,通常为 window )中断,但在Python中,您可以将合适的对象作为第一个参数传递。
请注意,其他面向对象编程(Java,C ++等)也将 self / this 参数传递到您的方法中,但它们是隐式的,并且 this 不出现作为显式参数。 这些语言不允许将方法呼叫为自由函数(反之亦然,您无法将自由函数用作方法)。
至于为什么称其为 __init__ :至少有一个优点,即您可以重命名类而无需重命名构造函数。 这使得重构更加容易和不容易出错。 顺便说一下,Python不是唯一这样做的- PHP使用 __construct ,尽管还支持以类命名的构造函数,但不再推荐使用。

1
(以下是一个过于简化的描述,但应该可以让您了解Python对象创建的过程。)

语句

x = Complex(3.0, -4.5)

不直接调用Complex.__init__。相反,它与以下内容有些相似:

x = Complex.__new__(Complex, 3.0, -4.5)
Complex.__init__(x, 3.0, -4.5)

你可能仍然认为这是不必要的混淆。但它是为了最大的灵活性而设计的。你可以覆盖__new__(通常只是从基类继承)来执行比返回类的实例更多(或不同)的操作。大多数情况下,你不需要这样做,所以为了让你不需要一直进行两次调用来创建和初始化一个对象,它被包装在将类型本身视为可调用对象的简写中,以便在一步中创建和初始化一个对象。


这与__new__有什么关系?论点是,您需要在调用点使用具有n-1个参数的n个形式方法来调用方法。这不是特定于__init__ - phant0m
1
我只是想展示一下为什么__init__需要三个参数,而Complex(3.0, -4.5)似乎只提供了两个。 - chepner

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接