“self”参数的目的是什么?为什么需要它?

What is the purpose of the `self` parameter? Why is it needed?

提问人:richzilla 提问时间:4/26/2010 最后编辑:Karl Knechtelrichzilla 更新时间:5/11/2023 访问量:1032074

问:

请看这个例子:

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

我知道这是指 的特定实例。但是,为什么必须明确地包含为参数呢?为什么我们需要在方法的代码中使用?其他一些语言将其隐含,或者使用特殊语法来代替。selfMyClassfuncselfself


有关设计决策的与语言无关的注意事项,请参阅将 this/self pointer 强制显式的优点是什么?

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

python oop self

评论

128赞 unutbu 4/26/2010
您可能会发现 Guido van Rossum 的这篇文章“为什么明确的自我必须留下来”很有趣:neopythonic.blogspot.com/2008/10/......
15赞 unutbu 4/26/2010
另请参阅“为什么必须在方法定义和调用中显式使用'self'”:docs.python.org/faq/...
39赞 Santa 4/28/2010
“我很容易理解” --- 很主观,你不觉得吗?什么比 ?后者,IMO,更直观。@nameself.name
3赞 Adam Gent 4/28/2010
虽然玩魔鬼提倡很容易忘记为每种方法添加额外的参数,并且在忘记时会有奇怪的行为,这让初学者很难。恕我直言,我宁愿具体说明静态方法等不寻常的事情,然后再具体说明实例方法等正常行为。
18赞 Evan Plaice 1/17/2012
这就是函数和类方法之间的主要区别。函数是自由浮动的,不受阻碍。类(实例)方法必须知道它的父类(和父属性),因此您需要向该方法传递对父类的引用(作为 self)。这只是一个隐含的规则,在理解 OOP 之前,你必须内化它。其他语言选择句法糖而不是语义简单,python 不是其他语言。

答:

0赞 SilentGhost 4/26/2010 #1

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

评论

24赞 Georg Schölly 4/26/2010
我不认为这有助于 richzilla 理解其背后的原因。
2赞 Dariusz Krynicki 10/9/2017
@SilentGhost:你已经搞定了。我印象深刻。如果我理解正确:我确实创建了一个对象作为定义类的实例,并且 self 参数引用了该对象?我知道 self 以隐含的方式指的是类本身,但如果你能更多地解释你的答案,那就太好了。
790赞 Thomas Wouters 4/26/2010 #2

