How to a, b = myClass(a, b) in Python? - python

Python does this:
t = (1, 2)
x, y = t
# x = 1
# y = 2
How can I implement my class so to do
class myClass():
def __init__(self, a, b):
self.a = a
self.b = b
mc = myClass(1, 2)
x, y = mc
# x = 1
# y = 2
Is there a magic function I could implement in order to achieve this?

You need to make your class iterable. Do this by adding the __iter__ method to it.
class myClass():
def __init__(self, a, b):
self.a = a
self.b = b
def __iter__(self):
return iter([self.a, self.b])
mc = myClass(1, 2)
x, y = mc
print(x, y)
Output:
1 2

If your class doesn't do much else, you might prefer to use a named tuple:
from collections import namedtuple
MyClass = namedtuple('MyClass', 'a b')
mc = MyClass(1, 2)
print(mc.a, mc.b) # -> 1 2
x, y = mc
print(x, y) # -> 1 2
BTW, style note: Class names should be UpperCamelCase.

Related

Deepcopy on two classes containing eachother gives recursion error. Python

When I have a object-structure like this:
from copy import deepcopy
class A:
def __init__(self, b):
self.b = b
def __deepcopy__(self, memodict):
return A(deepcopy(self.b, memodict))
class B:
def __init__(self, a):
self.a = a
def __deepcopy__(self, memodict):
return B(deepcopy(self.a, memodict))
test_a = A(None)
test_b = B(None)
test_a.b = test_b
test_b.a = test_a
copy_a = deepcopy(test_a)
And I try to make a deepcopy of a object I get a "maximum recursion depth exceeded" error.
Which I understand why this happens but I don't know what the best approach would be to solve this?
Help much appreciated
You should not override __deepcopy__, just let deepcopy function do its work.
By the way I had to remove annotation :B because its a foreward reference and gives name error.
from copy import deepcopy
class A:
def __init__(self, b):
self.b = b
class B:
def __init__(self, a):
self.a = a
a = A(None)
b = B(None)
a.b = b
b.a = a
aa = deepcopy(a)
print (aa is a) # -> False
print(aa.b is b) # -> False
print(aa.b.a is aa) # -> True
But if you for any reason want to override the __deepcopy__ you should do it like this:
from copy import deepcopy
class A:
def __init__(self, b):
self.b = b
def __deepcopy__(self, memodict):
a = A(None)
memodict[id(self)] = a
a.b = deepcopy(self.b, memodict)
return a
class B:
def __init__(self, a: A):
self.a = a
def __deepcopy__(self, memodict):
b = B(None)
memodict[id(self)] = b
b.a = deepcopy(self.a, memodict)
return b
a = A(None)
b = B(None)
a.b = b
b.a = a
aa = deepcopy(a)
print(aa is a) # -> False
print(aa.b is b) # -> False
print(aa.b.a is aa) # -> True
ref: https://stackoverflow.com/a/15774013/1951448

Python fuction stereotyped

Class A has functionA has if. And functionA is repeated by 100 time in out.
In this case, it looks non scene to caluculate if self.z.... each time in called by for in out.
Class A():
def __ini__(self, z)
self.z = z
def functionA(self, a):
if self.z == 1:
b = zFunc1 * a
elif self.z == 2:
b = zFunc2 * a
return b
def out(self):
for i in range(100):
print(self.functionA(i))
So I'm looking for the way to fix functionA in __ini__ like
Class A():
def __ini__(self, z):
self.z = z
functionA < = FIX by (self.z = 2)
"""
def functionA(self, a):
b = zFunc2 * a
reuturn b
"""
Is there solution?
Just make zFunc* another class attribute decided in __init__:
class A:
def __init__(self, z):
self.z = z
self.z_func = zFunc1 if z == 1 else zFunc2
def function_a(self, a):
return self.z_func * a
In fact, in this example you don't even need self.z as an attribute at all.

Pass String Parameter into Class/Function (Python)

