为什么我无法在同一模块中实例化实例?

时间:2016-08-17 06:27:01

标签: python

假设我的模块是myclass.py,这里是代码:

#!/usr/bin/env python
# coding=utf-8

class A(object):
    b = B()
    def __init__(self):
        pass

class B(object):
    pass

并导入

In [1]: import myclass
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-1-e891426834ac> in <module>()
----> 1 import myclass

/home/python/myclass.py in <module>()
      2 # coding=utf-8
      3 
----> 4 class A(object):
      5     b = B()
      6     def __init__(self):

/home/python/myclass.py in A()
      3 
      4 class A(object):
----> 5     b = B()
      6     def __init__(self):
      7         pass

NameError: name 'B' is not defined

我知道如果我在A类之上定义B类,那就没问题,没有错误。但是,我不想这样做,有没有其他方法可以解决这个问题。我知道在C中有功能声明。谢谢!

3 个答案:

答案 0 :(得分:8)

类定义是一个声明。执行语句AA时,BB的语句尚未执行。因此,目前还没有课程B,您可以获得NameError: name 'B' is not defined

class A(object):
    b = B()              # <== AA
    def __init__(self):
        pass
class B(object):         # <== BB
    pass

修复它:

您可以更改班级的顺序:

class B(object):
    pass

class A(object):
    b = B()
    def __init__(self):
        pass

您可以将使用课程B的语句移至classmethod,并在课程B定义后调用它:

class A(object):

    @classmethod
    def init(cls):
        cls.b = B()

    def __init__(self):
        pass

class B(object):
    pass

A.init()

答案 1 :(得分:0)

如果您这样做,它应该可以工作:

class A(object): 
    def __init__(self): 
        self.b = B() 

class B(object): 
    pass

编辑:如果您想在编写A类后编写课程的所有定义,就可以这样做。

class B:
    pass

class A(object): 
    b = B()
    def __init__(self): 
        pass 

class B(object): 
    def __init__(self):
        pass

编辑2:忽略上述解决方案,它不起作用。

答案 2 :(得分:0)

有什么好的理由去做你正在做的事情吗?一般来说,这是Python中非常危险的模式。

在你的情况下

class A(object):
    b = B()
    def __init__(self):
        pass

您正在将B的实例绑定到A类,这意味着A类的每个实例都将共享B类的相同实例。这是您必须正确处理的情况。

一般情况下,您不希望这样,如果您希望A的每个实例与B的实例相关,您必须在__init__

中进行分配
class A(object): 
    def __init__(self): 
        self.b = B() 

在这些情况下,它不计量定义B类的位置,因为它在运行时实例化。

再次要注意两种情况下的语义是非常不同的(如果你了解Java,前者更像是定义static属性)。

关于:

  

我知道在C中有函数声明

你不应该像C这样的语言有太多相似之处,这在许多方面都是非常不同的,最重要的是:它是一种编译语言,这意味着你的代码在被翻译之前被解析为整体/ em>到机器语言,这就是为什么你可以进行函数声明并填充你的命名空间而不管你定义的顺序。

Python是一种解释型语言,这意味着每个语句在被调用时都被翻译,并且在导入模块时会调用类声明。

所以回顾一下:如果你真的需要一个类绑定实例,你必须在A类之前声明B类,否则必须__init__内实例化B,然后你可以声明B你想要的地方(因为它在运行时调用)。