11

必须有一种简单的方法来做到这一点,但不知何故我可以绕着它走。我可以描述我想要的最好的方法是一个类的 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)

我不能使用通用的 Multiply 类,因为我必须先实例化它,这会破坏库“AttributeError:Multiply 实例没有调用方法”。在不更改 Library 类的情况下,有没有办法可以做到这一点?

4

6 回答 6

12

库是否真的指定它想要一个“未初始化的版本”(即类引用)?

在我看来,图书馆好像真的想要一个对象工厂。在这种情况下,可以输入:

lib3 = Library(lambda: Multiply(5))

要了解 lambda 的工作原理,请考虑以下事项:

Multiply5 = lambda: Multiply(5)
assert Multiply5().run(3) == Multiply(5).run(3)
于 2008-12-11T18:44:54.597 回答
9

根本不需要 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)
于 2008-12-11T18:53:30.070 回答
1

这有点作弊,但你可以给你的 Multiply 类一个__call__返回自身的方法:

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

这样,当库调用c()它时,它实际上会调用c.__call__()它返回你想要的对象。

于 2008-12-11T18:39:04.110 回答
1
def mult(x):
    def f():
        return Multiply(x)
    return f


op3 = mult(5)
lib3 = Library(op3)
print lib3.Op(2)
于 2008-12-11T18:42:25.663 回答
1

Library如果我正确理解了您的问题空间,则您有一个通用接口,该接口接受 1 个使用该类调用的参数。不幸的是,不是调用函数,而是Library假设函数被包装在一个带有run方法的类中。

您当然可以以编程方式创建这些类。类可以由方法返回,并且由于闭包的概念,您应该能够将任何函数包装在满足您需求的类中。就像是:

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) )

话虽如此,将库更改为获取函数然后提供函数可能是执行此操作的更强大的方法。

于 2008-12-11T18:50:19.360 回答
0

由于type是 python 类对象的默认类,调用一个类会创建该类的一个新实例,type使用正确的参数调用将产生一个新类。

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

my_class现在引用一个名为“my_class”的新类,它是 的子类object,具有一个名为“an_attribute”的属性,其值为 1。由于方法也只是指向函数对象的类属性,因此您可以将它们添加到字典中属性以及:

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

这就是它的工作原理。我不建议这样做,除非你绝对需要。在 99% 的情况下,你没有。请参阅@Parker Coates 的回答,了解实现目标的干净方式。

于 2018-12-03T18:09:12.623 回答