I have a parent class and several subclasses. Every subclass accepts different parameters, but all subclasses have some common parameters. I don't want to write the "common parameters" for every subclass. How can I do this?
class Parent:
def __init__(self, name):
self.name = name
class Subclass(Parent):
def __init__(self, age):
self.age = age
def do_something(self):
print(self.name)
instance = Subclass(name="Test", age=42)
instance.do_something() # 42
You can try this:
class Subclass(Parent):
def __init__(self, **kwargs):
super().__init__(kwargs['name'])
self.age = kwargs['age']
def do_something(self):
print(self.name)
And then use this just like you did in the question:
instance = Subclass(name="Test", age=42)
I use it in the following manner
You can add as many child classes as you want
class ParentClass(object):
def __init__(self,baseArgs):
self.var1=baseArgs['var1']
self.var2=baseArgs['var2']
self.var3=baseArgs['var3']
class ChildClass(ParentClass):
def __init__(self,childArgs,baseArgs):
super(ChildClass, self).__init__(baseArgs)
self.cvar1=childArgs['cvar1']
self.cvar2=childArgs['cvar2']
a=ChildClass({'cvar1':40,'cvar2':50},{'var1':10,'var2':20,'var3':30})
print(a.var1)
# 10
Related
I just learned about object oriented programming in python, and there was something that didn't make sense to me.
# 1st example
class Bird:
def __init__(self, name):
self.name = name
def fly(self):
print(f"{self.name.title()} is flying.")
class Penguin(Bird):
def fly(self):
print("A penguin can't fly.")
a_penguin = Penguin('rico')
print(a_penguin.name)
a_penguin.fly()
# 2nd example
class Bird:
def __init__(self, name):
self.name = name
def fly(self):
print(f"{self.name.title()} is flying.")
class Penguin(Bird):
def __init__(self, name):
super().__init__(name)
def fly(self):
print("A penguin can't fly.")
a_penguin = Penguin('rico')
print(a_penguin.name)
a_penguin.fly()
Both of examples above do the same thing, and my question is that is it necessary to call super() when creating child class ?
If your __init__() function doesn't do anything at all different from the superclass's version, then it should be fine for you to omit it - like any other method, the subclass will inherit the superclass's implementation.
However, if your __init__() function did more stuff, then you'd want to call the superclass's __init__() and then do your class's additional stuff:
class Bird:
def __init__(self, name):
self.name = name
def fly(self):
print(f"{self.name.title()} is flying.")
def run(self):
print(f"{self.name.title()} is walking.")
class Ostrich(Bird):
def __init__(self, name, speed):
super().__init__(name)
self.speed = speed
def fly(self):
print(f"An ostrich cannot fly.")
def run(self):
print(f"{self.name.title()} is running at {self.speed} kph!")
I'm learning simple python inheritance and I want that one of my parent class method default argument is changed conditionally to one of my subclass argument value, and I don't know if this is possible.
Here is an example of what I'd like to do:
class Parent(object):
def __init__(self, name):
self.name = name
def doSomething(self, name, strict = True):
if strict:
return self.name
else:
return name
class Child(Parent):
def __init__(self, name, **kwargs):
super(Child, self).__init__(name)
if 'changeBehavior' in kwargs:
# Here is the thing:
# Can I change the default value of strict to kwargs['changeBehavior']
# in a way that when I later call doSomething(), it will behave according
# to its new default behavior?
def doSomething(self, name, strict = kwargs['changeBehavior']):
super(Child, self).doSomething(strict = kwargs['changeBehavior'])
If this can be done in this way, is there any other method to do so?
Thanks
You can use partial.
from functools import partial
class Parent(object):
def __init__(self, name):
self.name = name
def doSomething(self, name, strict=True):
print('Got strict={}'.format(strict))
if strict:
return self.name
else:
return name
class Child(Parent):
def __init__(self, name, **kwargs):
super().__init__(name)
change_behavior = kwargs.get('changeBehavior')
if change_behavior is not None:
self.doSomething = partial(self.doSomething, strict=change_behavior)
p = Parent('name')
c = Child('name', changeBehavior=False)
p.doSomething('name')
c.doSomething('name')
outputs
Got strict=True
Got strict=False
When I try to do this I get the error NameError: global name 'name' is not defined is there an easy work around?
class C(object):
def __init__(self, name):
self.name = name
class D(C):
def __init__(self):
C.__init__(self, name)
obj1 = D()
In class D, when you initialize it from C, you're not passing a value to the initialization of C, so it raises a NameError when it tries to pass it. You either need to allow D to take a value name and then pass it to C,
class C(object):
def __init__(self, name):
self.name = name
class D(C):
def __init__(self, name):
C.__init__(self, name) # name must be passed on initialization of D.
or define a default value for name in D.
class C(object):
def __init__(self, name):
self.name = name
class D(C):
def __init__(self, name='Monty Python'):
C.__init__(self, name) # allows you to only pass a name if you want to.
Instead of using the parent class name use super() here so that later if you need to you can enable things like mixins, interfaces, abstract classes, etc.
Then you can also allow for those keyword arguments in the parent class to be used in the child class like this:
class D(C):
def __init__(self,**kwargs):
super(D,self).__init__(**kwargs)
Example usage:
In [349]: obj1 = D(name='test')
In [350]: obj1.name
Out[350]: 'test'
never ever hard code the metho you inheriting instead of do super() by this if you want to change the method just change in the class name will be sufficient
there is no need to give argument's to super() in python3
class C(object):
def __init__(self, name):
self.name = name
class D(C):
def __init__(self, name):
super().__init__(self, name)
I need to change a inherited class to another inherited class where only one of the attributes has changed
i need to "Promote" a Cashier to a Manager, the only thing that is suppose to change is the salary
both Cashier and Manager are inherited classes of Employee (where I'm not sure if I'm using the "hasattr" function the right way)
class Employee:
def __init__(self,name):
self.name=name
if(hasattr(self,'shifts')==False):
self.shifts=[]
class Manager(Employee):
def __init__(self,name,salary):
Employee.__init__(self,name)
self.salary=salary
class Cashier(Employee):
def __init__(self,name,salarey_per_hours):
Employee.__init__(self,name)
self.salery_per_hours=salarey_per_hours
def promote(self,salary):
return Manager(self.name,salary)
P.s It's my first time uploading a question
What you could do is create the addition method of your class and add self to the manager class you are returning like so:
class Employee(object):
def __init__(self, name):
self.name=name
if not hasattr(self, 'shifts'):
self.shifts = []
def __add__(self, other):
if isinstance(other, Employee):
for key, value in other.__dict__.items():
if key == 'salary':
continue
self.__setattr__(key, value)
return self
class Manager(Employee):
def __init__(self, name, salary):
super().__init__(name)
self.salary = salary
class Cashier(Employee):
def __init__(self,name,salary):
super().__init__(name)
self.salary = salary
def promote(self, salary):
manager = Manager(self.name, salary)
manager += self
return manager
cashier = Cashier('hank', 22)
cashier.shifts = [1, 2, 3, 4]
print(cashier.shifts)
promoted_cashier = cashier.promote(30)
print(promoted_cashier.shifts)
Here you make sure that everything except the "salary" is transferred to the promoted class. And since both the Manager and the Cashier are an Employee this should work nicely. I changed your code a bit to what I'm used to since there was some unusual coding with you Calling Employee in the init which I assumed you did not explicitly needed. Sorry if that was not the case.
You can change the object's class by obj.__class__ to the another class by
doing obj.__class__ = SomeClass
Beware that is can lead to strange behaviours if it is handled incorrectly.
by modifying your code
class Employee:
def __init__(self,name):
self.name=name
if(hasattr(self,'shifts')==False):
self.shifts=[]
class Manager(Employee):
def __init__(self,name,salary):
Employee.__init__(self,name)
self.salary=salary
class Cashier(Employee):
def __init__(self,name,salarey_per_hours):
Employee.__init__(self,name)
self.salery_per_hours=salarey_per_hours
def promote(self,salary):
self.__class__ = Manager
# return Manager(self.name,salary)
You can also take a look at this post changing the class of a python object (casting)
i am new to OOP.
i have a parent class with a method that i wanna access in my subclass. But i cannot figure out the right syntax for that. I cannot find a clear cut example anywhere
Members in the base class are simply available to the subclass as well (unless they are overwritten):
class Base:
def example (self):
print('This is in the base class')
class Subclass (Base):
def test (self):
self.example()
An object of type Subclass can now access example directly or indirectly:
>>> x = Subclass()
>>> x.test()
This is in the base class
>>> x.example()
This is in the base class
class Parent(object):
def __init__(self, name):
self.name = name
def output(self):
print self.name
class Child(Parent):
def __init__(self, name, age):
Parent.__init__(self, name)
self.age = age
def output(self):
super(Child, self).output()
print self.age
if __name__ == '__main__':
a = Parent("wy")
b = Child("zhang", 10)
a.output()
b.output()
You can try this code.