High Order Function Constructor - python

I'm programming in Python and I need to program a particular object but I'm having some difficulties: I want an object that can recall on demand a particular generator passed during its construction through init.
Now I've write something like this but obviously it doesn't work.
class Foo():
id = ''
def __init__ (self, num)
self.id = num
def recallGenerator():
return self.generator
where and how have I to pass and store the generator that I want to recall with recallGenerator() ?

Well, I have solved.
This is the class I wanted
class Foo():
id = ''
generator = ''
def __init__ (self, num, gen)
self.id = num
self.generator = gen
def recallGenerator(param1, param2,...):
return self.generator(param1, param2,...)
Now, given a generic generator G(param1, param2...) you can create the object and pass it to the constructor with
objectIWanted = Foo(1, G)
and then you can recall the generator with
objectIWanted.recallGenerator(param1, param2,...)
NB note the missing parenthesis when passing G to the constructor.

Related

Can I change the __call__ of a Python Object without rewriting the code?

Consider the following scenario in pseudo-python-code:
class Component_i: # same for i = 1,2,3,...
__call__(self, input):
return input
class MyClass:
def __init__(self):
self.comp_1 = Component_1()
self.comp_2 = Component_2()
self.comp_3 = Component_3()
def __call__(self, input):
return self.comp_3(self.comp_2(self.comp_1(input)))
A = MyClass()
Now i would like to do the following:
class Component_2B:
__call__(self, input, option = True):
if option:
return input
else:
return do_stuff_with_input(input)
A.comp_2 = Component_2B()
And then I would like to change the __call__ of A to also accept the optional input option, and this optional input to be passed to A.comp_2 whenever it is called. But to make things complicated, I would like to achieve this without rewriting the __call__.
Does anyone have an Idea?
Here is a MWE:
class MultiplyWithParameter:
def __init__(self, parameter: float):
self.p = parameter
def __call__(self, input: float):
return self.p * input
class ProcessDataClass:
def __init__(self, parameter: float):
self.mul = MultiplyWithParameter(parameter)
def __call__(self, input: float):
input = input * 5 + 4
input = self.mul(input)
return input - 3
DataProcessor = ProcessDataClass(2.5)
class OptionalMultiplyWithParameter:
def __init__(self, parameter: float):
self.p = parameter
def __call__(self, input: float, multiply: Bool = True):
if multiply:
return self.p * input
else:
return input
now i want to set
DataProcessor.mul = OptionalMultiplyWithParameter(DataProcessor.mul.p)
and use DataProcessor(4.23, False). This shall pass the False to DataProcessor.mul during the call. I want to do this without rewriting the __call__ of ProcessDataClass (otherwise would be simple).
Here is some Motivation:
Assume there is a package called coollibrary in the internet from which I would like to use function coolclassfactory. This function returns an Instance of CoolClass which has a range of attributes and a __call__. Some of its attributes might be of class ProcessWithParameters. When initialized, CoolClass loads parameters from the Internet. Now I would like to give my CoolClass Instance which i built with coolclassfactory as an attribute to MyClass. But I would then like to replace all attributes that my CoolClass Instance has and that are of class ProcessWithParameters with another class OptionalProcessWithParameters, which essentially allows at runtime to choose between two possible ways of how to process input with parameters. Since this runtime option is new, i have to add it during the call (i assume? - here is important this should be safe to be used in multiprocessing!). Now unfortunately because I use coolclassfactory and this returns one of many possible subclasses of CoolClass each with an individual __call__, i can not simply rewrite the __call__, because that changes depending on how coolclassfactory is called. Essentially I would have to rewrite all the calls of subclasses of CoolClass, which I am trying to avoid...
you can always subclass what ever class and rewrite/expand/adjust any part of the original to your liking and with the use of super() access the original functionality
from your example, something like this for example:
class ProcessDataClassOptional(ProcessDataClass):
def __init__(self, parameter: float):
super().__init__(parameter) #use the original init to do its thing
self._mul = OptionalMultiplyWithParameter(parameter) #our modification
def __call__(self, input: float, multiply: Bool = True):
self.mul = lambda x: self._mul(x, multiply) # now the original will use our modify mul
return super().__call__(input)
and now you can instead use the adjusted version
DataProcessor = ProcessDataClassOptional(2.5)
DataProcessor(4.23)
DataProcessor(4.23, False)
when used as the original there shouldn't be any change, but now you can use the new behavior with it too

When doing function chaining in python, is there a way to refer to the "current" object?

