The proper way to call a parent method from a child class - python

I'm trying to use a parent method from a child class. A bare bone example is given below.
class one:
def multiply(self, x, y):
self.x = 500
return self.x*y
class two(one):
def multiplier(self, x, y):
self.x = x
ver1 = one.multiply(one, self.x, y) # here, if I don't pass one as an argument, I get a TypeError
print('The answer of ver1:', ver1)
print('What is self.x btw?', self.x)
ver2 = super().multiply(self.x, y)
print('The answer of ver2:', ver2)
print('What is self.x now?', self.x)
t = two()
t.multiplier(3,4)
This prints:
The answer of ver1: 2000
What is self.x btw? 3
The answer of ver2: 2000
What is self.x now? 500
I looked on here and many answers seem to imply that ver2 is the correct way to call a parent method but I don't want self.x to change in the child class, so the answer I want is ver1. But, in ver1, it seems redundant to pass one as an argument when it is already specified that multiply is one's method (if I don't pass one as an argument, I get
TypeError: multiply() missing 1 required positional argument: 'y'
So what is the correct way to call a method from a parent class without changing variables in the child class?

Use self, not one:
class two(one):
def multiplier(self, x, y):
self.x = x
ver1 = self.multiply(x, y)
print('The answer of ver1:', ver1)
print('What is self.x btw?', self.x)
Super is useful if you override the same method but want access to the parent:
class two(one):
def multiply(self, x, y):
self.x = x
ver2 = super().multiply(x, y)
print('The answer of ver2:', ver2)
print('What is self.x now?', self.x)
It seems redundant to pass one as an argument when it is already specified that multiply is one's method (if I don't pass one as an argument, I get TypeError: multiply() missing 1 required positional argument: 'y')
This is because when you use self, the method is bound to the instance and the instance is passed automatically as first parameter. When using one.multiply, the method is not bound and you need to pass it manually. But this is not the right way to go, as you intuited.
I don't want self.x to change in the child class
There are two classes and an instance which is an instance of both classes due to inheritance. x is an instance attribute, so it belongs to the instance, not to any of both classes. It can't change in parent and not child class or the opposite.

Related

what code should i write after the object definition to print all the fun method

class ApnaCollege():
def __init__(self,x,y):
self.x = x
self.y = y
print(self.x)
def fun(self):
print("I am a function with no argument")
def fun(self,x):
print("The function with an argument")
def fun(self,x,y):
print("The function with an two argument")
obj = ApnaCollege()
obj.fun()
obj.fun(3)
To see all the methods of an object defined by a class:
dir(obj)
You can find more info here: Ask Python: How to find all the methods of a given class in Python? including how to filter out dunder methods and get the methods you explicitly defined.

Using local variable within a function by another function in a class

Due to some circumstances I can only pass the argument to one function within a class.
Example:
class win1():
def __init__(self):
self.diction = dict()
self.x = self.wanted_touse()
#is it possible to make it here? If yes, it will be good to be like this
# self.X = X or self.y = Y (is this even possible without passing an argument in it?)
def fun(self, X,Y):
self.x = X
self.y = Y
def wanted_touse(self):
#I wanted to use X and Y here while at the same time I cannot pass the argument to this function because of some circumstances.
#Here with some functions to make the dictionary for self.x example for x in enumerate(self.x)
self.diction[something] = something
I would like to learn to see whether is it possible to use a variable within a function in win1 into want_touse function.
Define your attribute in the __init__(), and then modify it in your fun() function, like this:
class win1():
def __init__(self):
self.x = None
def fun(self, X,Y):
self.x = X
def wanted_touse(self):
pass
#do whatever you want with self.x here, so long as you've run your fun() function and changed self.x as you intended.
This example is just using a single variable. You can apply this to additional variables as needed.

Python OOP: how to use a flag parameter to access methods?

