Reputation: 17468
Suppose my module is myclass.py
, and here is the code:
#!/usr/bin/env python
# coding=utf-8
class A(object):
b = B()
def __init__(self):
pass
class B(object):
pass
and import it
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
I know that if I define the class B above the class A, it is ok, there is no error. But, I don't want do that, are there any other methods to solve this. And I know that in C, there is function declaration.Thank you!
Upvotes: 2
Views: 807
Reputation: 1141
Is there any good reason to do what you are doing? In general this is quite dangerous pattern in Python.
In your case
class A(object):
b = B()
def __init__(self):
pass
You are binding an instance of B to the class A, which means that every instance of class A will share the same instance of class B. It's a case you must then handle properly.
In general you don't want this, If you want each instance of A to be related to an instance of B, you must make the assignment inside __init__
class A(object):
def __init__(self):
self.b = B()
In these case it doesn't meter where class B is defined, since it's instantiated at run time.
Again beware that the semantic is very different in the two cases (if you know Java, the former is more like defining a static
attribute).
About:
And I know that in C, there is function declaration
You shouldn't make too much parallels with a language like C, which is very different on many aspects, most important: it's a compiled language, that means that you code is parsed in it whole before being translated to machine language, that's why you can make function declaration and have your namespace populated regardless of the order you define things.
Python is an interpreted language, which means basically that each statement is translated when it's called and a class declaration is called when the module is imported.
So to recap: if you really need a class bound instance, you have to declare class B before class A, else you must instantiate B inside __init__
, then you can declare B wherever you want (since it's called at runtime).
Upvotes: 0
Reputation: 728
It should work if you do it like so:
class A(object):
def __init__(self):
self.b = B()
class B(object):
pass
EDIT: You can do it like this if you want to write all the definitions of the class after you have written class A.
class B:
pass
class A(object):
b = B()
def __init__(self):
pass
class B(object):
def __init__(self):
pass
EDIT 2: Ignore the above solution, it doesn't work.
Upvotes: 0
Reputation: 6288
The class definition is a statement. When statement AA
is executed, The statement of BB
is not executed yet. Therefore, There is no class B
yet and you get NameError: name 'B' is not defined
class A(object):
b = B() # <== AA
def __init__(self):
pass
class B(object): # <== BB
pass
To fix it:
You can change the order of classes:
class B(object):
pass
class A(object):
b = B()
def __init__(self):
pass
You can move the statement which use the class B
to classmethod
and call it after the the defintion of class B
:
class A(object):
@classmethod
def init(cls):
cls.b = B()
def __init__(self):
pass
class B(object):
pass
A.init()
Upvotes: 8