How do I get attributes from parent class constructor in child class constructor?
class A:
def __init__(number):
self.number = number
class B(A):
def __init__():
self.number = A.number?
test = B(A)
print(test.number)
I don't know how to do it so as not to pass arguments to the child class.
I think you have something wrong there. The correct code for parent / derived class would be
class A:
def __init__(self, number):
self.number = number
class B(A):
def __init__(self, number):
super().__init__(0) # Initialize parent class.
self.number = number
# Instantiate a B object
test = B(7)
# Print the property
print(test.number)
That will always produce '7' in the screen. Now both A and B __init__ methods refer to the same 'number' property of the object, so, it does not make much sense both classes setting the same property upon initialization. If you change B's __init__ method for:
class B(A):
def __init__(self, number):
self.number = number
super().__init__(0) # Initialize parent class.
Then print(test.number) would always print '0' instead of anything you passed on creation because you are overwriting the property.
The typical code would rather be:
class A:
def __init__(self, number):
self.number = number
class B(A):
def __init__(self, number):
super().__init__(number)
This way the derived class initializes the parent in a meaningful way.
Related
i have the following code:
class A:
def __init__(self, name,val):
self.name = name
self.val = val
class B(A):
super(A)__init__ // here i want to have just a variable self.name. that means val=0
def outputName(self):
print(f"name = {self.name}")
class C(A):
super(A)__init__ // here i want to habe just a variable self.val. that means name = 0
def outputVal(self):
print(f"val= {self.val}")
n = B('martin')
v = C(25)
outputName(n)
outputVal(v)
My Question: How can i specify that i just want name in class B in val in class C?
an another solution that i know is e.g. n=B('Martin',0) and v =C(0,25) but i think it is nonesense
Any idea how i can right it better?
Here you just need to feed a specific variable to super(). Minor notes: since you have a single inheritance, you don't need to specify which class you're instantiating when calling super(). Also, don't forget the "dot" in super().__init__() and, most importantly, don't forget to define __init__() in subclasses:
class A:
def __init__(self, name, val):
self.name = name
self.val = val
class B(A):
def __init__(self, name):
super().__init__(name=name, val=None) # Only initialise name variable of the base class
def outputName(self):
print(f"name = {self.name}")
class C(A):
def __init__(self, val):
super().__init__(name=None, val=val) # Same here but with val instead.
def outputVal(self):
print(f"val= {self.val}")
Or, alternatively, as Tim has suggested you can make class A have default values in init:
class A:
def __init__(self, val=None, name=None):
I have this two classes that I needed to divide, though they share some common features. Is it possible to access first class' self.value from the second class? Please look at the pseudo code, surely more understandable then my words.
class a:
def __init__(self):
self.value = 45
class b(a):
def __init__(self):
self.other_value = #this should be self.value from class a
You need call the parent constructor first
class B(A):
def __init__(self):
super().__init__()
print(self.value)
you should call the parent constructor:
class b(a):
def __init__(self):
a.__init__(self)
#now you can use it with self.value
I want to use the super function to write a string into a list of a specific instance of a parent object. Here's my code so far:
#!/usr/bin/env python
# test.py
class Master(object):
def __init__(self):
pass
class Sub1(Master):
list = []
def __init__(self):
pass
class Sub2(Sub1):
def __init__(self, name):
super(Sub2, self).list.append(name)
m = Master()
m.foo = Sub1()
m.foo.bar = Sub2('something')
m.bla = Sub1()
m.bla.blub = Sub2('else')
print(m.foo.list)
In this case the output is of course
['something', 'else']
However I want it to be just 'something'.
How can I achieve this?
I tried:
class Sub1(Master):
def __init__(self):
self.list = []
Which yields:
AttributeError: 'super' object has no attribute 'list'
Is there an easy solution?
As you have noted, if you define lst as a class attribute in Sub1, it is shared among all instances, which is not what you want. So you have to define lst as an instance attribute in Sub1 but then it has to be managed by an instance of Sub1 and not an instance of Sub2. Here is a modified code that offers what you expect:
class Master(object):
def __init__(self):
super().__init__()
class Sub1(Master):
def __init__(self):
super().__init__()
self.lst = []
def add(self, item):
self.lst.append(item.name)
class Sub2(Sub1):
def __init__(self, name):
super().__init__()
self.name = name
m = Master()
m.foo = Sub1()
m.foo.add(Sub2('something'))
m.bla = Sub1()
m.bla.add(Sub2('else'))
print(m.foo.lst)
print(m.bla.lst)
Here is the ouput:
['something'] <-- m.foo.lst
['else'] <-- m.bla.lst
Rem1: When using super() the whole class hierarchy has to be collaborative (i.e. use super() in the constructor).
Rem2: In Python3, super() is equivalent to super(classname, self)
Rem3: Don't use list as a variable name (it is a builtin type)
Rem4: My code stores only the name attribute in the list to mimic the example your gave, but I guess that in real life you would rather store instances of Sub2 in that list. To do so, simply remove the .name in the addfunction.
EDIT : Thinking a bit more about my answer, I came to another solution that may be closer to your initial attempt. Let me know which one works best for your actual problem...
class Master(object):
def __init__(self):
super().__init__()
class Sub1(Master):
def __init__(self):
super().__init__()
self.lst = []
class Sub2(Sub1):
def __init__(self, parent, name):
super().__init__()
parent.lst.append(name)
m = Master()
m.foo = Sub1()
m.foo.bar = Sub2(m.foo, 'something')
m.bla = Sub1()
m.bla.blub = Sub2(m.bla, 'else')
print(m.foo.lst)
print(m.bla.lst)
Your actual problem seems to be in the way you initialize list.
You need to assign it in __init__(), not within the class body, to avoid it being shared between all instances of the class (see Static class variables in Python).
class Sub1(Master):
def __init__(self):
self.list = []
class TextToNumbers():
def __init__(self, number):
self.text = str(number)
self.chunks = parse_text_to_chunks(self.text)
def parse_text_to_chunks(text_to_parse):
#stuff
This is an example of a class I'm building. I want it to define some variables with class methods on initialization. (at least I think that is what I want) I think if I talk about my end goal it is that I have a set of complex information that needs to be available about a class directly at initialization. How do I call a class method at initialization, to define a class variable?
If you are looking for a way to call an instance method during initialization, you can use self to call that like this
class TextToNumbers():
def __init__(self, number):
self.text = str(number)
self.chunks = self.parse_text_to_chunks(self.text)
print self.chunks
def parse_text_to_chunks(self, text_to_parse):
# 1st parameter passed is the current INSTANCE on which this method is called
self.var1 = text_to_parse[1:]
return self.var1
TextToNumbers(123)
And I believe this is what you really need. But if you want a class method
class TextToNumbers():
def __init__(self, number):
self.text = str(number)
self.chunks = TextToNumbers.parse_text_to_chunks(self.text)
print self.chunks
#classmethod
def parse_text_to_chunks(cls, text_to_parse):
# 1st parameter passed is the current CLASS on which this method is called
cls.var1 = text_to_parse[1:]
return cls.var1
TextToNumbers(123)
But there is no point in creating a class method to initialize a class variable in __init__, since a class variable is shared by all the instances of the class, calling from __init__ will overwrite everytime an object is created.
Is it possible to leave a parent class unspecified until an instance is created?
e.g. something like this:
class SomeParentClass:
# something
class Child(unspecifiedParentClass):
# something
instance = Child(SomeParentClass)
This obviously does not work. But is it possible to do this somehow?
You can change the class of an instance in the class' __init__() method:
class Child(object):
def __init__(self, baseclass):
self.__class__ = type(self.__class__.__name__,
(baseclass, object),
dict(self.__class__.__dict__))
super(self.__class__, self).__init__()
print 'initializing Child instance'
# continue with Child class' initialization...
class SomeParentClass(object):
def __init__(self):
print 'initializing SomeParentClass instance'
def hello(self):
print 'in SomeParentClass.hello()'
c = Child(SomeParentClass)
c.hello()
Output:
initializing SomeParentClass instance
initializing Child instance
in SomeParentClass.hello()
Have you tried something like this?
class SomeParentClass(object):
# ...
pass
def Child(parent):
class Child(parent):
# ...
pass
return Child()
instance = Child(SomeParentClass)
In Python 2.x, also be sure to include object as the parent class's superclass, to use new-style classes.
You can dynamically change base classes at runtime. Such as:
class SomeParentClass:
# something
class Child():
# something
def change_base_clase(base_class):
return type('Child', (base_class, object), dict(Child.__dict__))()
instance = change_base_clase(SomeParentClass)
For example:
class Base_1:
def hello(self):
print('hello_1')
class Base_2:
def hello(self):
print('hello_2')
class Child:pass
def add_base(base):
return type('Child', (base, object), dict(Child.__dict__))()
# if you want change the Child class, just:
def change_base(base):
global Child
Child = type('Child', (base, object), dict(Child.__dict__))
def main():
c1 = add_base(Base_1)
c2 = add_base(Base_2)
c1.hello()
c2.hello()
main()
Result:
hello_1
hello_2
Works well in both python 2 and 3.
For more information, see the related question How to dynamically change base class of instances at runtime?