您需要使用的原因是 Python 不使用特殊语法来引用实例属性。Python 决定以一种使方法所属的实例自动传递而不是自动接收的方式执行方法:methods 的第一个参数是调用该方法的实例。这使得方法与函数完全相同,并留下实际名称由您使用(尽管这是惯例,当您使用其他东西时,人们通常会皱眉头。 对代码来说并不特别,它只是另一个对象。self.selfself

Python本可以做一些其他的事情来区分普通名称和属性 - 像Ruby那样的特殊语法,或者像C++和Java那样需要声明,或者可能更不同的东西 - 但它没有。Python 的宗旨是让事情变得明确,让什么是什么变得清晰,虽然它并不完全在所有地方都这样做,但它确实为实例属性做到了这一点。这就是为什么分配给实例属性需要知道要分配给哪个实例的原因,这就是为什么它需要 .self.

评论

26赞 SilentGhost 4/26/2010
@Georg:指类对象,而不是实例对象cls
22赞 SingleNegationElimination 11/23/2010
@SilentGhost:实际上,第一个参数的名称是你想要的。在类方法上,约定是使用实例方法,并且约定使用实例方法。如果我愿意,我可以用于类方法和实例方法。如果我喜欢,我也可以使用。clsselfselfclsbobfnord
75赞 Jules Gagnon-Marchand 12/13/2012
我发现有趣的是,社区没有选择而不是.在较旧的编程语言中是否有一些我不知道的历史?thisselfself
29赞 Bakuriu 9/21/2013
@Julius 这来自Modula-3的惯例,有关此选择的更多详细信息,请参阅此答案。(免责声明:它的矿山)。self
12赞 Wes Turner 11/9/2014
@Julius 关键字(Smalltalk,1980)早于关键字(来自C++)。请参阅:stackoverflow.com/questions/1079983/...selfthis
11赞 Ming-Tang 4/26/2010 #3

self是对对象本身的对象引用,因此,它们是相同的。 Python 方法不会在对象本身的上下文中调用。 在 Python 中可用于处理自定义对象模型或其他东西。self

23赞 Matthew Rankin 4/26/2010 #4

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

与 Modula-3 一样,[在 Python 中]没有从其方法中引用对象成员的简写:方法函数是用一个表示对象的显式第一个参数声明的,该参数由调用隐式提供。

通常,方法的第一个参数称为 self。这只不过是一个约定:self这个名字对Python来说绝对没有特殊的含义。但是请注意,如果不遵循约定,您的代码对其他 Python 程序员来说可能不太易读,并且也可以想象编写依赖于此类约定的类浏览器程序。

有关详细信息,请参阅有关类的 Python 文档教程

22赞 Ponkadoodle 4/26/2010 #5

除了已经说明的所有其他原因外,它还允许更轻松地访问被覆盖的方法;您可以调用 .Class.some_method(inst)

它有用的地方的一个例子:

class C1(object):
    def __init__(self):
         print "C1 init"

class C2(C1):
    def __init__(self): #overrides C1.__init__
        print "C2 init"
        C1.__init__(self) #but we still want C1 to init the class too
>>> C2()
"C2 init"
"C1 init"
87赞 kame 4/27/2010 #6

我喜欢这个例子:

class A: 
    foo = []

a, b = A(), A()
a.foo.append(5)

b.foo  # [5]
class A: 
    def __init__(self): 
        self.foo = []

a, b = A(), A()
a.foo.append(5)

b.foo  # []

评论

21赞 teddy teddy 9/8/2012
因此,没有 self 的 var 只是类的静态 var,就像在 Java 中一样
7赞 Konstantin 3/28/2014
泰迪泰迪,你不完全正确。行为(静态或非静态)不仅取决于变量类型,还取决于变量类型。尝试使用简单的整数而不是列表来做第一个示例。结果会大不相同。self
2赞 Resigned June 2023 8/7/2014
实际上,我的问题是为什么允许您在第一个示例中说,而不是?显然属于这个班级......a.fooA.foofoo
0赞 Paarth 10/29/2014
可以使用大多数语言从对象的实例调用静态成员。为什么这令人惊讶?
2赞 LegendaryDude 7/13/2017
@RadonRosborough 因为在第一个示例中,和都是(类)的标签(或指针)。 引用类方法。但是,在第二个示例中,成为对 的实例的引用,就像 一样。现在它们是实例而不是类对象本身,self 允许方法对实例进行操作。abA()a.fooA().fooaA()bfoo
440赞 Debilski 4/28/2010 #7

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

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)

所以整个结构保持不变。我怎样才能利用它?如果我们暂时假设我们没有为我们的类编写方法,我们可以这样做:lengthVector

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

这之所以有效,是因为 的第一个参数 可以重新用作 中的参数。如果没有明确的 .length_globalselflength_newself


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

v_instance.length()

在内部转换为

Vector.length(v_instance)

很容易看出适合哪里。您实际上并没有在 Python 中编写实例方法;你写的是类方法,它必须将实例作为第一个参数。因此,您必须将实例参数显式放置在某个位置。self

评论

