There must be an easy way to do this, but somehow I can wrap my head around it. 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 uninstantiated version of a class to work with. It then instantiates the class itself to work on. The problem is that I'd like to be able to dynamically create versions of the class, to pass to the library, but I can't figure out how to do it since the library expects an uninstantiated version. The code below describes the problem:
必须有一个简单的方法来做到这一点,但不知怎的,我可以绕过它。我能描述我想要的最好的方法是一个类的lambda函数。我有一个库,希望作为一个参数,可以使用一个未经实例化的类。然后它实例化类本身以继续工作。问题是我希望能够动态创建类的版本,传递给库,但我无法弄清楚如何做到这一点,因为库需要一个未实例化的版本。下面的代码描述了问题:
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 can't use the generic Multiply class, because I must instantiate it first which breaks the library "AttributeError: Multiply instance has no call method". Without changing the Library class, is there a way I can do this?
我不能使用通用的Multiply类,因为我必须首先实例化它,它会破坏库“AttributeError:Multiply instance has no call method”。在不更改Library类的情况下,有没有办法可以做到这一点?
6 个解决方案
#1
8
There's no need for lambda at all. lambda is just syntatic sugar to define a function and use it at the same time. Just like 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 returning it.
根本不需要lambda。 lambda只是合成糖来定义一个函数并同时使用它。就像任何lambda调用可以用显式def替换一样,我们可以通过创建满足您需求并返回它的真实类来解决您的问题。
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)
#2
11
Does the library really specify that it wants an "uninitialized version" (i.e. a class reference)?
库是否真的指定它需要“未初始化的版本”(即类引用)?
It looks to me as if the library actually wants an object factory. In that case, it's acceptable to type:
它看起来好像图书馆实际上想要一个对象工厂。在这种情况下,键入以下内容是可以接受的:
lib3 = Library(lambda: Multiply(5))
To understand how the lambda works, consider the following:
要了解lambda的工作原理,请考虑以下事项:
Multiply5 = lambda: Multiply(5)
assert Multiply5().run(3) == Multiply(5).run(3)
#3
1
This is sort of cheating, but you could give your Multiply class a __call__
method that returns itself:
这有点作弊,但您可以为Multiply类提供一个返回自身的__call__方法:
class Multiply:
def __init__(self,mult):
self.mult = mult
def __call__(self):
return self
def run(self,x):
return x*self.mult
That way when the library calls c()
it actually calls c.__call__()
which returns the object you want.
这样当库调用c()时它实际上调用c .__ call __()返回你想要的对象。
#4
1
def mult(x):
def f():
return Multiply(x)
return f
op3 = mult(5)
lib3 = Library(op3)
print lib3.Op(2)
#5
1
If I understand your problem space correctly, you have a general interface that takes 1 argument which is called using the Library
class. Unfortunately, rather than calling a function, Library
assumes that the function is wrapped in a class with a run
method.
如果我正确理解你的问题空间,你有一个通用接口,它接受1个参数,使用Library类调用。不幸的是,不是调用函数,而是假设函数包含在带有run方法的类中。
You can certainly create these classes programatically. Classes may be returned by methods, and thanks to the concept of closures you should be able to wrap any function in a Class that meets 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) )
That being said, changing Library to take a function and then providing functions is probably the stronger way to do this.
话虽如此,更改库以获取功能然后提供功能可能是更好的方法。
#6
0
Since type
is the default class of a python class object, and calling a class creates a new instance of that class, calling type
with the correct arguments will result in a new class.
由于type是python类对象的默认类,并且调用类会创建该类的新实例,因此使用正确的参数调用type将导致生成新类。
my_class = type("my_class", (object,), {"an_attribute": 1})
my_class
now refers to a new class named "my_class", which is a subclass of object
, with an attribute called "an_attribute", whose value is 1. Since methods are also just class attributes pointing to a function object, you can add them to the dictionary of attributes as well:
my_class现在引用一个名为“my_class”的新类,它是object的子类,具有一个名为“an_attribute”的属性,其值为1.由于方法也只是指向函数对象的类属性,因此可以将它们添加到属性字典也是:
{"an_attribute": 1, "a_method": lambda self: print("Hello")}
This is how it works. I do not recommend doing it this way, unless you absolutely need to. In 99% of all cases, you don't. Refer to @Parker Coates' answer for the clean way to achieve your goal.
这是它的工作原理。除非你绝对需要,否则我不建议这样做。在99%的情况下,你没有。请参阅@Parker Coates的答案,了解实现目标的干净方法。
#1
8
There's no need for lambda at all. lambda is just syntatic sugar to define a function and use it at the same time. Just like 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 returning it.
根本不需要lambda。 lambda只是合成糖来定义一个函数并同时使用它。就像任何lambda调用可以用显式def替换一样,我们可以通过创建满足您需求并返回它的真实类来解决您的问题。
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)
#2
11
Does the library really specify that it wants an "uninitialized version" (i.e. a class reference)?
库是否真的指定它需要“未初始化的版本”(即类引用)?
It looks to me as if the library actually wants an object factory. In that case, it's acceptable to type:
它看起来好像图书馆实际上想要一个对象工厂。在这种情况下,键入以下内容是可以接受的:
lib3 = Library(lambda: Multiply(5))
To understand how the lambda works, consider the following:
要了解lambda的工作原理,请考虑以下事项:
Multiply5 = lambda: Multiply(5)
assert Multiply5().run(3) == Multiply(5).run(3)
#3
1
This is sort of cheating, but you could give your Multiply class a __call__
method that returns itself:
这有点作弊,但您可以为Multiply类提供一个返回自身的__call__方法:
class Multiply:
def __init__(self,mult):
self.mult = mult
def __call__(self):
return self
def run(self,x):
return x*self.mult
That way when the library calls c()
it actually calls c.__call__()
which returns the object you want.
这样当库调用c()时它实际上调用c .__ call __()返回你想要的对象。
#4
1
def mult(x):
def f():
return Multiply(x)
return f
op3 = mult(5)
lib3 = Library(op3)
print lib3.Op(2)
#5
1
If I understand your problem space correctly, you have a general interface that takes 1 argument which is called using the Library
class. Unfortunately, rather than calling a function, Library
assumes that the function is wrapped in a class with a run
method.
如果我正确理解你的问题空间,你有一个通用接口,它接受1个参数,使用Library类调用。不幸的是,不是调用函数,而是假设函数包含在带有run方法的类中。
You can certainly create these classes programatically. Classes may be returned by methods, and thanks to the concept of closures you should be able to wrap any function in a Class that meets 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) )
That being said, changing Library to take a function and then providing functions is probably the stronger way to do this.
话虽如此,更改库以获取功能然后提供功能可能是更好的方法。
#6
0
Since type
is the default class of a python class object, and calling a class creates a new instance of that class, calling type
with the correct arguments will result in a new class.
由于type是python类对象的默认类,并且调用类会创建该类的新实例,因此使用正确的参数调用type将导致生成新类。
my_class = type("my_class", (object,), {"an_attribute": 1})
my_class
now refers to a new class named "my_class", which is a subclass of object
, with an attribute called "an_attribute", whose value is 1. Since methods are also just class attributes pointing to a function object, you can add them to the dictionary of attributes as well:
my_class现在引用一个名为“my_class”的新类,它是object的子类,具有一个名为“an_attribute”的属性,其值为1.由于方法也只是指向函数对象的类属性,因此可以将它们添加到属性字典也是:
{"an_attribute": 1, "a_method": lambda self: print("Hello")}
This is how it works. I do not recommend doing it this way, unless you absolutely need to. In 99% of all cases, you don't. Refer to @Parker Coates' answer for the clean way to achieve your goal.
这是它的工作原理。除非你绝对需要,否则我不建议这样做。在99%的情况下,你没有。请参阅@Parker Coates的答案,了解实现目标的干净方法。