2010-05-26 44 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() 

你基本上调用拉姆达,没有任何说法,这会导致错误。