Dealing with classes (nested etc) does not look easy in Python, surprisingly! The following problem appeared to me recently and took sever
The code executed in a method runs in the local scope of that method. If you access an object that is not in this scope, Python will look it up in the global/module scope, NOT in the class scope or the scope of any enclosing class!
This means that:
A.a = 'a_b'
inside C.B.__init__
will set the class attribute of the global A
class, not C.A
as you probably intended. For that you would have to do this:
C.A.a = 'a_b'
Also, Python will not call parent methods if you override them in subclasses. You have to do it yourself.
The scoping rules mean that if you wanted to call the __init__
method of the parent class inside C.B.__init__
, it has to look like this:
C.A.__init__(self)
and NOT like this:
A.__init__(self)
which is probably what you've tried.
Nested classes seems so unpythonic, even if considered as factories. But to answer your question: There simply is no c5.a (instance of C.B). In the init-method of C.B you add to the CLASS C.A an attribute a, but not to C.B! The class A does already have an attribute a, if instantiated! But the object of class B (and even the class) doesn't!
You must also keep in mind, that __init__
is not an constructor like in C++ or Java! The "real constructor" in python would be __new__
. __init__
just initializes the instance of a class!
class A:
c = 'class-attribute'
def __init__(self):
self.i = 'instance-attribute'
So in this example c is a class-attribute, where i is an attribute of the instance.
Even more curios, is your attempt to add an attribute to the baseclass at the moment of the instantiation of the child-class. You are not getting a "late" inheritance-attribute that way. You simply add to the class A an additional attribute, which surprises me to even work. I guess you are using python 3.x?
The reason for this behaviour? Well, i guess it has to do with pythons neat feature that in python definitions are executed(AFAIK).
The same reason why:
def method(lst = []):
is almost ever a bad idea. the deafult-parameter gets bound at the moment of the definition and you won't generate a new list-object every-time you call the method, but reusing the same list-object.