Assume I were given the following class:
class foo(object):
def __init__(self, int):
self.count = int
def increment(self, int):
return foo(int + 1)
def decrement(self, int):
return foo(int - 1)
My goal is to chain together function calls to reach the result I want without having to assign each object to a variable. For instance, I know I can do this:
obj = foo(0)
obj = obj.increment(obj.count)
obj = obj.decrement(obj.count)
obj = obj.increment(obj.count)
obj = obj.decrement(obj.count)
print obj.count
0
but I would like to be able to do this:
finalcount = obj(0).increment(?.count).decrement(?.count)
but I don't know if there is something that I can put in place of ? to refer to the object who's method is being called since that object hasn't been assigned a name.
Your object doesn't really contribute anything in your current code. Note how the methods in your class don't refer to any object state — they never use self. Better would be to omit the int parameter entirely, and use self.count instead:
class foo(object):
def __init__(self, int):
self.count = int
def increment(self):
return foo(self.count + 1)
def decrement(self):
return foo(self.count - 1)
Then, what you wanted to write becomes this:
finalcount = foo(0).increment().decrement()
But, to answer your original question, there is no way to refer to the "current" object in the chain of calls. If you want to refer to an intermediate object, you must assign it to a variable.

Use keywords in class to call a specific method

Suppose a Python class has different methods, and depending on what the user specifies, a different method is carried out in the main function calculate().
In the example below the user needs to specify the keyword argument 'methodOne' or 'methodTwo'. If no or an incorrect keyword is specified it should default to 'methodOne'.
class someClass(object):
def __init__(self,method=None):
methodList = ['methodOne','methodTwo']
if method in methodList:
self.chosenMethod = method
else:
self.chosenMethod = self.methodOne
def methodOne(self):
return 1
def methodTwo(self):
return 2
def calculate(self):
return self.chosenMethod()
The above clearly does not work since method is a string and not a function. How can I select self.methedOne() or self.methedOne() based on my keyword argument method? In principle the following works:
def __init__(self,method=None):
if method == 'methodOne':
self.chosenMethod = self.methodOne
elif method == 'methodTwo':
self.chosenMethod = self.methodTwo
else:
self.chosenMethod = self.methodOne
But if I have more than two methods this becomes rather ugly. Is there a way to do this similar to my original code?
You could use getattr() for that purpose:
class someClass(object):
def __init__(self,method=None):
methodList = ['methodOne','methodTwo']
if method in methodList:
self.chosenMethod = method
else:
self.chosenMethod = self.methodOne
def methodOne(self):
return 1
def methodTwo(self):
return 2
def calculate(self):
return getattr(self, self.chosenMethod)()
x = someClass(method='methodOne')
print x.calculate()
>>> 1
You can use getattr to get the actual method on the class object.
class someClass(object):
def __init__(self,method=None):
# store it with the object so we can access it later in calculate method
self.method = method
def methodOne(self):
return 1
def methodTwo(self):
return 2
def calculate(self):
# get the actual method from the string here
# if no such method exists then use methodOne instead
return getattr(self, self.method, self.methodOne)()
> someClass('methodOne').calculate()
# 1
> someClass('methodTwo').calculate()
# 2

Python: Dynamically adding function to a class, whose name is contained in a string

