【问题标题】:Python 'self' keywordPython 'self' 关键字
【发布时间】:2023-03-04 15:31:01
【问题描述】:

我是 Python 新手(通常使用 C#),最近几天开始使用它。

在一个类中,您是否需要为对该类数据成员和方法的任何调用添加前缀?那么,如果我在该类中调用一个方法或从该类中获取一个值,我需要使用self.method()self.intvalue,例如?

我只是想检查一下我还没有遇到过更详细的方法。

【问题讨论】:

标签: python


【解决方案1】:

首先,Python 的self 不是关键字,它是一种编码约定,与Python 的cls 相同。

Guido 写了一篇非常详细且有价值的文章,介绍了 Python 对类的支持的起源,并且在那篇文章中,Guido 解释了为什么使用 selfcls,以及为什么它们是必要的。

http://python-history.blogspot.com/2009/02/adding-support-for-user-defined-classes.html

【讨论】:

    【解决方案2】:

    没有比这更冗长的方法了。始终使用self.x 访问实例属性x。请注意,与 C++ 中的 this 不同,self 不是关键字。您可以为方法的第一个参数指定任何您想要的名称,但强烈建议您遵守将其命名为self 的约定。

    【讨论】:

    • +1 因为在Python中self只是一个代表实例对象的变量名!
    • 对仇恨感到抱歉,但那是什么?中世纪?你真的在每个函数调用上都“自我”吗? python 不能像其他人一样摆脱纸袋并隐式提供对自我的访问的原因是什么?
    • @Toskan 不,您没有在每个函数调用上显式传递self。它是隐式传递的;你只需要在方法上明确地接受它。我更喜欢必须明确使用self,因为它使范围更清晰。另请参阅下面尼克的回答和Guido's blog 以了解更多原因。其他人都使用对self 的隐式访问也不是真的,其他人也不是总是做得更好。
    • 哦,我不明白...我可以def f(): self.member = 42吗?
    • @Toskan 好吧,我的评论、尼克的回答和 Guido 的博客文章中提出了很多观点。我不会在这里重复它们。您不必同意他们的观点,但请接受其他人真正喜欢它的方式,并且除了向后兼容性之外还有其他原因。
    【解决方案3】:

    我将用自然的后续问题的答案来补充 Sven 的(准确)回答(即为什么self 明确而不是隐含的?)。

    Python 以这种方式工作,因为它根据词法作用域的概念进行操作:裸名称引用将始终引用当前函数定义中的局部变量、包含函数定义的局部变量、模块的全局变量或一个内置的。 (范围是词法的,因为当您在符号分析期间沿着解析树向下移动时,您只需要记住在通往当前函数的路径上的函数定义中看到的名称 - 其他任何内容都可以处理为“未看到,因此是全局的或内置”。同样值得注意的是,范围规则与函数定义的嵌套有关,而不是调用)。

    在这方面没有对方法进行任何特殊处理 - 类语句在很大程度上与词法范围规则无关,因为在某些语言中不存在相同的函数与方法的明显区别(相反,方法是动态创建的从对象中检索相关属性时的函数)。

    这允许一个函数在它已经被定义之后被添加到一个类中,并且与那些在类语句的主体中定义的方法没有区别(一个称为“monkeypatching”的过程)。

    由于对象名称空间与词法范围规则是分开的,因此有必要提供一些其他方式来引用这些属性。这是由显式self 处理的任务。

    请注意,对于复杂的算法,将成员变量的引用缓存为方法内的局部变量并不少见。

    【讨论】:

    • 为了扩展与类作用域“基本无关”的点,一个例外是 Python 3.x 中的 __class__ 魔术变量(在使用内置 super() 时也会隐式引用)在一种方法中)。当编译器看到这个神奇的变量名时,它会创建一个自动闭包引用,然后用完全构造的类填充该引用。这仅适用于在类范围内实际定义的方法 - 猴子补丁方法必须显式命名类(正如所有函数在 2.x 中所做的那样)。有关详细信息,请参阅 PEP 3135。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 2018-12-12
    • 2011-10-03
    相关资源
    最近更新 更多