It's unclear to me how one accomplishes this in Python, though I am confused about the fundamentals of OOP:
Let's say I create a Shape class, and use this as an example.
class Shape:
def __init__(self, x, y):
self.x = x
self.y = y
def area(self):
return self.x * self.y
def perimeter(self):
return 2 * self.x + 2 * self.y
def scaleSize(self,scale):
self.x = self.x * scale
self.y = self.y * scale
In my case, I must create a Class which inputs a file whereby there are only two types, file_typeA and file_typeB. For the user, it would be exceptionally cumbersome to use a Class for Type A and a Class for Type B.
## use case for an a "read in file name" class `filename`
foo = filename(path = "path/to/file.txt", file_type = "TypeA")
My question is, how do I restrict the "Type A" methods for a file initialized with flag file_type="TypeA", and restrict the methods for a file initialized with flag file_type = "TypeB"?
Let's try the Shape class again, whereby the two types are Square and Triangle. The wrong way to code this is something like this:
class Shape:
def __init__(self, x, y, type):
self.x = x
self.y = y
self.type = type
if type == "Square":
def area(self):
return self.x * self.y
def perimeter(self):
return 2 * self.x + 2 * self.y
def scaleSize(self,scale):
self.x = self.x * scale
self.y = self.y * scale
elif type == "Triangle":
def hooray(self):
print("HOORAY! It's hip to be a triangle!")
else:
print("'type' must be either Circle or Triangle")
## example Class instantiation
bar = Shape(2, 3, type="Square")
For such a class, how do I create it such that the method area cannot be used for a Shape of type=="TypeB"?
I think you need to define a mother class:
class Shape:
pass
then sub-classes
class Triangle(Shape):
# whatever methods there are
What you're describing is a factory function which creates the proper object according to some parameter:
def create(type):
if type=="Triangle":
return Triangle()
elif type=="Square":
return Square()
but it's not very useful since the caller has to pass the name of the class instead:
c = create("Triangle")
instead of just doing:
c = Triangle()
Well, it may have its interest when saving/restoring a program state from a text file containing the type(s) of the objects in the program memory when saved (if you don't want to use pickle).
That's not how you OOP! OOP helps to eliminate those kinds of conditionals. You should create a Shape base class, then use that to define subclasses for each individual kind of shape. The subclasses should include the methods needed for that kind of shape.
If you want the caller to be able to specify a shape using a string, for example because they are using data from a file or the user, you can write a factory method to do that. You can actually ask Python for the subclasses of your class; no need to list them out! DRY
class Shape(object):
__subs = {}
#classmethod
def of_type(cls, name, *args, **kwargs):
"""Factory method that instantiates Shape subclasses given their name as a string"""
lname = name.lower()
subs = cls._Shape__subs
if cls is Shape:
if not subs: # build subclass dictionary
subs.update({c.__name__.lower(): c for c in cls.__subclasses__()})
if lname in subs: # instantiate the named subclass
return subs[lname](*args, **kwargs)
raise NameError("invalid shape name: %s" % name)
raise TypeError("of_type() may be called only on Shape base class")
class Square(Shape):
pass
class Triangle(Shape):
pass
# set tri to an instance of type Triangle
tri = Shape.of_type("Triangle")
Note that the factory method passes through any arguments given after the name. Class names are case-insensitive.

Python 3: Calling a class function inside of __init__

I have a little question about python 3.
I want to create a class, which is using a function from within of that class. Just like:
class Plus:
def __init__(self, x, y):
self.x = x
self.y = y
self.test()
def test(self):
return self.x + self.y
now I am doing something like
a = Plus(5,6)
print(a)
and python is giving me
<__main__.Plus object at 0x000000000295F748>
and not 11 as I want it. I know that I can get 11 by
a = Plus(5, 6).test()
print(a)
but that's not what I want. I want to call the class and getting the result without adding .test() to it.
Can you help me?
I would go for:
class Plus:
def __init__(self, x, y):
self.x = x
self.y = y
self.test()
def test(self):
res = self.x + self.y
self.__repr__ = lambda:str(res)
return res
>>> Plus(5,5)
10
>>> a = Plus(5,5)
>>> a
10
>>> a.test()
10
This way you are not recomputing the sum each time you call print, its updated when you call the test method.
You'd need to define a __str__ method for your Plus class:
class Plus:
def __init__(self, x, y):
self.x = x
self.y = y
def test(self):
return self.x + self.y
def __str__(self):
return str(self.test())
now I am doing something like
a = Plus(5,6)
print(a)
and python is giving me
<__main__.Plus object at 0x000000000295F748>
and not 11 as I want it. I know that I can get 11 by
a = Plus(5, 6).test()
print(a)
but that's not what I want. I want to call the class and getting the result without adding .test() to it.
I am not sure what do you mean by 'and not 11 as I want it'. If you want Plus(5, 6) to actually return 11 (int instance), you should make Plus a function that returns the sum. Alternatively you can override __new__ method and hook upon object creation -- but this is a bad idea.
What are you trying to achieve?
I doubt, that by 'and not 11 as I want it' you want something special to be printed (formatted, represented). If so, override __str__ or __unicode__ or __repr__ method.
Edit:
ignore this answer, it is a comment on a misinterpretation of the question
This is just wrong.
when you instantiate an object, you'd expect to get a reference to that object.
if you just want a global function returning a number, why even bother to make a class with an init?
in python you shouldn't want static class's like in C# for encapsulation. instead name the module something, and use that for encapsulation.

Call a method from a class on something created by a different method in the same class?

I would like to call a method from a class on something created by another method in the class. How would I do this?
For example, I've just created a class called call me, and would like to use the result of the subtract method in the add method.
class call_me(object):
def __init__(self, x, y):
self.x = 5
self.y = 10
def subtract(self):
difference = self.y - self.x
return difference
def add(self.subtract,second_number):
# code to add the difference returned by subtract to the second number.
How would I add a second number to the difference returned by subtract? Is there a way I could pass difference to add?
def add(self, second_number):
difference = self.substract()
return difference + second_number

Categories