What is the best way to create a new member function of a class with function name contained as string? Also, this new function is merely as pass-through for another object(helper class), which has the same function name but with variable arguments. I use lambda to achieve this, but I don't know how to handle the scenario, where my pass-through wrapper would be more than one-statement (which is my requirement)
# This is a helper class
class Compensation:
def bonus(self):
return 10000
def salary(self):
# Do something
def stack(self):
# Do something
# This is a employer class
class employee:
def __init__(self):
self.compensation = Compensation()
# This is a wrapper that creates the function
def passThru(funcName):
fn = "employee."+funcName+"=" + "lambda self, *arg: self.compensation." + funcName +"(*arg)"
exec(fn)
fnNames = ["bonus", "salary", "stocks"]
for items in fnNames: passThru(items)
emp = employee()
emp.bonus() # returns 1000
All that trickery with exec gives me a headache ;-) I'm not exactly clear on what you want to do, but adding a new method with a name given by a string is really quite easy. For example,
class employee:
pass
# Some multiline-function.
def whatever(self, a, b):
c = a + b
return c
e = employee()
# Make `whatever` an `employee` method with name "add".
setattr(employee, "add", whatever)
print e.add(2, 9)
Whenever you're reaching for exec, you're probably missing a straightforward way.
EDIT: an oddity here is that if someone tries to display e.add, they'll get a string claiming its name is whatever. If that bothers you, you can add, e.g.,
whatever.__name__ = "add"
Fleshing it out
Is this closer to what you want? Note that #gnibbler suggested much the same, although more telegraphically:
class Compensation:
def bonus(self, a):
return 10000 + a
def salary(self):
return 20000
def stack(self, a=2, b=3):
return a+b
class employee:
def __init__(self):
self.comp = Compensation()
e = employee()
for name in "bonus", "salary", "stack":
def outer(name):
def f(self, *args, **kw):
return getattr(self.comp, name)(*args, **kw)
f.__name__ = name
return f
setattr(employee, name, outer(name))
print e.bonus(9)
print e.salary()
print e.stack(b="def", a="abc")
That displays:
10009
20000
abcdef
All that said, you might want to re-think your architecture. It's strained.
You want setattr. Let's say you have:
>>> inst = Foo(10)
>>> class Foo(object):
def __init__(self, x):
self.x = x
>>> inst = Foo(10)
>>> inst2 = Foo(50)
If you want to add a method to all instances of the class, then setattr on the class. This function will end up being an unbound method on the class, becoming bound in each instance, so it will take the self param:
>>> setattr(inst.__class__, "twice_x", lambda self: self.x * 2)
>>> inst.twice_x()
20
>>> inst2.twice_x()
100
If you want to add the function to just one instance of the class, then setattr on the instance itself. This will be a regular function which will not take the implicit self argument:
>>> setattr(inst, "thrice_x", lambda: inst.x * 3)
>>> inst.thrice_x()
30
>>> inst2.thrice_x()
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
inst2.thrice_x()
AttributeError: 'Foo' object has no attribute 'thrice_x'
You are looking for setattr/getattr.
for func_name in fnNames:
setattr(employee, func_name, (lambda self, *args:getattr(self.compensation, func_name)(*args)))
This still has a problem because you need the lambda function to be closed over func_name. While you could create a closure with another lambda, I'll pull it out into another function for readability
for func_name in fnNames:
def f(func_name): # close the lambda over "func_name"
return lambda self, *args:getattr(self.compensation, func_name)(*args)
setattr(employee, items, f(func_name))

Dynamically generate method from string?

I have a dict of different types for which I want to add a simple getter based on the name of the actual parameter.
For example, for three storage parameters, let's say:
self.storage = {'total':100,'used':88,'free':1}
I am looking now for a way (if possible?) to generate a function on the fly with some meta-programming magic.
Instead of
class spaceObj(object):
def getSize(what='total'):
return storage[what]
or hard coding
#property
def getSizeTotal():
return storage['total']
but
class spaceObj(object):
# manipulting the object's index and magic
#property
def getSize:
return ???
so that calling mySpaceObj.getSizeFree would be derived - with getSize only defined once in the object and related functions derived from it by manipulating the objects function list.
Is something like that possible?
While certainly possible to get an unknown attribute from a class as a property, this is not a pythonic approach (__getattr__ magic methods are rather rubyist)
class spaceObj(object):
storage = None
def __init__(self): # this is for testing only
self.storage = {'total':100,'used':88,'free':1}
def __getattr__(self, item):
if item[:7] == 'getSize': # check if an undefined attribute starts with this
return self.getSize(item[7:])
def getSize(self, what='total'):
return self.storage[what.lower()]
print (spaceObj().getSizeTotal) # 100
You can put the values into the object as properties:
class SpaceObj(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
storage = {'total':100,'used':88,'free':1}
o = SpaceObj(**storage)
print o.total
or
o = SpaceObj(total=100, used=88, free=1)
print o.total
or using __getattr__:
class SpaceObj(object):
def __init__(self, **kwargs):
self.storage = kwargs
def __getattr__(self,name):
return self.storage[name]
o = SpaceObj(total=100, used=88, free=1)
print o.total
The latter approach takes a bit more code but it's more safe; if you have a method foo and someone create the instance with SpaceObj(foo=1), then the method will be overwritten with the first approach.
>>> import new
>>> funcstr = "def wat(): print \"wat\";return;"
>>> funcbin = compile(funcstr,'','exec')
>>> ns = {}
>>> exec funcbin in ns
>>> watfunction = new.function(ns["wat"].func_code,globals(),"wat")
>>> globals()["wat"]=watfunction
>>> wat()
wat

Categories