Lambda function for classes in python?

There should be an easy way to do this, but somehow I can wrap my head around me. The best way I can describe what I want is a lambda function for a class. I have a library that expects as an argument an unreasonable version of the class to work. Then it creates an instance of the class that it should work on. The problem is that I want to be able to dynamically create versions of the class, go to the library, but I cannot figure out how to do this, since the library expects an unexplored version. The code below describes the problem:

class Double: def run(self,x): return x*2 class Triple: def run(self,x): return x*3 class Multiply: def __init__(self,mult): self.mult = mult def run(self,x): return x*self.mult class Library: def __init__(self,c): self.c = c() def Op(self,val): return self.c.run(val) op1 = Double op2 = Triple #op3 = Multiply(5) lib1 = Library(op1) lib2 = Library(op2) #lib3 = Library(op3) print lib1.Op(2) print lib2.Op(2) #print lib3.Op(2) 

I cannot use the generic Multiply class because I must first create an instance that breaks the library "AttributeError: Multiply instance does not have a call method." Without changing the library class, is there any way to do this?

+7
python lambda
source share
6 answers

No need for lambda at all. lambda is just syntactic sugar to define a function and use it simultaneously. Just as any lambda call can be replaced with an explicit def, we can solve your problem by creating a real class that meets your needs and returns it.

 class Double: def run(self,x): return x*2 class Triple: def run(self,x): return x*3 def createMultiplier(n): class Multiply: def run(self,x): return x*n return Multiply class Library: def __init__(self,c): self.c = c() def Op(self,val): return self.c.run(val) op1 = Double op2 = Triple op3 = createMultiplier(5) lib1 = Library(op1) lib2 = Library(op2) lib3 = Library(op3) print lib1.Op(2) print lib2.Op(2) print lib3.Op(2) 
+8
source share

Does the library really indicate that it wants a "uninitialized version" (ie a reference to the class)?

It seems to me that the library really wants a factory object. In this case, you can enter the type:

 lib3 = Library(lambda: Multiply(5)) 

To understand how lambda works, consider the following:

 Multiply5 = lambda: Multiply(5) assert Multiply5().run(3) == Multiply(5).run(3) 
+11
source share

This is kind of a hoax, but you can give your Multiply method a __call__ method that returns itself:

 class Multiply: def __init__(self,mult): self.mult = mult def __call__(self): return self def run(self,x): return x*self.mult 

Thus, when the library calls c() , it actually calls c.__call__() , which returns the desired object.

+1
source share
 def mult(x): def f(): return Multiply(x) return f op3 = mult(5) lib3 = Library(op3) print lib3.Op(2) 
+1
source share

If I understand your problematic space correctly, you have a common interface that takes a single argument, which is called using the Library class. Unfortunately, instead of calling a function, the Library assumes that the function is wrapped in a class using the run method.

You can create these classes programmatically. Classes can be returned by methods, and thanks to the concept of closures, you should be able to wrap any function in the class that suits your needs. Something like:

 def make_op(f): class MyOp(object): def run(self, x): return f(x) return MyOp op1 = make_op(lambda x: return x*2) op2 = make_op(lambda x: return x*3) def multiply_op(y): return make_op(lambda x: return x*y) op3 = multiply_op(3) lib1 = Library(op1) lib2 = Library(op2) lib3 = Library(op3) print( lib1.Op(2) ) print( lib2.Op(2) ) print( lib3.Op(2) ) 

Considering that changing the library to execute a function and then providing functions is probably a more efficient way to do this.

+1
source share

Since type is the default class class of a python class, and a class call creates a new instance of this class, a call type with the correct arguments will result in a new class.

 my_class = type("my_class", (object,), {"an_attribute": 1}) 

Now my_class refers to a new class called "my_class", which is a subclass of object , with the attribute "an_attribute", whose value is 1. Since methods are also just class attributes that point to a function object, you can add them to the attribute dictionary:

 {"an_attribute": 1, "a_method": lambda self: print("Hello")} 

Here's how it works. I do not recommend doing it this way unless you absolutely need to. In 99% of cases, you do not. See @Parker Coates answer for a clean way to achieve your goal.

0
source share

All Articles