代码之家  ›  专栏  ›  技术社区  ›  gerdemb

Python中类的lambda函数?

  •  8
  • gerdemb  · 技术社区  · 16 年前

    一定有一个简单的方法,但不知何故,我可以把我的头绕起来。我能描述我想要的是类的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)
    

    我不能使用通用的multiple类,因为我必须先实例化它,这会破坏库“attributeError:multiple instance has no 呼叫 方法“。在不改变图书馆课程的情况下,我有办法做到这一点吗?

    6 回复  |  直到 6 年前
        1
  •  8
  •   Parker Coates    16 年前

    根本不需要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
  •   Deestan    16 年前

    库是否确实指定它需要“未初始化的版本”(即类引用)?

    在我看来,库实际上想要一个对象工厂。在这种情况下,可以输入:

    lib3 = Library(lambda: Multiply(5))
    

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

    Multiply5 = lambda: Multiply(5)
    assert Multiply5().run(3) == Multiply(5).run(3)
    
        3
  •  1
  •   Greg Hewgill    16 年前

    这是一种欺骗,但你可以给你的乘法A班 __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__() 返回所需的对象。

        4
  •  1
  •   Moe    16 年前
    def mult(x):
        def f():
            return Multiply(x)
        return f
    
    
    op3 = mult(5)
    lib3 = Library(op3)
    print lib3.Op(2)
    
        5
  •  1
  •   Greg Case    16 年前

    如果我正确理解了您的问题空间,那么您有一个采用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) )
    

    也就是说,将库更改为接受一个函数,然后提供函数可能是实现这一点的更强大的方法。

        6
  •  0
  •   Bachsau    6 年前

    自从 type 是Python类对象的默认类,调用类将创建该类的新实例,调用 类型 如果参数正确,将生成一个新类。

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

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

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

    这就是它的工作原理。我不建议这样做,除非你绝对需要这样做。在99%的情况下,你没有。请参考@parker coates的答案,了解实现目标的清洁方式。