Can One Write Methods for Three Instances of Same Class - python

I ask this question out of curiosity, there are probably many workarounds to what I am about to ask.
When you create a class in python, you can define methods that take two instances of this class, by the use of "self" and "other" keywords, such as
class MyClass():
def __init__(self, x):
self.x = x
def __add__(self, other):
return self.x + other.x
Can you do the same with 3 or more instances of the same class? That is, is there something like "self", "other", "another"?

You can create a list that contains the arguments of different class instances that can be called from a loop.
class MyClass():
def __init__(self, x):
self.x = x
def __add__(self, others):
temp = self.x
for obj in others:
temp += obj.x
return temp
x = MyClass(5)
y = MyClass(5)
z = MyClass(5)
print(x.__add__([y, z])) # 15

Related

Inheriting function data

I have a question about inheriting data from functions, defined inside another class. I have written an example script to clarify myself. In this script I define a class called Test. Here I define x and y in the __init__() function. Thereafter, I make a calculation and return x,y. I then create another class called Inherit_Test that inherits the x,y from Test. In this class I define z and make a calculation with the inherited values from Test. Afterwards, I call the class with Values. The problem arises when I want to access the data stored in Values. The type of this object is "Inherited_Values", while you would expect the type to be int and have the value 3*4*43. I hope I have explained myself well enough, thanks!
class Test():
def __init__(self, x , y ):
self.x = x
self.y = y
def Calculation(self):
self.x = 3*4 #self.x*self.x
self.y = 43 #self.y*self.y
return self.x, self.y
class Inherit_Test(Test):
def __init__(self,z ):
Test.__init__(self, x = Test.Calculation(self)[0],
y = Test.Calculation(self)[1])
self.z = z
def Inherit_Calculation(self):
self.z = self.x * self.y
return self.z
Value = Inherit_Test(0)
Value.Inherit_Calculation()
unfortunately, your question is not very clear defined and it is hard to assume what you exactly wanted to do. I'll try to help you with the following code :
class Test():
def __init__(self):
self.Calculation() # instantiation of the self.x and self.y; no init params needed
def Calculation(self):
self.x = 3*4 #self.x*self.x
self.y = 43 #self.y*self.y
#return self.x, self.y # do you need to return something here ?
class Inherit_Test(Test):
def __init__(self):
super().__init__() # instantiation of the parameters of your super class
#self.z = z # do you need this part ?
def Inherit_Calculation(self):
self.z = self.x * self.y
return self.z
Result:
Value = Inherit_Test()
print(type(Value.Inherit_Calculation()))
print(Value.x)
print(type(Value.x))
print(Value.y)
print(type(Value.y))
print(Value.z)
print(type(Value.z))
<class 'int'>
12
<class 'int'>
43
<class 'int'>
516
<class 'int'>

Is there an accepted pythonic way of splitting off a base class part from a subclass object?

I am looking for the best way to split off the base class content of a subclass object. That is, if I have an object b of class B, which subclasses class A, I would like a method for class B that returns an object a of class A with the relevant content taken from b (which is a subset of all the content in b). Currently I have roughly the following (the actual classes are more complicated of course, this is a simplified toy example)
class A:
def __init__(self):
self.x = 0
def update(self, dx):
self.x += dx
class B(A):
def __init__(self):
super().__init__()
self.y = None
def update(self, dx):
super().update(dx)
self.y = self.x*self.x
def split_off_base_part(self):
a = A()
a.__dict__.update({k: v for k, v in self.__dict__.items() if k in a.__dict__})
return a
but I am not too happy with it. Is there a more pythonic way of doing this? Possibly one that doesn't require calling A.__init__ or is this simply not possible in general?
You could re-define the init for A so that it can optionally take parameters, that is nice than trying to update the __dict__.
class A:
def __init__(self, _x = 0):
self.x = _x
def update(self, dx):
self.x += dx
class B(A):
def __init__(self):
super().__init__()
self.y = None
def update(self, dx):
super().update(dx)
self.y = self.x*self.x
def toA(self):
return A(self.x)
Or you could define that as a class-method (almost like a second constructor) on A, which takes a B and returns a stripped down A.

python; how to pass one argument through multiple methods in a class

