想想这个例子:

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,考虑如何在类中调用函数?


当前回答

首先,self是一个传统的名字,你可以用其他任何东西(连贯)来代替它。

它引用对象本身,因此当您使用它时,您声明.name和.age是您将要创建的Student对象(注意,不是Student类)的属性。

class Student:
    #called each time you create a new Student instance
    def __init__(self,name,age): #special method to initialize
        self.name=name
        self.age=age

    def __str__(self): #special method called for example when you use print
        return "Student %s is %s years old" %(self.name,self.age)

    def call(self, msg): #silly example for custom method
        return ("Hey, %s! "+msg) %self.name

#initializing two instances of the student class
bob=Student("Bob",20)
alice=Student("Alice",19)

#using them
print bob.name
print bob.age
print alice #this one only works if you define the __str__ method
print alice.call("Come here!") #notice you don't put a value for self

#you can modify attributes, like when alice ages
alice.age=20
print alice

代码在这里

其他回答

首先,self是一个传统的名字,你可以用其他任何东西(连贯)来代替它。

它引用对象本身,因此当您使用它时,您声明.name和.age是您将要创建的Student对象(注意,不是Student类)的属性。

class Student:
    #called each time you create a new Student instance
    def __init__(self,name,age): #special method to initialize
        self.name=name
        self.age=age

    def __str__(self): #special method called for example when you use print
        return "Student %s is %s years old" %(self.name,self.age)

    def call(self, msg): #silly example for custom method
        return ("Hey, %s! "+msg) %self.name

#initializing two instances of the student class
bob=Student("Bob",20)
alice=Student("Alice",19)

#using them
print bob.name
print bob.age
print alice #this one only works if you define the __str__ method
print alice.call("Come here!") #notice you don't put a value for self

#you can modify attributes, like when alice ages
alice.age=20
print alice

代码在这里

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

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中编写实例方法;你所写的是类方法,它必须以一个实例作为第一个参数。因此,必须显式地将实例参数放置在某个位置。

它的使用类似于Java中this关键字的使用,即给出对当前对象的引用。

这个参数的使用,通常称为self并不难理解,为什么它是必要的呢?或者为什么要明确地提到它?我想,对于大多数查找这个问题的用户来说,这是一个更大的问题,如果不是,他们在继续学习python时肯定会有同样的问题。我建议他们阅读以下几篇博客:

1:使用自我解释

注意,它不是关键字。

每个类方法(包括init)的第一个参数始终是对类当前实例的引用。按照惯例,这个参数总是命名为self。在init方法中,self指向新创建的对象;在其他类方法中,它引用被调用方法的实例。例如,下面的代码与上面的代码相同。

2:为什么我们要这样做,为什么我们不能像Java那样把它作为一个参数,而是用一个关键字来代替

我想补充的另一件事是,一个可选的self参数允许我在一个类中声明静态方法,不写self。

代码示例:

class MyClass():
    def staticMethod():
        print "This is a static method"

    def objectMethod(self):
        print "This is an object method which needs an instance of a class, and that is what self refers to"

PS:这只适用于Python 3.x。

在以前的版本中,您必须显式地添加@staticmethod装饰器,否则self参数是必须的。

它是对类实例对象的显式引用。