2016-06-13 35 views
1

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

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 init代码块才执行def some函数代码?我认为python的执行顺序是一种自顶向下的方法。任何洞察力将不胜感激。

+4

我不清楚你在这里问什么。你是否故意忽略'someFunction()'的'self'参数,并想知道为什么'__init __()'不能从封闭范围看到名字?或者你想知道调用方法的正确方法是什么?下一个问题的答案是Andy Hayden的答案如下。前一个问题的答案有一点涉及。 –

+0

您能否解释为什么__init __()无法从封闭范围看到名称,这正是我想要问的。 – 7alman

+1

相关:http://stackoverflow.com/questions/9505979/the-scope-of-names-defined-in-class-block-doesnt-extend-to-the-methods-blocks http://stackoverflow.com/问题/ 13937637/why-doesnt-class-start-a-new-scope-like-def-does –

回答

1

您需要self太前缀是:

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

以及方法中的'self'参数。 –

+0

那么,你不能在实例方法中调用不使用自参数的函数? – 7alman

+0

@ 7alman这是python101 ...也许你应该从一些关于python类的教程开始......如果你正在为此付出努力,那么你以后会遇到更多问题(例如,将它修复为self.someFunction()你可能会发现你会得到一个关于正在传递的参数的错误,但是这个方法除了参数 –

0

安迪·海登的答案给你必要的修复,但我想你可以欣赏专门针对你的问题多一点背景。请注意,这里描述了所谓的“新”对象模型,尽管旧模型(从2.2天前开始,仍然是Python 2中的默认模式,运行几乎相同)。

当解释器编译一类是读取整个类体,并在字典中保存定义(在你的情况,someFunction__init__)。它建立了一个“基类”(它继承的类)的列表,然后它调用类的元类(除非你采取特殊的行动,在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__的动作。当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类中的属性是任何。

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} 

希望这会给你更多的洞察,当你声明类如何实例和类相关的情况,以及。

+0

欣赏进一步的洞察。 – 7alman

相关问题