假设我的模块是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中有功能声明。谢谢!
答案 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你想要的地方(因为它在运行时调用)。