Python类@property:使用setter但逃避getter? [英] Python class @property: use setter but evade getter?

查看:70
本文介绍了Python类@property:使用setter但逃避getter?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在python类中,@property是一个很好的装饰器,避免使用显式的setter和getter函数。但是,它的开销是经典类函数的2到5倍。就我而言,在设置属性的情况下这是完全可以的,与设置时需要执行的处理相比,开销微不足道。

In python classes, the @property is a nice decorator that avoids using explicit setter and getter functions. However, it comes at a cost of an overhead 2-5 times that of a "classical" class function. In my case, this is quite OK in the case of setting a property, where the overhead is insignificant compared to the processing that needs to be done when setting.

但是,获得财产时我不需要任何处理。它始终只是返回自我属性。是否有一种优雅的方法来使用setter而不使用getter而不需要使用其他内部变量?

However, I need no processing when getting the property. It is always just "return self.property". Is there an elegant way to use the setter but not using the getter, without needing to use a different internal variable?

仅说明一下,下面的类具有 var,它是指内部变量 _var。调用 var要比使用 _var花费更长的时间,但是如果开发人员和用户都可以只使用 var而不必跟踪 _var,那就太好了。

Just to illustrate, the class below has the property "var" which refers to the internal variable "_var". It takes longer to call "var" than "_var" but it would be nice if developers and users alike could just use "var" without having to keep track of "_var" too.

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。

For those interested, on my pc calling "var" takes 204 ns on average while calling "_var" takes 44 ns on average.

推荐答案

在这种情况下,请勿使用属性属性对象是数据描述符,这意味着对 instance.var 的任何访问都将调用该描述符,而Python将

Don't use a property in this case. A property object is a data descriptor, which means that any access to instance.var will invoke that descriptor and Python will never look for an attribute on the instance itself.

您有两个选择:使用 .__ setattr __() 挂钩或构建仅实现 .__ set __

You have two options: use the .__setattr__() hook or build a descriptor that only implements .__set__.

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 并根据需要进行调整。

Now normal attribute lookups are used when reading .var but when assigning to .var the __setattr__ method is invoked instead, letting you intercept value and adjust it as needed.

演示:

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



设置描述符



setter描述符只会截取变量赋值:

A setter descriptor

A setter descriptor would only intercept variable assignment:

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 __ 属性,以防止再次调用设置器。

Note how we need to assign to the instance .__dict__ attribute to prevent invoking the setter again.

演示:

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

这篇关于Python类@property:使用setter但逃避getter?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