2010-05-26 82 views
0

如何使用getattr調用方法? 我想創建一個元類,它可以調用其他一些以「oposite_」開頭的類的非現有方法。該方法應該有相同數量的參數,但要返回相反的結果。在Python中使用getattr調用方法

def oposite(func): 
    return lambda s, *args, **kw: not oposite(s, *args, **kw) 


class Negate(type): 
    def __getattr__(self, name): 
     if name.startswith('oposite_'): 
      return oposite(self.__getattr__(name[8:]))   
    def __init__(self,*args,**kwargs): 
     self.__getattr__ = Negate.__getattr__ 


class P(metaclass=Negate): 
    def yep(self): 
     return True 
    def maybe(self, sth): 
     return sth 

但問題是,

self.__getattr__(sth) 

返回NoneType對象。

>>> p = P() 
>>> p.oposite_yep() #should be False 
Traceback (most recent call last): 
    File "<pyshell#115>", line 1, in <module> 
    p.oposite_yep() 
TypeError: <lambda>() takes at least 1 positional argument (0 given) 
>>> p.oposite_maybe(False) #should be true 

如何處理這個問題?

+8

爲了記錄,「oposite」拼寫爲兩個p。但是,正如我的一位同事所說的,「程序員不需要拼寫正確,他們需要拼寫一致。」 – Seth 2010-05-27 00:05:44

回答

0

您忘記處理屬性名稱不是'oposite_'開頭的情況。

+0

這只是一個return語句。但即使如此,問題依然存在。 – 2010-05-26 23:48:24

0
class Negate(type): 
    def __getattr__(self, name): 
     if name.startswith('oposite_'): 
      def oposite(*args,**kwargs): 
       return not getattr(self,name[8:])(*args,**kwargs) 
      return oposite 
     else: 
      raise AttributeError("%r object has no attribute %r" % 
           (type(self).__name__, name)) 

    def __init__(self,*args,**kwargs): 
     self.__getattr__ = Negate.__getattr__ 

class P(metaclass=Negate): 
    def yep(self): 
     return True 
    def same(self,x,y): 
     return x==y 

p=P() 
print(p.oposite_yep()) 
# False 
print(p.oposite_same(1,2)) 
# True 
print(p.nope()) 

順便說一句,你還可以用類裝飾而不是一個元類做到這一點:

def Negater(cls): 
    def __getattr__(self, name): 
     if name.startswith('oposite_'): 
      def oposite(*args,**kwargs): 
       return not getattr(self,name[8:])(*args,**kwargs) 
      return oposite 
     else: 
      raise AttributeError("%r object has no attribute %r" % 
           (type(self).__name__, name)) 
    setattr(cls,'__getattr__',__getattr__) 
    return cls 

@Negater 
class P(): 
    .... 
+0

好的,但是如果yep除了自我沒有參數。如果你接受另一個論點,它就不起作用。 – 2010-05-27 06:42:56

0

的錯誤是"TypeError: <lambda>() takes at least 1 positional argument (0 given) "

這無關你元類的魔力,這是因爲您沒有將任何參數傳遞給lambda函數。

當你這樣做:

p.oposite_yep 

它叫__getattr__,它返回的opposite()的結果,這是一個lambda功能。

您的lamda函數被返回,它在飛行中創建,並且永遠不會被放入實例。它不會收到「自我」作爲第一個參數:它只是一個匿名函數。

所以,當你這樣做:

p.oposite_yep() 

你基本上調用拉姆達,沒有任何說法,這會導致錯誤。