Python 'self' keyword
我刚接触过python(通常在c_上工作),在过去的几天里开始使用它。
在一个类中,是否需要在对该类的任何调用之前加上数据成员和方法的前缀?所以,如果我从该类中调用一个方法或从该类中获取一个值,我需要使用self.method()或self.intvalue?
我只是想确认一下,我还没有遇到一种更详细的方法。
- 你看过这个docs.python.org/tutorial/classes.html吗
- 在python中,self不是关键字。
- @TMC,谢谢你的链接。
- @nmichaels也可能是:/
没有冗长的方式。总是使用EDCOX1 0来访问实例属性EDCOX1(1)。注意,与C++中的EDCOX1 2不同,EDCOX1×3 }不是关键字。您可以给方法的第一个参数指定任意名称,但强烈建议您遵循调用它self的约定。
- +1,因为在python中,self只是一个表示实例对象的变量名!
- 对不起,你的仇恨,那是什么?中世纪?你真的在每一个函数调用上都交了"self"?为什么python不能像其他人一样从纸袋中出来并提供对自我隐式访问?
- @Toskan不,您没有在每个函数调用上显式传递self。它是隐式传递的;您只需在方法上显式接受它。我个人更喜欢明确使用self,因为它保持了范围的清洁。另请参阅下面尼克的答案和吉多的博客,了解更多原因。其他人使用对self的隐式访问也是不正确的,其他人也不总是做得更好。
- 哦,所以我不明白…我可以做def f(): self.member = 42吗?
- 我读了这篇文章,但我并没有真正看到在每个函数调用上必须自己提交的交换所带来的附加值。你可以做到,多亏了类型提示,可选。比如说def: f(PythonSelf self),而不是用pythonself->implicit。这样就不会失去它的优势,同时也不会让其他人对它的存在感到恼火。本文的主要观点是向后兼容性。这是一个足够公平的观点,看看Python2对3的剧情。对我来说,这显然是一件古老的遗物。
- @好吧,在我的评论、尼克下面的回答和圭多的博客中,有很多观点。我不会在这里重复。你不必同意他们,但是请接受其他人真正喜欢它的方式,并有理由而不是向后兼容。
- @ Toskan:EDOCX1·0的含义已经隐含了。您只显式声明EDCOX1 OR 0一次,在方法签名中,EDOCX1"0"传递方法调用是隐式的,不确定您的问题是什么?在您的示例中,EDCOX1引用9。然后,当你实际上调用EDOCX1,10时,你不会在EDOCX1 0中再次通过:EDOCX1×12。这是有意义的,因为EDOCX1 13访问实例命名空间EDCOX1对0与类命名空间的关系如何?
- @好的,那么在函数创建中,当您不能在调用f时使用它时,总是定义自我有什么用呢?例如,我似乎做不到f(differentinstanceofanobject),如果你做不到,那有什么价值呢?
- @ Toskan?如果f是class C和c = C()的常规方法,那么您可以使用c.f()在c上调用f,它总是将c作为f的第一个参数。这就是它隐含的原因。这也是f的签名至少需要1个参数的原因,根据惯例,该参数为self。这样可以确保f中的代码可以访问c的命名空间。如果你有differentinstanceofanobject = C()和def f(self, obj):,那么你可以打c.f(differentinstanceofanobject),c.f可以访问c和differentinstanceofanobject。
- 当你不能做d = D()c.f(d)时,为什么要明确地把self定义为参数?那一定是个古老的遗迹。没有其他编程语言有这种怪癖。我觉得很没用。
- @托斯卡纳,你显然是在这里闲逛。"没有其他编程语言有这样的怪癖。"这是不真实的,实际上很常见,例如在Perl5和Dylan中。更新的语言如rust决定通过自我明确。人们喜欢这样,因为尼克下面的回答和吉多的博客中给出了原因。
- @Svenmarnach Guidos博客帖子…是的,我读过。基本上,他给出了一些例子,然后说,"好吧,我猜那些也可以用内隐的自我来解决",是的,我同意他的观点,所以到目前为止,0分支持外显的self。然后他提到了装饰师,没有给出一个可靠的例子。他说,"我们不知道它是静态的还是非静态的",在某一点上,你会知道它是静态的还是非静态的。我不是说这是小事。但它显然是可以解决的。仅仅因为其他一些编程语言正在走捷径,这对我来说真的是一个不够好的借口。
- 实际上,吉多提出的最令人信服的论点是"方法戳"。比如说,你也可以用def f() this.xyz()来插入一个全局函数,但这很奇怪。现在,如果你说"把自己交给Python做起来更容易",那么我会同意的。我想这就是NCOGLLAN想说的。这很简单。
我将补充SVEN(准确)的回答,回答自然的后续问题(即为什么self是明确的而不是含蓄的?).
python是这样工作的,因为它在词汇作用域的概念上工作的:裸名称引用总是引用当前函数定义中的局部变量、包含函数定义的局部变量、模块的全局变量或内置变量。(作用域是词法上的,因为在符号分析过程中,当沿着解析树向下时,只需要记住在指向当前函数的路径上的函数定义中看到的名称-任何其他名称都可以被处理为"看不到,因此是全局的或内置的"。还值得明确指出的是,作用域规则与函数定义的嵌套相关,而不是与调用相关)。
在这方面,方法没有任何特殊的处理方法-类语句在很大程度上与词汇范围规则无关,因为在某些语言中没有相同的锐利的函数与方法区别(相反,当从对象中检索相关属性时,方法是从函数动态创建的)。
这允许在已经定义函数之后将其添加到类中,并且与在类语句主体(称为"monkeypatching"的过程)中定义的方法不可区分。
由于对象名称空间与词汇作用域规则是分开的,因此有必要提供其他方法来引用这些属性。这是显式self处理的任务。
注意,对于复杂的算法,将成员变量的引用缓存为方法中的局部变量并不少见。
- 为了扩展与类作用域有关的"基本无关"点,一个例外是python 3.x中的__class__magic变量(在方法中使用builtin super()时也隐式引用)。当编译器看到这个魔力变量名时,它会创建一个自动的闭包引用,然后用完全构造的类来填充它。这只适用于在类作用域内实际定义的方法-猴子修补的方法必须显式地命名类(就像所有函数都必须在2.x中那样)。详情见PEP 3135。
首先,python的self不是关键字,它是一种编码约定,与python的cls相同。
guido写了一篇关于python支持类的起源的非常详细和有价值的文章,在那篇文章中,guido解释了为什么使用self和cls,以及为什么它们是必需的。
请参阅http://python-history.blogspot.com/2009/02/adding-support-for-user-defined-classes.html。