4赞 Jeeyoung Kim 11/23/2010
Vector.length_new = length_global...实际上,我开始在我的类声明中使用这样的语法。每当我只想从另一个类继承某些方法时,我只需显式复制对方法的引用。
2赞 teddy teddy 9/8/2012
公平地说,Python的“实例方法”只是静态全局方法(如Java或C++)的语法糖,并传递实例对象以打包多个属性?---,这有点半真半假,因为在多态性中,“this”(如在 java 中)或“self”的更重要目的是为您提供正确的方法实现。Python 确实有这个。所以在 python 中调用 myobj.someMethod() 等于 TheClassOfMyObj.someMethod(myobj)。请注意,“TheClassOfMyObj”是由 python 从“self”中自动找出的,否则你必须找出来。
4赞 RussW 9/6/2013
事实上,实例方法不仅只是类方法,而且方法只是作为类成员的函数,如图所示。Vector.length_new = length_global
1赞 Karoly Horvath 3/16/2014
“这行得通,因为 length_global 的第一个参数可以在 length_new 中重新用作 self 参数。如果没有一个明确的自我,这是不可能的“——它的工作原理是一样的。它将被重新用于隐性自我......第二个例子是循环推理 - 你必须显式地将 self 放在那里,因为 Python 需要显式的 self。
1赞 Debilski 3/16/2014
@KarolyHorvath:当然,也可以有一种带有模型的语言,其中内部定义的方法不需要显式的自我,但外部定义的方法需要。但我想说的是,在这两种情况下,要求明确的自我是有一定一致性的,这使得这样做成为合理的理由。其他语言可能会选择不同的方法。
46赞 ninjagecko 6/22/2011 #8

我将使用不使用类的代码进行演示:

def state_init(state):
    state['field'] = 'init'

def state_add(state, x):
    state['field'] += x

def state_mult(state, x):
    state['field'] *= x

def state_getField(state):
    return state['field']

myself = {}
state_init(myself)
state_add(myself, 'added')
state_mult(myself, 2)

print( state_getField(myself) )
#--> 'initaddedinitadded'

类只是避免一直传递这种“状态”事物的一种方式(以及其他一些好东西,如初始化、类组合、很少需要的元类,以及支持自定义方法来覆盖运算符)。

现在让我们使用内置的 python 类机制来演示上面的代码,以展示它基本上是一回事。

class State(object):
    def __init__(self):
        self.field = 'init'
    def add(self, x):
        self.field += x
    def mult(self, x):
        self.field *= x

s = State()
s.add('added')    # self is implicitly passed in
s.mult(2)         # self is implicitly passed in
print( s.field )

[从重复的封闭式问题中迁移了我的答案]

评论

1赞 Cees Timmerman 9/22/2017
我希望 Python 像 Ruby 一样对处理程序进行糖衣炮弹。
0赞 skan 9/22/2022
如果我不使用 self,我只使用字段 += x 怎么办?
18赞 Gaurav Nishant 8/31/2012 #9

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

评论

4赞 LEMUEL ADANE 10/26/2012
class myClass: def myFunc(this, name): this.name = name
11赞 dan-klasson 8/17/2013 #10

它遵循 Python 禅宗“显式比隐式好”。它确实是对类对象的引用。例如,在 Java 和 PHP 中,它被称为 .this

如果是模型上的字段,则可通过 访问它。user_type_nameself.user_type_name

617赞 Arjun Sreedharan 1/27/2014 #11

假设您有一个类,其中包含定义为以下内容的方法:ClassAmethodA

class ClassA:
    def methodA(self, arg1, arg2):
        ... # do something

并且是此类的实例。objectA

现在,当被调用时,python 会在内部为您将其转换为:objectA.methodA(arg1, arg2)

ClassA.methodA(objectA, arg1, arg2)

变量引用对象本身。self

评论

148赞 Seth 10/8/2014
我读了所有其他的答案,有点明白了,我读了这个,然后一切都有意义了。
6赞 Cees Timmerman 9/22/2017
不过,为什么不像 Ruby 那样把这些胆量留在里面呢?
0赞 saurav 1/28/2018
但是在__init__(self)方法中,它接受自我,那么即使没有创建对象,它如何指代自己呢?
2赞 Rain 7/13/2021
不过,这并不能回答这个问题。OP询问为什么必须明确定义。self
1赞 Karl Knechtel 9/5/2022
@saurav 不会创建对象;它通过确定对象的初始状态来初始化对象。当您调用 时,后台有几个步骤。在正常情况下:在(类的通常元类)中查找并找到;,它将调用,然后将结果传递给 。同时,通常默认为 ,这将创建指定类的新对象(即,设置其并为其指定一个空值来保存属性)。__init__MyClass()MyClass.__call__typeMyClass.__new__selfMyClass.__init__MyClass.__new__object.__new____class____dict__
3赞 Oussama L. 1/27/2014 #12

