GoingMyWay
GoingMyWay

Reputation: 17468

Why I can't instantiate a instance in the same module?

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

Answers (3)

Oberix
Oberix

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

Shubham Vasaikar
Shubham Vasaikar

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

napuzba
napuzba

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

Related Questions