【问题标题】:How does python interpreter build objects [duplicate]python解释器如何构建对象[重复]
【发布时间】:2020-04-20 15:34:47
【问题描述】:

我最近在学习 Java 后开始关注 Python。我对python解释器的对象构造方式感到困惑。

与 Java 相比,我们只需提供参数即可构造对象,Python 也是如此。

但是当我们在类中定义__init()__ 方法时,我想不出为什么它需要self 参数。

我阅读了this 的问题,发现这些方法需要self 参数,因为python 调用ClassA.methodA(ObjectA, arg1, arg2) 格式的方法。

但我真的不明白为什么 __init()__ 方法需要这个。

是不是因为 Python 生成对象的方式与 Java 生成对象的方式不同。 如果有人可以向我解释,我真的很感激。

【问题讨论】:

  • __init__ 不创建对象;它init初始化由__new__创建的对象。
  • 如果你来自 c++ 背景 m __init__ 提供与 struct 对象相同的功能

标签: python oop self


【解决方案1】:

为什么必须在方法定义和调用中显式使用“self”?

这个想法是从 Modula-3 借来的。事实证明它非常有用,原因有很多。

首先,更明显的是,您使用的是方法或实例属性而不是局部变量。阅读 self.x 或 self.meth() 可以绝对清楚地知道使用了实例变量或方法,即使您不知道类定义。在 C++ 中,您可以通过缺少局部变量声明来判断(假设全局变量很少或容易识别)——但在 Python 中,没有局部变量声明,因此您必须查找类定义当然。一些 C++ 和 Java 编码标准要求实例属性具有 m_ 前缀,因此这种显式性在这些语言中仍然有用。

其次,这意味着如果您想显式引用或调用特定类的方法,则不需要特殊的语法。在 C++ 中,如果要使用派生类中覆盖的基类中的方法,则必须使用 :: 运算符 - 在 Python 中,您可以编写 baseclass.methodname(self, )。这对于__init__() 方法特别有用,通常在派生类方法想要扩展同名的基类方法并因此必须以某种方式调用基类方法的情况下。

最后,对于实例变量,它解决了赋值的语法问题:因为 Python 中的局部变量(根据定义!)是那些在函数体中被赋值的变量(并且没有显式声明为全局变量),必须有某种方式告诉解释器赋值是指分配给实例变量而不是局部变量,并且最好是语法上的(出于效率原因)。 C++ 通过声明来做到这一点,但 Python 没有声明,很遗憾不得不为此目的引入它们。使用显式 self.var 很好地解决了这个问题。同样,对于使用实例变量,必须编写 self.var 意味着在方法中对非限定名称的引用不必搜索实例的目录。换句话说,局部变量和实例变量存在于两个不同的命名空间中,你需要告诉 Python 使用哪个命名空间。

参考:https://docs.python.org/3/faq/design.html#why-must-self-be-used-explicitly-in-method-definitions-and-calls

【讨论】:

    猜你喜欢
    • 2013-04-18
    • 1970-01-01
    • 2017-03-09
    • 2020-01-30
    • 2012-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-18
    相关资源
    最近更新 更多