实例化后装饰类及其成员

时间:2015-10-30 09:19:08

标签: python decorator

我试图创建一些装饰器,允许在实例化时装饰类成员,因为我想要一些装饰的实例和其他不是。

在下面的示例中,将once装饰器应用于SomeClass实例的预期结果是,当调用some_func时,调用other_func会打印一条消息而不是调用原始函数。

#!/usr/bin/env python

import functools

def some_once(func):
    @functools.wraps(func)
    def wrapped(self, *args, **kwargs):
        if not self._new_attr:
            print("don't have new attr yet")
            func(self, *args, **kwargs)
            self._new_attr = True

    return wrapped

def other_once(func):
    @functools.wraps(func)
    def wrapped(self, *args, **kwargs):
        if self._new_attr:
            print("We have a new attr")
        else:
            func(self, *args, **kwargs)

    return wrapped

def once(cls):
    setattr(cls, "_new_attr", False)
    setattr(cls, "some_func", some_once(cls.some_func))
    setattr(cls, "other_func", other_once(cls.other_func))
    return cls

class SomeClass:

    def some_func(self, parameter):
        return "The parameter is " + str(parameter)

    def other_func(self, parameter):
        return "The other parameter is " + str(parameter)

if __name__ == '__main__':
    a = SomeClass()
    print(dir(a))
    print(a.some_func("p1"))
    print(a.other_func("p2"))

    b = once(SomeClass())
    print(dir(b))
    print(b.some_func("p3"))
    print(b.other_func("p4"))

结果的问题在于,不是查看self._new_attr,而是查看string._new_attr,而字符串是函数的参数。我对这里的错误感到困惑。

1 个答案:

答案 0 :(得分:1)

不要装饰实例。做一个新的装饰课。

更改此行:

private double Distance(double lat1, double lon1, double lat2, double lon2, int unit) 
    {  
      double theta = lon1 - lon2;  
      double dist = Math.Sin(Deg2rad(lat1)) * Math.Sin(Deg2rad(lat2)) + Math.Cos(Deg2rad(lat1)) * Math.Cos(Deg2rad(lat2)) * Math.Cos(Deg2rad(theta));  
      dist = Math.Acos(dist);  
      dist = Rad2deg(dist);  
      dist = dist * 60 * 1.1515;  
      if (unit == GeoFence.RadiusUnits.Kilometers.GetHashCode()) 
      {  
        dist = dist * 1.609344;  //kilometers
      } 
      else if (unit ==  GeoFence.RadiusUnits.Feet.GetHashCode()) 
      {  
        //Here I need to calculate distance in feet
      } 
      return (dist);  //By default the distance is in statute miles 
    } 

成:

b = once(SomeClass())

应该做的伎俩。 b = once(SomeClass)() 为您提供了一个新的装饰类。在下一步中创建一个实例。