This code:
class a:
def __init__(self):
print("a here")
class b(a):
def __init__(self):
print("b here")
super().__init__()
B = b()
class a:
def __init__(self):
print("NEW a here")
BB = b()
produces this output:
b here
a here
b here
a here
Why?
If I change the super().init() in class b to a.init(self), it works correctly.
Class b holds a reference to its base class(es). That reference is created when the class is created, not looked up by name later on when super gets called. Thus, the "incorrect" behavior that you're seeing is actually the expected behavior. To change what class b sees as its base class, you need to redefine b too.
I think that this is happening because class b is still inheriting from the original class a that you defined.
You can check this by printing out the ids of the a classes
id(a)
id(b.__bases__[0])
I have a few classes set up that hold values for an application. I'd like to import them into the same class, however, the values in the last class are being ignored. Here is a simple example.
class A:
def __init__(self):
self.testA = 'A'
class B:
def __init__(self):
self.testB = 'B'
class C(A, B):
def __init__(self):
super().__init__()
print(self.testA)
print(self.testB)
test = C()
The above will work only if I do not include the print(self.testB) the variable in class 'B'. I'd like to access the data from Class B as well. How? Thank you.
class A:
print('class A')
def __init__(self):
print('---1')
print('1')
class B:
print('class B')
def __init__(self):
print('sss')
class C(A,B):
print('222')
def __init__(self):
return 11
class D(B,A):
print('pp')
d1 = D()
I'm getting output:
class A
class B
222
pp
sss
Why 222 is getting print without creating an object for Class C.
Remove d1 = D() and you'll see that the first three lines are still printed.
This is because unlike function definitions, class definitions are not deferred until the class is constructed. The interpreter instead executes each line as it parses it.
I'm not the strongest pillar when it comes to class inheritance, so here goes my rather silly question. Following the code below, I would logically assume that after the 'super' call, the pointer arrives at self.example() which would in turn refer to the 'example' method in the same class and value 20 will be printed.
class A(object):
def __init__():
self.example()
def example(self):
print(20)
class B(A):
def __init__():
super().__init__()
def example(self):
print(10)
x = B()
Result : 10
This clearly isn't the case and 10 is printed instead. Could someone please shed some light on the mysterious world of class inheritance.
class A(object):
def __init__():
self.example()
def example(self):
print(20)
class B(A):
def __init__():
super().__init__()
x = B()
x.example()
Look for this, at example.
When you inherit B, from A, then method example is inheritated to B, you not must rewrite this to B. Of course still you can write this method for B, then you will override 'A' method, for objects of class B.
You also can use one class to Inheritance with many others:
class Base(object):
def __init__(self):
print("Base created")
class ChildA(Base):
def __init__(self):
Base.__init__(self)
class ChildB(Base):
def __init__(self):
super(ChildB, self).__init__()
ChildA()
ChildB()
ChildB have another call which is equivalent to that used in example above.
I'm trying to dynamically create a class using type() and assign an __init__ constructor which calls super().__init__(...); however, when super() gets called I receive the following error:
TypeError: super(type, obj): obj must be an instance or subtype of type
Here is my code:
class Item():
def __init__(self, name, description, cost, **kwargs):
self.name = name
self.description = description
self.cost = cost
self.kwargs = kwargs
class ItemBase(Item):
def __init__(self, name, description, cost):
super().__init__(name, description, cost)
def __constructor__(self, n, d, c):
super().__init__(name=n, description=d, cost=c)
item = type('Item1', (ItemBase,), {'__init__':__constructor__})
item_instance = item('MyName', 'MyDescription', 'MyCost')
Why is super() inside the __constructor__ method not understanding the object parameter; and how do I fix it?
Solution 1: Using cls = type('ClassName', ...)
Note the solution of sadmicrowave creates an infinite loop if the dynamically-created class gets inherited as self.__class__ will correspond to the child class.
An alternative way which do not have this issue is to assigns __init__ after creating the class, such as the class can be linked explicitly through closure. Example:
# Base class
class A():
def __init__(self):
print('A')
# Dynamically created class
B = type('B', (A,), {})
def __init__(self):
print('B')
super(B, self).__init__()
B.__init__ = __init__
# Child class
class C(B):
def __init__(self):
print('C')
super().__init__()
C() # print C, B, A
Solution 2: Using MyClass.__name__ = 'ClassName'
An alternative way to dynamically create class is to define a class inside the function, then reassign the __name__ and __qualname__ attributes:
class A:
def __init__(self):
print(A.__name__)
def make_class(name, base):
class Child(base):
def __init__(self):
print(Child.__name__)
super().__init__()
Child.__name__ = name
Child.__qualname__ = name
return Child
B = make_class('B', A)
class C(B):
def __init__(self):
print(C.__name__)
super().__init__()
C() # Display C B A
Here is how I solved the issue. I reference the type() method to dynamically instantiate a class with variable references as such:
def __constructor__(self, n, d, c, h):
# initialize super of class type
super(self.__class__, self).__init__(name=n, description=d, cost=c, hp=h)
# create the object class dynamically, utilizing __constructor__ for __init__ method
item = type(item_name, (eval("{}.{}".format(name,row[1].value)),), {'__init__':__constructor__})
# add new object to the global _objects object to be used throughout the world
self._objects[ item_name ] = item(row[0].value, row[2].value, row[3].value, row[4].value)
There may be a better way to accomplish this, but I needed a fix and this is what I came up with... use it if you can.