想想这个例子:

class MyClass:
    def func(self, name):
        self.name = name

我知道self引用MyClass的特定实例。但是为什么func必须显式地包含self作为参数呢?为什么我们需要在方法的代码中使用self ?其他一些语言将其隐式化,或者使用特殊的语法。


有关设计决策的语言无关性考虑,请参见强制显式使用this/self指针的好处是什么?

要关闭OP省略方法的self形参并获得TypeError的调试问题,请使用TypeError: method()接受1个位置参数,但给出了2个。如果OP省略了self。在方法体中得到一个NameError,考虑如何在类中调用函数?


当前回答

让我们看一个简单的向量类:

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

我们需要一个计算长度的方法。如果我们想在类中定义它会是什么样子呢?

    def length(self):
        return math.sqrt(self.x ** 2 + self.y ** 2)

当我们将它定义为全局方法/函数时,它应该是什么样子?

def length_global(vector):
    return math.sqrt(vector.x ** 2 + vector.y ** 2)

所以整个结构保持不变。我怎样才能利用这个呢?假设我们还没有为Vector类编写length方法,我们可以这样做:

Vector.length_new = length_global
v = Vector(3, 4)
print(v.length_new()) # 5.0

这是因为length_global的第一个参数可以重用为length_new中的self参数。如果没有显式的自我,这是不可能的。


另一种理解显式self需求的方法是查看Python在哪里添加了一些语法糖。当你记住的时候,基本上,一个电话就像

v_instance.length()

在内部转化为

Vector.length(v_instance)

很容易看出自我在哪里。实际上你不用在Python中编写实例方法;你所写的是类方法,它必须以一个实例作为第一个参数。因此,必须显式地将实例参数放置在某个位置。

其他回答

因为按照python的设计,其他的选择几乎行不通。Python被设计为允许在隐式this (a-la Java/ c++)或显式@ (a-la ruby)都不能工作的上下文中定义方法或函数。让我们看一个带有python约定的显式方法的例子:

def fubar(x):
    self.x = x

class C:
    frob = fubar

现在fubar函数不能工作了,因为它假定self是一个全局变量(在frob中也是如此)。另一种方法是使用替换的全局作用域(其中self是对象)执行方法。

隐式方法是

def fubar(x)
    myX = x

class C:
    frob = fubar

这意味着myX将被解释为fubar(以及frob)中的局部变量。这里的替代方案是使用替换的局部作用域执行方法,该作用域在调用之间保留,但这将消除方法局部变量的可能性。

然而,目前的情况很好:

 def fubar(self, x)
     self.x = x

 class C:
     frob = fubar

在这里,当作为方法调用时,frob将通过self参数接收它所调用的对象,fubar仍然可以以对象作为参数调用并且工作相同(我认为它与C.frob相同)。

以下摘自关于self的Python文档:

As in Modula-3, there are no shorthands [in Python] for referencing the object’s members from its methods: the method function is declared with an explicit first argument representing the object, which is provided implicitly by the call. Often, the first argument of a method is called self. This is nothing more than a convention: the name self has absolutely no special meaning to Python. Note, however, that by not following the convention your code may be less readable to other Python programmers, and it is also conceivable that a class browser program might be written that relies upon such a convention.

有关更多信息,请参阅Python类文档教程。

我很惊讶居然没人提起Lua。Lua也使用“self”变量,但是可以省略,但仍然使用。c++对'this'做了同样的处理。我不认为有任何理由必须在每个函数中声明“self”,但你仍然可以像使用lua和c++一样使用它。对于一门以简洁为傲的语言来说,它要求你声明self变量是很奇怪的。

看看下面的例子,它清楚地解释了self的目的

class Restaurant(object):  
    bankrupt = False

    def open_branch(self):
        if not self.bankrupt:
           print("branch opened")

#create instance1
>>> x = Restaurant()
>>> x.bankrupt
False

#create instance2
>>> y = Restaurant()
>>> y.bankrupt = True   
>>> y.bankrupt
True

>>> x.bankrupt
False  

Self用于/需要用于区分实例。

来源:python中的self变量解释- Pythontips

我的小钱

在Person类中,我们用self定义了init方法,这里需要注意的有趣的事情是self和实例变量p的内存位置是相同的<__main__。位于0x106a78fd0>的Person对象

class Person:

    def __init__(self, name, age):
        self.name = name 
        self.age = age 

    def say_hi(self):
        print("the self is at:", self)
        print((f"hey there, my name is {self.name} and I am {self.age} years old"))

    def say_bye(self):
        print("the self is at:", self)
        print(f"good to see you {self.name}")

p = Person("john", 78)
print("the p is at",p)
p.say_hi()  
p.say_bye() 

如上所述,self和实例变量都是同一个对象。