在方法中,self 是指新创建的对象;在其他类方法中,它引用其方法被调用的实例。__init__

自我,作为一个名字,只是一个约定俗成,随心所欲地称呼它!但是在使用它时,例如要删除对象,您必须使用相同的名称: ,其中在__del__(var)var__init__(var,[...])

你也应该看看,以获得更大的图景这篇文章可能会有所帮助。cls

8赞 kmario23 11/15/2014 #13

请看下面的例子,它清楚地解释了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

评论

2赞 user441521 1/13/2016
是的,我想我们知道为什么使用 self,但问题是为什么语言会让你明确声明它。许多其他语言不需要这个,而一种以简短为荣的语言,你会认为它们只会在幕后给你变量,让你像Lua或C++(this)那样使用。
3赞 geekidharsh 4/14/2018
@kmario23 您的回复来自这里: pythontips.com/2013/08/07/the-self-variable-in-python-explained 在将答案发布为您自己的答案时,请务必注明原作者。
14赞 rassa45 5/26/2015 #14

Python不是为面向对象编程而构建的语言,与Java或C++不同。

首先,方法属于整个类(静态方法)或类的对象(实例)(对象方法)。

在 Python 中调用静态方法时,只需编写一个包含常规参数的方法。

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

但是,一个对象(即实例)方法,它需要你创建一个对象(即实例,在本例中为动物),需要参数。self

class Animal():
    def objectMethod(self):
        print "This is an object method which needs an instance of a class"

该方法还用于引用类中的变量字段。self

class Animal():
    #animalName made in constructor
    def Animal(self):
        self.animalName = "";

    def getAnimalName(self):
        return self.animalName

在本例中,指的是整个类的 animalName 变量。切记:如果在方法中创建了新变量(称为局部变量),则将不起作用。该变量仅在该方法运行时存在。要定义字段(整个类的变量),必须在类方法之外定义它们。selfself

如果你不明白我在说什么,那么谷歌“面向对象编程”。一旦你理解了这一点,你甚至不需要:)问这个问题。

评论

0赞 András Aszódi 7/24/2015
+1 因为 和 之间的区别。我想补充一点,为了调用第一个,你会说,虽然需要一个实例:staticMethod()objectMethod(self)Animal.staticMethod()objectMethod()a = Animal(); a.objectMethod()
0赞 user441521 1/13/2016
你说的不是100%正确。这只是一个惯例。您仍然可以从创建的对象调用静态方法。你只是不能使用任何类成员,因为你没有声明一个自我。我甚至可以调用 Animal.objectMethod(animalObj) 来调用非静态。基本上,这意味着静态方法只是一个不使用成员变量的方法。应该没有必要声明自我。我认为这是一个愚蠢的语言要求。像 Lua 和 C++ 这样的语言在后台为您提供了 obj 变量。
3赞 Cees Timmerman 9/22/2017
您做了一个无用的 animalName 字符串声明和崩溃的 animalName 方法。
6赞 Cees Timmerman 9/22/2017
@ytpillai无关紧要。令人困惑和不正确的代码不应作为答案呈现。
3赞 Cees Timmerman 9/22/2017
def getAnimalName不破坏您尝试返回的字符串,并引用类的实例,而不是其中的任何字段。self
250赞 sw123456 6/28/2015 #15

实例化对象时,对象本身将传递到参数中。self

enter image description here

因此,对象的数据绑定到该对象。下面是一个示例,说明人们可能希望如何可视化每个对象的数据可能看起来是什么样子。请注意如何替换为对象的名称。我并不是说下面的这个示例图是完全准确的,但它希望能帮助人们直观地看到 .selfself

enter image description here

将 Object 传递到参数中,以便对象可以保留自己的数据。self

