自我的目的是什么?

ric*_*lla 1061 python oop class self

selfPython 中这个词的目的是什么?我理解它指的是从该类创建的特定对象,但我不明白为什么它明确需要作为参数添加到每个函数.为了说明,在Ruby中我可以这样做:

class myClass
    def myFunc(name)
        @name = name
    end
end
Run Code Online (Sandbox Code Playgroud)

我很容易理解.但是在Python中我需要包括self:

class myClass:
    def myFunc(self, name):
        self.name = name
Run Code Online (Sandbox Code Playgroud)

谁能跟我说说这个?这不是我在(无可否认的有限)经历中遇到的事情.

Tho*_*ers 679

您需要使用的原因self.是因为Python不使用@语法来引用实例属性.Python的决定做方法的方式,使该实例该方法属于可通过自动,但不接受自动:方法的第一个参数是实例的方法被调用.这使方法与函数完全相同,并留下实际名称以供您使用(虽然self是惯例,当您使用其他东西时,人们通常会对您不满.)self对代码来说并不特殊,它只是另一个对象.

Python可以做其他事情来区分普通名称和属性 - 像Ruby这样的特殊语法,或者需要像C++和Java那样的声明,或者可能是更不同的东西 - 但事实并非如此.Python的所有内容都是为了使事情变得明确,让它显而易见的是什么,虽然它并不是完全无处不在,但它确实是为了实例属性.这就是为什么分配一个实例属性需要知道要分配的实例,这就是它需要的原因self..

  • 我觉得有趣的是社区没有选择"这个"而不是"自我"."self"是否有一些我在较旧的编程语言中不知道的历史? (64认同)
  • @Julius"self"来自Modula-3的惯例,见[this answer](http://stackoverflow.com/questions/13652006/why-accessing-to-class-variable-from-within-the-class-needs -self-in-python/13652256#13652256)有关此选择的更多详细信息.(免责声明:它的我的). (23认同)
  • @Georg:`cls`指的是类对象,而不是实例对象 (21认同)
  • @SilentGhost:实际上,第一个参数的名称是你想要的.在类方法上,惯例是使用`cls`和`self`常规用于实例方法.如果我想,我可以使用`self`作为classmethods和`cls`作为实例方法.如果我喜欢的话,我也可以使用`bob`和`fnord`. (16认同)
  • @Julius`self`关键字(Smalltalk,1980)早于`this`关键字(来自C++).请参阅:/sf/ask/75598841/#1080192 (7认同)
  • 例外情况是它不是"常规"方法或"实例方法",而是其他东西 - 类方法或静态方法或只是普通函数:) (5认同)
  • @ThomasWouters - 说python的"self"关键字与Java的"this"关键字完全相同是正确的吗?如果没有,有什么区别? (3认同)
  • 如果像Lua和C++(这个)那样在幕后给我们自我,那将是很好的."Python的所有内容都是为了使事情变得明确,让它显而易见的是什么,虽然它并不是完全无处不在,但它确实是为了实现属性." 你用这种方式结束它是件好事,因为来自其他语言我即将争论第一部分.使用空格来表示意义并不是一个明确的事情,它是python的核心.我认为与其他语言相比,Python根本不是很明确.那么为什么停下来明确宣布自我就是问题所在. (2认同)

Deb*_*ski 412

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

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
Run Code Online (Sandbox Code Playgroud)

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

    def length(self):
        return math.sqrt(self.x ** 2 + self.y ** 2)
Run Code Online (Sandbox Code Playgroud)

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

def length_global(vector):
    return math.sqrt(vector.x ** 2 + vector.y ** 2)
Run Code Online (Sandbox Code Playgroud)

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

Vector.length_new = length_global
v = Vector(3, 4)
print(v.length_new()) # 5.0
Run Code Online (Sandbox Code Playgroud)

这是因为第一个参数length_global,可以重新用作self参数length_new.如果没有明确的话,这是不可能的self.


理解显式需求的另一种方法self是查看Python添加一些语法糖的位置.当你记住,基本上,一个电话就像

v_instance.length()
Run Code Online (Sandbox Code Playgroud)

内部转变为

Vector.length(v_instance)
Run Code Online (Sandbox Code Playgroud)