If I have a class as such:
class Sample:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
I can create an object by:
temp = Sample(a=100,b=100,c=100)
But what if I have:
my_str = "a=100,b=100,c=100"
How can I temp = Sample(my_str) properly?
You can parse and eval the string like:
Code:
#classmethod
def from_str(cls, a_str):
return cls(**eval("dict({})".format(a_str)))
Test Code:
class Sample:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
#classmethod
def from_str(cls, a_str):
return cls(**eval("dict({})".format(a_str)))
x = Sample.from_str("a=100,b=100,c=100")
print(x.a)
Results:
100
use eval
temp = eval("Sample("+my_str+")")
Although it is definitely an option, using eval can be dangerous. Here is an option which is #StephenRauch's code just without using eval.
>>> class Sample:
... def __init__(self, a, b, c):
... self.a = a
... self.b = b
... self.c = c
...
... #classmethod
... def from_str(cls, a_str):
... result = {}
... for kv in a_str.split(','):
... k, v = kv.split('=')
... result[k] = int(v)
... return cls(**result)
...
>>> x = Sample.from_str('a=100,b=100,c=100')
>>> x.a
100
>>> type(x.a)
<class 'int'>
You can use the below code.
class Sample:
def __init__(self, a, b, c):
self.a = int(a)
self.b = int(b)
self.c = int(c)
mystr = "a=100,b=100,c=100"
temp = Sample(mystr.split(",")[0].split("=")[1],mystr.split(",")[1].split("=")[1],mystr.split(",")[2].split("=")[1])
print(temp.a)
print(temp.b)
print(temp.c)
See it in action here
This works for me:
my_str = "a=100,b=100,c=100"
temp = Sample(int(my_str.split(',')[0].split('=')[1]),
int(my_str.split(',')[1].split('=')[1]),
int(my_str.split(',')[2].split('=')[1]))
print(temp.a)
# prints 100
print(temp.b)
# prints 100
print(temp.c)
# prints 100

Is it possible to create a method by an argument

Say I have two functions
def do1(x, y):
return x + y
def do2(x, y):
return x - y
I can create a class like this
class foo(object):
def __init__(self, func):
self.func = func
abc = foo(func=do1)
abc.func(1, 1) # return 2
abc = foo(func=do2)
abc.func(1, 1) # return 0
Is it possible for me make abc.func to be a method rather than an attribute?
Thanks.
You can add a method to a class like so:
def do(self, x, y):
return x+y
class Foo(object0:
def __init(self):
pass
Foo.bar = do
a = Foo()
a.bar(1,2)
out> 3
Or to an instance:
def do2(x,y):
return x + y
a = Foo()
a.bar2 = do2
a.bar2(3,4)
out> 7

Intersection of two lists containing Object types in python

How to find the intersection of two lists containing tuples of float values in Python?
For example:
A = [(1.1,2.2),(3.3,4.4),(5.5,6.6)]
B = [(1.1,2.2),(7.7,8.8),(3.3,4.4)]
I need
A intersection B = [(1.1,2.2),(3.3,4.4)]
Update:
My bad. Thanks for the response but I there was a misconception in my understanding.
The question should be
For example:
A = [Point(1.1,2.2),Point(3.3,4.4),Point(5.5,6.6)]
B = [Point(1.1,2.2),Point(7.7,8.8),Point(3.3,4.4)]
I need
A intersection B = [Point(1.1,2.2),Point(3.3,4.4)]
where Point is my python class containing two float variables as shown
class Point:
def __init__(self, a_, b_):
self.a = a_
self.b = b_
If order does not matter use set.intersection:
A = [(1.1,2.2),(3.3,4.4),(5.5,6.6)]
B = [(1.1,2.2),(7.7,8.8),(3.3,4.4)]
print(set(A).intersection(B))
set([(3.3, 4.4), (1.1, 2.2)])
Or make B a set and iterate over A keeping common elements:
st = set(B)
print([ele for ele in A if ele in st ])
[(1.1, 2.2), (3.3, 4.4)]
If you are looking for objects with the same attribute values:
A = [Point(1.1,2.2),Point(3.3,4.4),Point(5.5,6.6)]
B = [Point(1.1,2.2),Point(7.7,8.8),Point(3.3,4.4)]
st = set((p.a,p.b) for p in B)
print([p for p in A if (p.a,p.b) in st])
Or create a hash method in your class:
class Point(object):
def __init__(self, a_, b_):
self.a = a_
self.b = b_
def __hash__(self):
return hash((self.a, self.b))
def __eq__(self, other):
return self.a, self.b == other.a,other.b
def __ne__(self, other):
return not self.__eq__(other)
A = [Point(1.1,2.2),Point(3.3,4.4),Point(5.5,6.6)]
B = [Point(1.1,2.2),Point(7.7,8.8),Point(3.3,4.4)]
print(set(A).intersection(B))

Categories