Is it possible to create a method by an argument - python

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

Related

Passing instance during composition

I have a Common (or could call Base) class.
from enum import Enum
class Common:
def a(self, condition):
if condition == True:
return self.Keys.F.value
else:
return self.Keys.G.value
def b(self):
return Common.a(self, True) * 10
and multiple other classes, all of them use the Common class.
class KlassOne:
class Keys(Enum):
E = 0
F = 1
G = 2
def func(self, attribute):
w = Common.a(self, condition=bool(attribute))
x = Common.b(self)
return w, x
class KlassTwo:
class Keys(Enum):
E = 0
G = 1
F = 2
def func(self, attribute):
y = Common.a(self, condition=bool(attribute))
z = Common.b(self)
return y, z
how do I avoid the Common.a(self, ...) way of implementing this.
Is there an alternative to it?
You can instantiate your class :
class KlassOne:
def func(self, attribute):
common = Common()
w = common.a(condition=bool(attribute))
x = common.b()
return w, x
Your recent update to the question means that Common looks more like a mixin. (I would refactor b like this)
class Common:
def a(self, condition):
if condition == True:
return self.Keys.F.value
else:
return self.Keys.G.value
def b(self):
return self.a(True) * 10
The above Common does not need to import from enum.
Now your other classes can inherit from the above, just as a mixin:
from enum import Enum
class KlassOne(Common):
class Keys(Enum):
E = 0
F = 1
G = 2
def func(self, attribute):
w = self.a(condition=bool(attribute))
x = self.b()
return w, x
First, the Common.a(... is not necessary inside Common:
class Common:
def a(self, condition):
if condition == True:
return 1
else:
return 2
def b(self):
return self.a(True) * 10
Second, if you want to pass self of KlassOne to a method of class Common, then KlassOne actually should be an instance of class Common:
class KlassOne:
def func(self, attribute):
w = Common.a(self, condition=bool(attribute)) # <- here self is instance of KlassOne
x = Common.b(self)
return w, x
This is an argument strongly in favour of inheritance:
class KlassOne(Common):
def func(self, attribute):
w = self.a(condition=bool(attribute))
x = self.b()
return w, x
If you want to use composition, you would need to instantiate Common, e.g. like
class KlassOne:
def __init__(self):
self.common = Common()
def func(self, attribute):
w = self.common.a(condition=bool(attribute))
x = self.common.b()
return w, x

Redefining methods through class inheritance in Python

I'm playing around with class inheritance and I'm wondering if its possible to change aspects of an inherited method in the child class without having to rewrite the whole thing?
For example:
class Parent:
def _init_(self, x):
self.x = x
def foo(self):
a = self.x
if a > 0:
forward = True
elif a < 0:
forward = False
return forward
class Child1(Parent):
def foo(self, y=None, bool=False):
if bool:
a = y
else:
a = self.x
super().foo()
class Child2(Parent):
pass
What I'm looking for is if I called Child1.foo it could reassign the variable a before running through
the method, as defined in the parent class. Where a is dependent on the y and bool arguments passed through the rewritten method in Child1:
print(Child1(2).foo(-2, True))
# => False
print(Child1(2).foo())
# => True
print(Child2(2).foo())
# => True
Is this possible, or would I just have to rewrite a new method for each class?
I think I understand your problem and I have some suggestions for how you can resolve this:
Using "private" methods
For example:
class Parent:
def __init__(self, x):
self.x = x
def _foo(self, a=None):
a = a if a else self.x * 2
if a > 10:
over = True
else:
over = False
return over
def foo(self):
return self._foo()
class Child1(Parent):
def foo(self, y=None, condition=False):
if condition:
a = y*2
else:
a = self.x*2
return self._foo(a)
class Child2(Parent):
pass
In this example, all child classes will inherit the _foo "private" function, where they may or may not receive a value of a.
Using abstract classes
There is another solution to this problem with abstract classes (here is an example of how to do this), where you forces the child class to implement the function foo:
Important
Remembering that in the case of abstract classes, if you do not define the function decorated with #abstractmethod, you will receive an error similar to this TypeError: Can't instantiate abstract class Child2 with abstract methods foo
Example:
Python 2.x
from abc import ABCMeta, abstractmethod
class Parent:
__metaclass__ = ABCMeta
def __init__(self, x):
self.x = x
def _foo(self, a=None):
a = a if a else self.x * 2
if a > 10:
over = True
else:
over = False
return over
#abc.abstractmethod
def foo(self):
pass
class Child1(Parent):
def foo(self, y=None, condition=False):
if condition:
a = y*2
else:
a = self.x*2
return self._foo(a)
class Child2(Parent):
def foo(self):
return self._foo()
Python 3.x
class Parent(metaclass=ABCMeta):
def __init__(self, x):
self.x = x
def _foo(self, a=None):
a = a if a else self.x * 2
if a > 10:
over = True
else:
over = False
return over
#abc.abstractmethod
def foo(self):
pass
class Child1(Parent):
def foo(self, y=None, condition=False):
if condition:
a = y*2
else:
a = self.x*2
return self._foo(a)
class Child2(Parent):
def foo(self):
return self._foo()
In both examples you will have the same result by running this:
print(Child1(2).foo(10, True)) // True
print(Child1(2).foo()) // False
print(Child2(2).foo()) // False

How to make local variable of a method of Superclass available to a subclass where the superclass is called by another class

As you can see the code, I have a super class bar_for_foo_mixin() and I have a subclass myfoo(bar_for_foo_mixin): I am computing a operation self.Z = X+Y in bar() method of superclass.
Now I want the self.z = 0 updated to the computation done in bar() method and inheirt this value to the subclass myfoo(bar_for_foo_mixin): and use it inside subclass.
class bar_for_foo_mixin():
def __init__(self):
self.z = 0
def bar(self, q):
x = 2
y = 8
self.z = x + y + q
class oldfoo():
def __init__(self):
pass
var = bar_for_foo_mixin()
var.bar(10)
class myfoo(bar_for_foo_mixin):
def __init__(self):
super(myfoo, self).__init__()
def hello(self):
print("hello", self.z)
final = myfoo()
final.hello()
Result of the code:
hello 0
Expected result:
hello 20
The bar_for_foo_mixin instance stored in your oldfoo.var class variable is a completely separate instance from the myfoo object you instantiated in the main program, so their instance variable z would not be shared.
If you would like a variable to be shared across all instances of a class, you should make it a class variable instead, and make methods that are dedicated to updating class variables, such as bar_for_foo_mixin.bar, a class method instead:
class bar_for_foo_mixin():
z = 0
#classmethod
def bar(cls, q):
x = 2
y = 8
cls.z = x + y + q
class oldfoo():
def __init__(self):
pass
var = bar_for_foo_mixin()
var.bar(10)
class myfoo(bar_for_foo_mixin):
def __init__(self):
super(myfoo, self).__init__()
def hello(self):
print("hello", self.z)
final = myfoo()
final.hello()
This outputs:
hello 20
You're not even calling the bar method by the new final variable:
class bar_for_foo_mixin():
def __init__(self):
self.z = 0
def bar(self, q):
x = 2
y = 8
self.z = x + y + q
class myfoo(bar_for_foo_mixin):
def __init__(self):
super(myfoo, self).__init__()
def hello(self):
print("hello", self.z)
final = myfoo()
final.bar(10) # <== call it to take effect
final.hello() # ==> hello 20

Add non-lamda function to self of Python class

Adding lambda expression to self of a Python class is easy:
class Foo(object):
def __init__(self, x):
if x > 0:
self.eval = lambda x: x
else:
self.eval = lambda x: x**2
return
def compute(self, y):
return self.eval(y)
In my case, self.eval is somewhat more complex such that it doesn't fit into a one-line lambda. I need def. How can I assign self.eval with a defined function though?
For performance reasons, I would like to not store self.x = x and not move the if into compute.
You can define a function anywhere:
class Foo(object):
def __init__(self, x):
if x > 0:
def eval(y):
return y
else:
def eval(y):
return y**2
self.eval = eval
def compute(self, y):
return self.eval(y)
Python functions are first class objects. You can assign any function to a variable:
class Foo(object):
def __init__(self, x):
if x > 0:
self.eval = self.method1
else:
self.eval = self.method2
def method1(self, x):
return x
def method2(self, x):
return x * x
def compute(self, y):
return self.eval(y)
f1 = Foo(1)
print(f1.compute(10)) # 10 (method1)
f2 = Foo(-1)
print(f2.compute(10)) # 100 (method2)
At least in Python 3 it is trivial to add a method to an existing class. Just look at the following code:
>>> class A:
val = 2 # declare a class variable (will be the default value
>>> def func(self, x): # declare a function that will be added as a method
return self.val * x
>>> A.compute = func # add the compute method to class A
>>> a = A() # create an instance
>>> a.val # control the value of the member
2
>>> a.compute(3) # use the added method
6
>>> a.val=3 # change the value of the variable for the specific instance
>>> a.compute(4) # control that the new variable value is used
12

In the main function, how to print the value (x,y) from the def __str__?

for example
def __str__ (self):
return (x,y)
def main():
how do u print the value of x and y from the def str(self): function
Would really appreciate it thanks!!!
That code doesn't make sense, so I'm extrapolating.
I'm assuming you have some class like so:
class Foobar(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return str((x,y))
def main():
foobar = Foobar(1,2)
main()
In this case, you COULD use string manipulation to handle it.
x_value, y_value = map(str.strip("()"), str(foobar).split(','))
But that's uglier than sin. Why not just reference the values directly?
x_value, y_value = foobar.x, foobar.y
Using the example in Adam's answer:
class Foobar(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return '({foo.x}, {foo.y})'.format(foo=self)
Would result in:
foo = Foobar(2, 3)
print(foo)
'(2, 3)'

Categories