2008-12-11 62 views
6

必須有一個簡單的方法來做到這一點,但不知何故,我可以把我的頭圍繞它。我可以描述我想要的最好的方式是一個類的lambda函數。我有一個圖書館期望作爲一個參數的一個類的未經證實的版本來處理。然後它實例化類自身來處理。問題是,我希望能夠動態創建類的版本,傳遞給庫,但我不知道如何去做,因爲庫期望一個未被證實的版本。下面的代碼說明了問題:python中的類的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) 

我不能使用通用乘類,因爲我必須先初始化它打破了圖書館「AttributeError的:乘實例沒有呼叫方法」。在不改變圖書館類的情況下,我有辦法做到這一點嗎?

回答

8

根本不需要lambda。 lambda只是用於定義函數並同時使用它的syntynt糖。就像任何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) 
+0

使用通用變頻器,當然是,它會在原則上接受任何一個帶參數的功能,從需要明確界定其類 – 2008-12-11 19:35:18

1

這有點作弊的,但你可以給你的乘法類__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__()返回所需的對象。

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


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

庫是否真的指定它需要「未初始化版本」(即類引用)?

它在我看來好像庫實際上想要一個對象工廠。在這種情況下,這是可以接受的類型:

lib3 = Library(lambda: Multiply(5)) 

要了解拉姆達是如何工作的,考慮以下因素:

Multiply5 = lambda: Multiply(5) 
assert Multiply5().run(3) == Multiply(5).run(3) 
1

如果我正確理解你的問題的空間,你有需要1的通用接口使用Library類調​​用的參數。不幸的是,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)) 

這就是說,改變庫函數,然後提供函數可能是更強大的方法來做到這一點。