尽管这可能并不完全准确,但请考虑实例化(创建和分配内部值)对象的过程,如下所示:创建对象时,该对象使用该类作为其(对象)自己的数据方法的模板。如果不将对象自己的变量名称传递到参数中,类中的属性和方法将保留为常规模板,并且不会引用(属于)对象。因此,通过将对象的名称传递到参数中,这意味着如果从一个类实例化 100 个对象,则 100 个对象中的每一个都可以跟踪其(每个对象)自己的数据和方法。selfself

摘要:类是通用的(非超特定的)模板,新创建的对象可以将其自己的特定数据传递到其中(不一定会影响可以从同一类创建的其余对象),从而减少复制粘贴的代码,用于创建许多具有相同模式的对象。 用于指定应使用特定对象的数据而不是其他一些数据。self

如下图所示:

enter image description here

评论

1赞 udarH3 8/10/2015
嘿,当通过“bob.name()”访问 Bob 的属性时,您实际上从 'init' 访问 bob().self.name,对吧?
7赞 sw123456 8/10/2015
当您在上面的注释中编写 bob.name() 时,您暗示 bob 有一个名为 name() 的方法,因为您在 name 后添加了括号。但是,在此示例中没有这样的方法。“bob.name”(没有括号)直接从 init(构造函数)方法访问名为 name 的属性。当调用 bob 的 speak 方法时,它是访问 name 属性并在 print 语句中返回它的方法。希望这会有所帮助。
0赞 udarH3 8/10/2015
是的,没有 paranthesis,我想写 sry。因此,您实际上得到了 name 的值,而不是 self.name,因为据我所知,self.name 和 name 是 2 个不同的变量。谢谢
4赞 sw123456 8/10/2015
否,您得到的值为 self.name,对于 bob 对象来说,该值实际上是 bob.name,因为该对象的名称在创建(实例化)时会传递到 self 参数中。再次,希望这会有所帮助。如果有,请随时为主要帖子投赞成票。
4赞 sw123456 8/10/2015
名称在实例化时分配给 self.name。创建对象后,属于该对象的所有变量都是以“self”为前缀的变量。请记住,当从类创建对象时,self 将替换为对象的名称。
5赞 skyking 8/27/2015 #16

这是因为按照 python 的设计方式,替代方案几乎行不通。Python 旨在允许在隐式(a-la Java/C++)或显式(a-la ruby)都不起作用的上下文中定义方法或函数。让我们举一个使用 python 约定的显式方法的例子:this@

def fubar(x):
    self.x = x

class C:
    frob = fubar

现在该函数将不起作用,因为它会假设这是一个全局变量(并且也是如此)。另一种方法是使用替换的全局范围(其中是对象)执行方法。fubarselffrobself

隐式方法是

def fubar(x)
    myX = x

class C:
    frob = fubar

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

但是,目前的情况很好:

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

 class C:
     frob = fubar

这里作为方法调用时,将通过参数接收调用它的对象,并且仍然可以使用对象作为参数调用并工作相同(我认为和我认为相同)。frobselffubarC.frob

8赞 user441521 1/13/2016 #17

我很惊讶没有人提起 Lua。Lua 也使用了 'self' 变量,但可以省略,但仍然使用。C++ 对“this”做同样的事情。我看不出有任何理由必须在每个函数中声明“self”,但您仍然应该能够像使用 lua 和 C++ 一样使用它。对于一种以简短而自豪的语言来说,它要求你声明 self 变量是很奇怪的。

13赞 Akash Kandpal 1/12/2018 #18

首先,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

代码在这里

8赞 Bugs Buggy 8/1/2018 #19

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

1:使用自述

请注意,它不是关键字。

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

2:为什么我们有这种方式,为什么我们不能像Java那样将其作为参数消除,而使用关键字来代替

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

代码示例:

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。

在以前的版本中,您必须显式添加装饰器,否则参数是强制性的。@staticmethodself

1赞 prosti 5/24/2019 #20

自我是不可避免的。

只有一个问题应该是隐含的或明确的。吉多·范·罗苏姆(Guido van Rossum)解决了这个问题,他说自我必须留下来self

那么自我住在哪里呢?