I am learning about class structure in python. Would like to know if it's possible to pass one argument through more than one method.
class Example(object):
def __init__(self, x):
self.x = x
def square(self):
return self.x**2
def cube(self):
return self.x**3
def squarethencube(y):
sq = Example.square(y)
cu = Example.cube(sq)
return cu
two = Example(2)
print(two.squarethencube())
Error is on line 10; AttributeError: 'int' object has no attribute 'x'
The goal is to use the 'squarethencube' method to pass '2' to square(), which is 4. Then pass '4' to cube(). The desired output is '64'. Obviously, you can write a function to do the math in a very simple way; the question here is how to use multiple methods.
I understand the error in that .x is getting assigned as an attribute onto the output of cube(sq). I was getting the same error, but on line 7, before I changed the argument to y (from self.x).
I've found some similar answers here but I need a simpler explanation.
Currently, square and cube are methods bound to the class; however, you are accessing them in squarethencube by class name, but they are methods, and thus rely on a reference to the class from an instance. Therefore, you can either create two new instances of the class or use classmethod:
Option1:
class Example(object):
def __init__(self, x):
self.x = x
def square(self):
return self.x**2
def cube(self):
return self.x**3
def squarethencube(self, y):
sq = Example(y).square()
cu = Example(y).cube()
return cu
Option 2: use a classmethod:
class Example(object):
def __init__(self, x):
self.x = x
#classmethod
def square(cls, x):
return x**2
#classmethod
def cube(cls, x):
return x**3
def squarethencube(self, y):
sq = Example.square(y)
cu = Example.cube(sq)
return cu
class Example:
def __init__(self, x):
self.x = x
def square(self):
return self.x**2
def cube(self):
return self.x**3
def squarethencube(self):
return (self.x**2)**3
two = Example(2)
print(two.squarethencube())

How to Nested Classes in Python when trying to write a __call__ overwrite

So hopefully below illustrates my point. I want to set the translate attributes once and then be able to pass any mods (like translate) into the modLevels function. The only way I know how to do this is through nested classes, but I can't figure out how to get access to the outer class points. Any ideas or maybe even let me know if I'm going about this all wrong. THANKS!
class PointSet:
def __init__(self, points):
self.points = points
class translate:
def __init__(self, xmove=0, ymove=0):
self.xmove = xmove
self.ymove = ymove
def __call__(self):
for p in Outer.points: # <-- this part isnt working
p.x += self.xmove; p.y += self.ymove
def modLevels(levels, *mods):
for lev in range(levels):
for mod in mods:
mod
set1 = PointSet(...list of point objects here...)
coolMod = translate(xmove=5)
change(5, coolMod)
Pass it as a parameter.
class PointSet:
def __init__(self, points):
self.points = points
class translate:
def __init__(self, xmove=0, ymove=0, parent):
self.parent = parent
self.xmove = xmove
self.ymove = ymove
def __call__(self):
for p in self.parent.points:
p.x += self.xmove; p.y += self.ymove
Self-contained example:
class A:
def __init__(self):
self.data = [1,2,3]
class B:
def __init__(self, parent):
self.data = [4,5,6]
self.parent = parent
def access(self):
print(self.parent.data)
a = A()
b = a.B(a)
b.access()
However, as explained in comments, you don't need a nested class at all.
class PointSet:
def __init__(self, points):
self.points = points
def translate(self, x, y):
for p in self.points:
p.x += x
p.y += y
Thank you all for your help. I found a way to access the outer class on ubuntu forums. Solved referencing outer class from an inner class.
I needed to do this to pass a few parameters to the translation constructor and then overwrite the call function to use those parameters. This is a similar concept to a C++ function object like what you would pass to an STL algorithm: more on function objects.

Python: avoid defining both a classmethod and an instancemethod

NOTE on the question below. I think the 'proper' pythonic idiom is to a) create module functions, such as foo_math below, and then call their specific action against an instance within the class itself. The bottom piece of code reflects that approach.
I want to define a classmethod which takes two arguments and returns a value. I want the same method to be able to be called on a class instance with the instance value pass as one of the arguments. Can I do this without defining two distinct methods as I have done here?
class Foo(object):
__init__(x):
self.x = x
#classmethod
def foo_math(cls, x, y):
return x + y
def math(self, y):
return Foo.foo_math(self.x, y)
What I would like is:
>>> Foo.math(3, 4)
7
>>> f = Foo()
>>> f.x = 3
>>> f.math(4)
7
Short of subtyping int, here is my conclusion to this question:
def foo_math(cls, x, y):
return x + y
class Foo(object):
__init__(x):
self.x = x
def foo_math(self, y):
return foo_math(self, y)
i don't recommend doing this, but if you really want, it's this (thank you other guy on stackoverflow for first part):
class staticorinstancemethod(object):
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
return functools.partial(self.func, instance)
then, do something like
class F(object):
#staticorinstancemethod
def math(instOrNone, v1, v2=None):
return instOrNone.x + v1 if instOrNone else v1 + v2
but maybe you just want to define the __add__ and __radd__ methods...
I don't think that you can call a method from a class without defining an object of that class (class methods don't belong inside the methods of any one class), so things like Foo.math(3, 4) will return a NameError as Foo has not been defined.
With this in mind, you should modify your code to be like this (even though with the problem solved there are still some issues with the code):
# A class method would probably go here somewhere.
class Foo(object):
def __init__(self, x):
self.x = x
def foo_math(self, x, y):
return x + y
def math(self, y):
return self.foo_math(self.x, y)
Then you can do:
>>> f = Foo(3)
>>> f.math(4)
7

Categories