很容易看到self适合的位置.你实际上并没有在Python中编写实例方法; 你写的是类方法,它必须将实例作为第一个参数.因此,您必须明确地将实例参数放在某处.

  • Vector.length_new = length_global ...我实际上开始在我的类声明中使用这样的语法.每当我只想从另一个类继承一些方法时,我只是显式复制对方法的引用. (3认同)
  • 事实上,不仅实例方法只是类方法,而且方法只是作为类成员的函数,如`Vector.length_new = length_global`所示. (3认同)
  • 是否可以说python的“实例方法”仅仅是静态全局方法(如Java或C ++)的语法糖,并且实例对象传入了封装多个属性的实例对象?---好吧,这是半正确的,因为在多态中,“ this”(如java中)或“ self”的更重要目的是为您提供方法的正确实现。Python确实有这个。因此,调用myobj.someMethod()等于python中的TheClassOfMyObj.someMethod(myobj)。请注意,“ TheClassOfMyObj”是由python从“ self”中自动找出来的,否则您必须找出来。 (2认同)

Arj*_*ran 374

假设您有一个类ClassA,其中包含一个methodA定义为的方法:

def methodA(self, arg1, arg2):
    # do something
Run Code Online (Sandbox Code Playgroud)

并且ObjectA是这个类的一个实例.

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

ClassA.methodA(ObjectA, arg1, arg2)
Run Code Online (Sandbox Code Playgroud)

self变量是指对象本身.

  • 我读了所有其他的答案,有点理解,我读了这个,然后一切都有道理. (79认同)
  • 这被称为神奇的答案__magic __() (7认同)
  • 这应该是答案!! 要点和准确 (6认同)
  • 这对我来说很重要! (4认同)
  • 但是,为什么不像 Ruby 那样将这些胆量保留在里面呢? (3认同)
  • 但这并不能回答问题。OP 询问为什么必须明确定义“self”。 (3认同)

sw1*_*456 207

实例化对象时,对象本身将传递给self参数.

在此输入图像描述

因此,对象的数据绑定到对象.下面是一个示例,说明如何可视化每个对象的数据外观.注意如何用对象名称替换"self".我不是说下面的这个示例图是完全准确的,但它有望用于可视化自我的使用.

在此输入图像描述

Object被传递给self参数,以便对象可以保持自己的数据.

虽然这可能不完全准确,但请考虑实例化这样的对象的过程:当一个对象被创建时,它使用该类作为其自己的数据和方法的模板.如果不将自己的名称传递给self参数,则类中的属性和方法将保留为通用模板,并且不会引用(属于)对象.因此,通过将对象的名称传递给self参数,意味着如果从一个类中实例化100个对象,则它们都可以跟踪自己的数据和方法.

见下图:

在此输入图像描述

  • 这是你解释东西的方式!不错的工作 :) (5认同)
  • 当您在上面的注释中编写bob.name()时,您暗示bob有一个名为name()的方法,因为您在名称后添加了括号.然而,在这个例子中没有这样的方法.'bob.name'(没有括号)直接从init(构造函数)方法访问名为name的属性.当调用bob的speak方法时,它是访问name属性并在print语句中返回它的方法.希望这可以帮助. (3认同)
  • 不,你得到self.name的值,对于bob对象实际上是bob.name,因为对象的名称在创建(实例化)时被传递给self参数.再次,希望这会有所帮助.如果有的话,请随意上传主要帖子. (3认同)
  • 在实例化时将名称分配给self.name.创建对象后,属于该对象的所有变量都是以"self"为前缀的变量.请记住,在从类创建self时,self将替换为对象的名称. (2认同)

kam*_*ame 76

我喜欢这个例子:

class A: 
    foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: [5]

class A: 
    def __init__(self): 
        self.foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: []
Run Code Online (Sandbox Code Playgroud)

  • 所以没有self的变量只是类的静态变量,就像在java中一样 (16认同)
  • 泰迪泰迪,你不完全正确.行为(静态或非静态)不仅取决于"self",还取决于变量类型.尝试使用简单整数而不是列表来完成第一个示例.结果会大不相同. (5认同)
  • 实际上,我对此的疑问是,为什么在第一个示例中允许您使用`a.foo`而不是`A.foo`?显然`foo`属于该类... (2认同)
  • @RadonRosborough因为在第一个示例中,“ a”和“ b”都是“ A()”(类)的标签(或指针)。`a.foo`引用`A()。foo`类方法。不过,在第二个示例中,“ a”和“ b”一样成为对A()的* instance *的引用。现在它们是实例,而不是类对象本身,* self *允许foo方法在实例上进行操作。 (2认同)