如果我们只坚持函数式编程,我们就不需要了。 一旦我们进入 Python OOP,我们就会在那里找到。selfself

以下是该方法的典型用例class Cm1

class C:
    def m1(self, arg):
        print(self, ' inside')
        pass

ci =C()
print(ci, ' outside')
ci.m1(None)
print(hex(id(ci))) # hex memory address

该程序将输出:

<__main__.C object at 0x000002B9D79C6CC0>  outside
<__main__.C object at 0x000002B9D79C6CC0>  inside
0x2b9d79c6cc0

所以保存类实例的内存地址。其目的是保存示例方法的引用,并让我们明确访问该引用。selfself


请注意,有三种不同类型的类方法:

  • 静态方法(读取:函数),
  • 类方法,
  • 实例方法(已提及)。
3赞 sameer_nubia 10/28/2019 #21

self 的行为类似于当前对象名称或类的实例。

# Self explanation.


 class classname(object):

    def __init__(self,name):

        self.name=name
        # Self is acting as a replacement of object name.
        #self.name=object1.name

   def display(self):
      print("Name of the person is :",self.name)
      print("object name:",object1.name)


 object1=classname("Bucky")
 object2=classname("ford")

 object1.display()
 object2.display()

###### Output 
Name of the person is : Bucky
object name: Bucky
Name of the person is : ford
object name: Bucky
0赞 laxman 2/26/2020 #22

文档中,

方法的特殊之处在于实例对象作为函数的第一个参数传递。在我们的示例中,调用完全等同于 。通常,调用具有 n 个参数列表的方法等效于使用参数列表调用相应的函数,该参数列表是通过在第一个参数之前插入方法的实例对象而创建的。x.f()MyClass.f(x)

在此之前,相关片段,

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

x = MyClass()

0赞 Rishi 6/23/2020 #23

我想说,至少对于 Python 来说,self 参数可以被认为是一个占位符。 看看这个:

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

p1 = Person("John", 36)

print(p1.name)
print(p1.age)

在这种情况下,Self 和许多其他人被用作存储名称值的方法。但是,在那之后,我们使用 p1 将其分配给我们正在使用的类。然后,当我们打印它时,我们使用相同的 p1 关键字。

希望这对 Python 有所帮助!

2赞 Rahul Jha 8/9/2020 #24

“self”关键字包含类的引用,是否要使用它取决于您,但如果您注意到,每当您在 Python 中创建新方法时,Python 都会自动为您编写 self 关键字。如果你做一些研发,你会注意到,如果你在一个类中创建两个方法,并试图在另一个方法中调用一个,除非你添加 self(类的引用),否则它不会识别方法。

class testA:
def __init__(self):
    print('ads')
def m1(self):
    print('method 1')
    self.m2()
def m2(self):
    print('method 2')

下面的代码会引发无法解析的引用错误。

class testA:
def __init__(self):
    print('ads')
def m1(self):
    print('method 1')
    m2()  #throws unresolvable reference error as class does not know if m2 exist in class scope
def m2(self):
    print('method 2')

现在让我们看看下面的例子

class testA:
def __init__(self):
    print('ads')
def m1(self):
    print('method 1')
def m2():
    print('method 2')

现在,当您创建类 testA 的对象时,您可以使用类对象调用方法 m1(),因为方法 m1() 包含 self 关键字

obj = testA()
obj.m1()

但是如果你想调用方法 m2(),因为 is 没有自引用,所以你可以直接使用类名调用 m2(),如下所示

testA.m2()

但是在实践中使用 self 关键字,因为它还有其他好处,例如在内部创建全局变量等。

0赞 saran 12/27/2020 #25

我的小 2 美分

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

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 和实例变量是同一个对象。

1赞 random_hooman 4/9/2021 #26

“self”一词是指类的实例

class foo:
      def __init__(self, num1, num2):
             self.n1 = num1 #now in this it will make the perimeter num1 and num2 access across the whole class
             self.n2 = num2
      def add(self):
             return self.n1 + self.n2 # if we had not written self then if would throw an error that n1 and n2 is not defined and we have to include self in the function's perimeter to access it's variables