在所有其他类/实例方法之前,Python的__init __(self)方法是否由解释器定义?

时间:2016-06-13 19:35:00

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

#例如:

class example(object):

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

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

为什么此代码会生成someFunction未定义的错误? 是因为python的解释器在执行def someFunction 代码之前执行了def init 代码块吗?我认为python的执行顺序是自上而下的方法。任何见解都将不胜感激。

2 个答案:

答案 0 :(得分:1)

您还需要在其前面添加self

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

答案 1 :(得分:0)

Andy Hayden的回答为您提供了必要的解决方案,但我认为您可能会欣赏一些专门针对您的问题的背景知识。请注意,这描述了所谓的" new"对象模型,虽然旧模型(从2.2天之前开始,仍然是Python 2中的默认模式,运行方式几乎相同)。

当解释器编译类时,读取整个类主体并将定义(在您的情况下,someFunction__init__)保存在字典中。它构建了一个"基类列表" (它继承的类),然后它调用类的元类(除非你采取特殊的行动,在Python中你的类'元类将是内置类型{{ 1}})带有类名,基类列表和表示类的名称空间作为参数的字典。

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

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__类时,输出

C

请注意,当声明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'} 的内容。该程序接下来创建一个type.__new__实例,并演示class属性也可以作为实例属性访问 - 方法解析顺序也应用于属性查找 - 实际上该实例也可以访问{{{已经有1}}和C个类。

A

此时B类的Creating c class attribute class attribute 如下所示:

__dict__

并且其实例的字典如下所示:

C

它仅包含实例属性{'CVar': 'class attribute', '__module__': '__main__', '__doc__': None, '__init__': <function C.__init__ at 0x10778bbf8>, 'myMethod': <function C.myMethod at 0x10778bc80>} 。但是在将值绑定到{'N': 42} 之后,我们可以看到实例属性现在与class属性不同。

N

通过对实例c.CVar的更新了解来确认这一点。

instance attribute class attribute

希望这会让您更深入地了解声明类时会发生什么,以及实例和类是如何相关的。