python python中类的Lambda函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/360368/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 19:57:29  来源:igfitidea点击:

Lambda function for classes in python?

pythonlambda

提问by gerdemb

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 callmethod". Without changing the Library class, is there a way I can do this?

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

采纳答案by Parker Coates

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)

回答by Deestan

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)

回答by Greg Hewgill

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__()它返回您想要的对象。

回答by Moe

def mult(x):
    def f():
        return Multiply(x)
    return f


op3 = mult(5)
lib3 = Library(op3)
print lib3.Op(2)

回答by Greg Case

If I understand your problem space correctly, you have a general interface that takes 1 argument which is called using the Libraryclass. Unfortunately, rather than calling a function, Libraryassumes that the function is wrapped in a class with a runmethod.

如果我正确理解您的问题空间,您将拥有一个通用接口,该接口采用 1 个参数,使用Library该类调用。不幸的是,不是调用函数,而是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.

话虽如此,将 Library 更改为获取一个函数然后提供函数可能是实现此目的的更强大的方法。

回答by Bachsau

Since typeis the default class of a python class object, and calling a class creates a new instance of that class, calling typewith the correct arguments will result in a new class.

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

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

my_classnow 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 的回答,了解实现目标的简洁方法。