【问题标题】:Does Python's __init__(self) method get defined by the interpreter before all other class/instance methods? [duplicate]Python 的 __init__(self) 方法是否在所有其他类/实例方法之前由解释器定义? [复制]
【发布时间】:2016-10-14 08:19:17
【问题描述】:

#例如:

class example(object):

    def someFunction():
        print("I am some function")

    def __init__(self,x,y):
        self.x = x
        self.y = y
        someFunction()

为什么这段代码会产生 someFunction is not defined 的错误? 是不是因为 python 的解释器在执行 def someFunction 代码之前执行了 def init 代码块?我认为python的执行顺序是自上而下的方法。任何见解将不胜感激。

【问题讨论】:

  • 我不太清楚你在这里问什么。您是否有意省略了someFunction() 上的self 参数,并且想知道为什么__init__() 看不到封闭范围内的名称?或者您想知道调用方法的正确方法是什么?后一个问题的答案是安迪·海登在下面的答案。前一个问题的答案有点复杂。
  • 你能解释一下为什么 __init__() 看不到封闭范围内的名字,这就是我想问的。
  • 正是我要找的 Sven,谢谢

标签: python python-2.7 python-3.x interpreter


【解决方案1】:

Andy Hayden 的回答为您提供了必要的解决方案,但我认为您可能会欣赏更多专门针对您的问题的背景知识。请注意,这描述了所谓的“新”对象模型,尽管旧模型(从 pre-2.2 天开始,仍然是 Python 2 中的默认值,操作几乎相同)。

当解释器编译一个类时,会读取整个类主体并将定义(在您的情况下为someFunction__init__)保存在字典中。它构建一个“基类”列表(它继承的类),然后调用该类的 metaclass(除非您采取特殊措施,在 Python 中,您的类的元类将是内置的键入 type) 并使用类名、基类列表和表示类名称空间的字典作为参数。

在 Python 3 中,新模型是默认模型,您可以使用 class 声明的关键字参数设置类的元类。这使您可以验证我的断言。考虑以下程序:

class print_args(type):
    def __new__(cls, name, bases, name_space):
        print("class:", cls)
        print("Declaring class", name)
        print("Bases:", bases)
        print("Namespace:", name_space)
        return type.__new__(cls, name, bases, name_space)

class A: pass

class B: pass

print("Defining C")
class C(A, B, metaclass=print_args):
    CVar = "class attribute"
    def myMethod(self, a):
        return self.N, self.CVar
    def __init__(self, N):
        self.N = N
print("Creating c")
c = C(42)
print(c.CVar, C.CVar)
print(C.__dict__)
print(c.__dict__)
c.CVar = "instance attribute"
print(c.CVar, C.CVar)
print(c.__dict__)

print_args 类是一个简单的元类,它通过从 type 继承并在打印后将实际工作委托给 type.__new__ 来模仿 type 的操作。当C 类被声明时,它会输出

Defining C
class: <class '__main__.print_args'>
Declaring class C
Bases: (<class '__main__.A'>, <class '__main__.B'>)
Namespace: {'__qualname__': 'C', '__module__': '__main__', '__init__': <function C.__init__ at 0x10778bbf8>, 'myMethod': <function C.myMethod at 0x10778bc80>, 'CVar': 'class attribute'}

请注意,这一切都发生在声明 C 类时 - 您可以通过下一行输出来判断这一点。另请注意,打印的值告诉您传递给type.__new__ 的内容。程序接下来创建一个C 实例,并演示类属性也可以作为实例属性访问——方法解析顺序也适用于属性查找——事实上,该实例也可以访问AB classes 有没有。

Creating c
class attribute class attribute

此时C 类的__dict__ 如下所示:

{'CVar': 'class attribute',
 '__module__': '__main__',
 '__doc__': None,
 '__init__': <function C.__init__ at 0x10778bbf8>,
 'myMethod': <function C.myMethod at 0x10778bc80>}

其实例的字典如下所示:

{'N': 42}

它只包含实例属性N。但是在将值绑定到c.CVar 之后,我们可以看到实例属性现在与类属性不同。

instance attribute class attribute

更新后的实例__dict__ 确认了这一点。

{'CVar': 'instance attribute', 'N': 42}

希望这能让您更深入地了解声明类时会发生什么,以及实例和类之间的关系。

【讨论】:

  • 欣赏进一步的见解。
【解决方案2】:

你也需要在它前面加上self

def __init__(self,x,y):
    self.x = x
    self.y = y
    self.someFunction()

【讨论】:

  • 方法上还有一个self 参数。
  • 那么,你不能在实例方法中调用不使用self参数的函数吗?
  • @7alman 这是python101 ...也许您应该从一些有关python类的教程开始...如果您为此苦苦挣扎,以后会遇到更多问题(例如,一旦将其修复为self.someFunction() 你可能会发现你得到一个关于传递一个参数的错误,但该方法没有除参数
  • 这不是 Joran 被问的问题,我知道实例方法需要传递 self 参数,并且必须在实例上调用它们,请看上面 sven 的评论。
  • @7alman 不,您必须传递 self 参数(使用 self.XXX)。 Sven 是正确的,someFunction 应该定义为def someFunction(self): ...@staticmethod someFunction(): ...
猜你喜欢
  • 2017-09-01
  • 1970-01-01
  • 2017-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-11
  • 1970-01-01
相关资源
最近更新 更多