Python类@property:使用setter但是避开getter?

在python类中,@property是一个很好的装饰器,避免使用显式的setter和getter函数。 然而,它的开销是“古典”类function的2-5倍。 就我而言,在设置属性的情况下,这相当不错,与设置时需要完成的处理相比,开销不重要。

但是,在取得物业时我不需要处理。 它总是只是“返回self.property”。 有没有一个优雅的方式来使用setter,但不使用getter,而不需要使用不同的内部variables?

为了说明,下面的类具有属性“var”,它指的是内部variables“_var”。 调用“var”比“_var”需要更长的时间,但如果开发人员和用户都可以使用“var”而不必跟踪“_var”,那将会很好。

class MyClass(object): def __init__(self): self._var = None # the property "var". First the getter, then the setter @property def var(self): return self._var @var.setter def var(self, newValue): self._var = newValue #... and a lot of other stuff here # Use "var" a lot! How to avoid the overhead of the getter and not to call self._var! def useAttribute(self): for i in xrange(100000): self.var == 'something' 

对于那些有兴趣的,在我的电脑上调用“var”平均需要204 ns,而调用“_var”平均需要44 ns。

在这种情况下不要使用property 。 一个property对象是一个数据描述符,这意味着对instance.var任何访问都将调用该描述符,Python将永远不会在实例本身上查找属性。

你有两个select:使用.__setattr__()钩子或build立一个只能实现.__set__的描述符。

使用.__setattr__()钩子

 class MyClass(object): var = 'foo' def __setattr__(self, name, value): if name == 'var': print "Setting var!" # do something with `value` here, like you would in a # setter. value = 'Set to ' + value super(MyClass, self).__setattr__(name, value) 

现在在读取 .var时使用普通的属性查找,但是当赋值给.var ,会调用__setattr__方法,让您截取value并根据需要进行调整。

演示:

 >>> mc = MyClass() >>> mc.var 'foo' >>> mc.var = 'bar' Setting var! >>> mc.var 'Set to bar' 

一个setter描述符

setter描述符只会拦截variables赋值:

 class SetterProperty(object): def __init__(self, func, doc=None): self.func = func self.__doc__ = doc if doc is not None else func.__doc__ def __set__(self, obj, value): return self.func(obj, value) class Foo(object): @SetterProperty def var(self, value): print 'Setting var!' self.__dict__['var'] = value 

注意我们需要如何分配给实例.__dict__属性来防止再次调用setter。

演示:

 >>> f = Foo() >>> f.var = 'spam' Setting var! >>> f.var = 'ham' Setting var! >>> f.var 'ham' >>> f.var = 'biggles' Setting var! >>> f.var 'biggles' 

property python文档: https : //docs.python.org/2/howto/descriptor.html#properties

 class MyClass(object): def __init__(self): self._var = None # only setter def var(self, newValue): self._var = newValue var = property(None, var) c = MyClass() c.var = 3 print ('ok') print (c.var) 

输出:

 ok Traceback (most recent call last): File "Untitled.py", line 15, in <module> print c.var AttributeError: unreadable attribute