how to call just one argument in the secondary function in python - python

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):

Related

Can I change the default behavior of my parent class method in my subclass method?

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

Python Class inheritance trouble

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)

Class Inheritance with parameters

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

How to convert all elements automatically in a list to a given object in Python

I want to create a list child class that can convert all elements automatically in it to an object no matter the element is create by init or append or extend. So by using both for loop or getitem. Here's a simple example code. What kind of magic method should I use?
class A():
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Object A with name {}'.format(self.name)
class CustomerList(list):
def __init__(self, *args):
super(CustomerList, self).__init__(*args)
c = CustomerList('a')
c.append('b')
c[0] # Object A with name a
c[1] # Object A with name b
for ele in c:
print(c)
# Object A with name a
# Object A with name b
are you asking how to override __append__?
class A():
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Object A with name {}'.format(self.name)
class CustomerList(list):
def __init__(self, *args):
super(CustomerList, self).__init__(*args)
def append(self,letter):
super(CustomerList, self).append(A(letter))
I guess???.. but as mentioned in the comments if you want
my_custom_list.extend(["A","B","V"])
my_custom_list[2] = "A"
to work you will need to override
def __setitem__(self,key,value): # cover a[2]='A'
super(CustomerList,self).__setitem__(key,A(value))
def extend(self,other):
super(CustomerList,self).extend([A(val) for val in other])
of coarse you probably then need to override both __add__,__iadd__ at a minimum as well
I think what you're trying to do is: When you append a new item into the list, it is an object of class A. What you can do is override list.append function:
class A():
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Object A with name {}'.format(self.name)
class CustomerList(list):
def __init__(self, *args):
super(CustomerList, self).__init__(*args)
def append(self, arg):
new_obj = A(arg)
self.insert(len(self), new_obj)

Overwrite base class attribute with #property of the same name

I am trying to subclass a python class and overwrite a regular attribute with a #property function. The catch is that I can't modify the parent class, and the api for the child class needs to look the same as the parent class (but behave differently). (So my question is different from this one in which the parent class also used a #property method to access the underlying attribute.)
The simplest possible example is
# assume this class can't be overwritten
class Parent(object):
def __init__(self, a):
self.attr = a
# how do I make this work?
class Child(Parent):
def __init__(self, a):
super(Child, self).__init__(a)
# overwrite access to attr with a function
#property
def attr(self):
return super(Child, self).attr**2
c = Child(4)
print c.attr # should be 16
This produces an error when the parent init method is called.
<ipython-input-15-356fb0400868> in __init__(self, a)
2 class Parent(object):
3 def __init__(self, a):
----> 4 self.attr = a
5
6 # how do I make this work?
AttributeError: can't set attribute
Hopefully it is clear what I want to do and why. But I can't figure out how.
This is easily fixed by adding a setter method
class Child(Parent):
def __init__(self, a):
self._attr = None
super(Child, self).__init__(a)
# overwrite access to a with a function
#property
def attr(self):
return self._attr**2
#attr.setter
def attr(self, value):
self._attr = value

Categories