nin*_*cko 38

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

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'
Run Code Online (Sandbox Code Playgroud)

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

现在让我们使用内置的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 )
Run Code Online (Sandbox Code Playgroud)

[从重复的封闭问题中移出我的答案]


Mat*_*kin 19

以下摘录来自关于selfPython文档:

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

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

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


Pon*_*dle 19

除了已经说明的所有其他原因之外,它还允许更容易地访问被覆盖的方法; 你可以打电话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
Run Code Online (Sandbox Code Playgroud)
>>> C2()
"C2 init"
"C1 init"
Run Code Online (Sandbox Code Playgroud)


小智 15

它的用法类似于this在Java中使用关键字,即提供对当前对象的引用.

  • class myClass: def myFunc(this, name): this.name = name (2认同)

ytp*_*lai 14

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

在Python中调用静态方法时,只需在其中编写一个带有常规参数的方法.

class Animal():
    def staticMethod():
        print "This is a static method"
Run Code Online (Sandbox Code Playgroud)

但是,在这种情况下,需要您创建变量的对象方法需要self参数

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

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

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


    def getAnimalName(self):
        return self.animalName
Run Code Online (Sandbox Code Playgroud)

在这种情况下,self指的是整个类的animalName变量.记住:如果方法中有变量,则self不起作用.该变量仅在该方法运行时存在.对于定义字段(整个类的变量),您必须在类方法外定义它们.

如果你不理解我所说的单词,那么Google就是"面向对象的编程".一旦你理解了这一点,你甚至不需要问这个问题:).

  • 你做了一个无用的animalName 字符串声明和崩溃的animalName 方法。 (3认同)
  • `def getAnimalName` 不会破坏您尝试返回的字符串,并且 `self` 指的是类的实例,而不是其中的任何字段。 (3认同)
  • @ytpillai不相关.不应将令人困惑和错误的代码显示为答案. (2认同)

dan*_*son 9

它遵循Python zen"显然优于隐式".它确实是对您的类对象的引用.例如,在Java和PHP中,它被称为this.

如果user_type_name是模型上的字段,则可以访问它self.user_type_name.


Min*_*ang 7

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


kma*_*o23 7

看看下面的例子,它清楚地解释了 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  
Run Code Online (Sandbox Code Playgroud)

self 用于/需要区分实例。

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

  • @kmario23 您的回复来自此处:https://pythontips.com/2013/08/07/the-self-variable-in-python-explained/ 在将答案发布为您自己的答案时,请务必感谢原作者。 (3认同)
  • 是的,我想我们知道为什么使用 self,但问题是为什么语言让你显式声明它。许多其他语言不需要这个,并且一种以简洁而自豪的语言,您可能会认为它们只会在幕后为您提供变量以供您使用,就像 Lua 或 C++(这个)所做的那样。 (2认同)

Aka*_*pal 7

首先,自我是一个传统的名称,你可以把任何其他东西(连贯的)代替.

它指的是对象本身,因此当您使用它时,您声明.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
Run Code Online (Sandbox Code Playgroud)

代码就在这里


Bug*_*ggy 7

使用通常称为“参数”的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"
Run Code Online (Sandbox Code Playgroud)

PS:仅在Python 3.x中有效。

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


use*_*521 6

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


sky*_*ing 5

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

def fubar(x):
    self.x = x

class C:
    frob = fubar
Run Code Online (Sandbox Code Playgroud)

现在该fubar函数将无法工作,因为它假定这self是一个全局变量(以及 in frob)。另一种方法是使用替换的全局范围(self对象在哪里)来执行方法。

隐式方法是

def fubar(x)
    myX = x

class C:
    frob = fubar
Run Code Online (Sandbox Code Playgroud)

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

然而,目前的情况很好:

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

 class C:
     frob = fubar
Run Code Online (Sandbox Code Playgroud)

这里的时候,被称为一方法frob将接收上它通过调用对象self的参数,并且fubar仍然可以用一个对象作为参数调用和工作一样(这一样的C.frob,我认为)。


归档时间:

查看次数:

807848 次

最近记录:

5 年,11 月 前