【问题标题】:python property decorator in OOPOOP中的python属性装饰器
【发布时间】:2018-07-06 09:56:46
【问题描述】:

我正在测试在 OOP 中使用 @property 的想法:

class Person(object):
    @property
    def name(self):
        return self.name

    @name.setter
    def name(self, newname):
        self.name = newname

james = Person()
james.name = 'James Bond'
print(james.name)
>>> RecursionError: maximum recursion depth exceeded

不知何故,这给了我一个递归错误??

但如果我将self.name 更改为self._name,似乎可以解决问题。所以我想我在使用name() 作为@property 时不能设置self.name

【问题讨论】:

  • 描述符协议的重点是obj.x调用x.__get__

标签: python decorator


【解决方案1】:

错误的原因是您试图返回一个与property 修饰的方法同名的属性。因此,当您调用方法name 时,调用会再次触发该方法,因为self.name 是类中声明的方法。这会触发非终止递归。相反,更改属性名称:

class Person(object):
   @property
   def name(self):
     return self._name

   @name.setter
   def name(self, newname):
      self._name = newname

【讨论】:

  • 那么我发现的添加'_'的方法是正确的方法吗?
  • @Code_Control_jxie0755 在这种情况下,您需要做的就是更改变量名。一般_variablename用于property的大部分演示。
  • 另一种方法是使用self.__dict__['name'],它有点神秘,但隐藏属性值的方法非常酷。
【解决方案2】:

此外,如果您认为 _ 表示法难看,您可以创建内部代理对象(python 3.3+ 的示例):

import types

class Person(object):
   def __init__(self):
       self.me = types.SimpleNamespace(name = "")

   @property
   def name(self):
     return self.me.name

   @name.setter
   def name(self, newname):
      self.me.name = newname

【讨论】:

  • 你并没有真正消除对我来说_的主要丑陋之处,那就是你创建了另一个属性供用户修改。
  • 也许类装饰器的小魔法可以保护变量不被覆盖:stackoverflow.com/a/39716001/4265407 但不能防止字段访问和操作。我认为我们需要像 inspect 这样的东西来做到这一点。
  • 正如我对另一个答案的建议,self.__dict__['name'] 通过利用类上的数据属性优先于实例字典条目来隐藏属性。
  • 但如果我写了s.__dict__['name'] = "foo",我可以在之后写s.name = "bar"。鉴于许多关键变量通常在类构造函数中定义/分配......
猜你喜欢
  • 2012-07-15
  • 2022-11-09
  • 2017-01-06
  • 2013-03-17
  • 2014-06-25
  • 1970-01-01
  • 2019-10-29
  • 2020-10-07
  • 2014-02-08
相关资源
最近更新 更多