2017-10-10 22 views
0

我有做一個匿名類的類:如何編程設置蟒蛇實例方法

class Anonyclass(object): 
    def __init__(self, **kwargs): 
     for kwarg in kwargs: 
      self.__setattr__(kwarg, kwargs[kwarg]) 

它的偉大工程動態設置的屬性,但是我不能設置實例方法這種方式,因爲他們沒有訪問到self。例如Anonyclass(foo = lambda x: x**2).foo(5) == 25,但我似乎無法在那裏推self ...

任何人都知道如何做到這一點?

+0

[將方法添加到現有對象實例](https://stackoverflow.com/questions/972/adding-a-method-to-an-existing-object-instance) –

回答

2

這不是創造新的「類」只是Anonyclass實例。 正如您可以設置實例屬性一樣,您可以設置知道它們綁定到哪個實例的可調用屬性。

from functools import partial 

class Anonyclass(object): 
    def __init__(self, **kwargs): 
     for kwarg, attr in kwargs.items(): 
      if callable(attr): 
        attr = partial(attr, self) 
      setattr(self, kwarg, attr) 

需要這個,因爲可贖回的情況下被設置繞過mechanism Python uses to bind a method to an instance汽車:

因此,假設所有可調用作爲參數,將採取self作爲第一個參數傳遞,你可以改變你的代碼 - 爲所有呼叫添加「自我」參數。所以我們使用functools.partial來做同樣的事情。 (這可以用lambda來完成,但是我們需要兩個lambda級別,以便「attr」變量保持自己綁定到正確的方法,而不是指向在for循環中分配的最後一個元素)

另外,如果你想真正創建和不綁定的屬性的情況下,你可以只需打個電話給type,傳遞你的kwargs您的代碼相同的參數:

def anon_class_factory(**kwargs): 
    return type("Anonyclass", (object,), kwargs) 

這將使任何在kwargs中傳遞的函數表現爲「真實」的方法。

1

你可以像下面這樣做。您可能需要修改for kwarg, value in kwargs.items():循環以檢查正在分配哪種類型的值,並以不同方式處理屬性的數據和/或屬性類型。因爲你的問題中沒有任何例子,所以我沒有嘗試過。

class _Callable(object): 
    def __init__(self, instance, name, value): 
     self.name = name 
     self.instance = instance 
     self.__setattr__(name, value) 

    def __call__(self, *args): 
     return self.__dict__[self.name](self.instance, *args) 

class AnonyClass(object): 
    def __init__(self, **kwargs): 
     for kwarg, value in kwargs.items(): 
      setattr(self, kwarg, _Callable(self, kwarg, value)) 

value = 6.480740698407860230965967436088 
print(AnonyClass(foo=lambda self, x: x**2).foo(value)) # -> 42.0 
+0

for this to work您必須將'Anonyclass .__ init__'中的'self'參數傳遞給'_Callable'實例。 – jsbueno

+1

@jsbueno:確實且固定。感謝您指出了這一點。沒有注意到,因爲testcase函數/方法沒有訪問它的'self'參數。 – martineau