微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用属性装饰器时,变量应该在 __init__ 中声明为 public 还是 private?

如何解决使用属性装饰器时,变量应该在 __init__ 中声明为 public 还是 private?

让我们考虑两个实现:

class A:
    def __init__(self,myvar):
        self._myvar = myvar # 

    @property
    def myvar(self):
        print("GET")
        return self._myvar

    @myvar.setter
    def myvar(self,newvar):
        print("SET")
        self._myvar = newvar

class B:
    def __init__(self,myvar):
        self.myvar = myvar

    @property
    def myvar(self):
        print("GET")
        return self._myvar

    @myvar.setter
    def myvar(self,newvar):
        print("SET")
        self._myvar = newvar

唯一的区别是在 __init__ 中,我们在 A 类中初始化了 _myvar,在 B 类中初始化了 myvar

a = A(myvar=5)
print(a.myvar)

输出

GET
5

b = B(myvar=5)
print(b.myvar)

输出

SET
GET
5

总而言之,根据我的理解,这两种实现的唯一区别在于 init.d 。类 A 的实例将直接设置 _myvar,而类 B 的实例将通过 myvar.setter 设置 _myvar。 所以我的问题如下: 哪个实现被认为更 pythonic ?是否有理由使用一个而不是另一个

解决方法

class B 是更好的做法。

假设您在 setter 中有一些验证步骤,例如您想确保仅将特定范围内的值设置为 myvarclass B 将确保即使通过构造函数运行验证步骤。但是,在 class A 的情况下,您是直接更新变量,在这种情况下,位于 setter 方法中的验证步骤将被跳过。

class EvenOnly_A:
  def __init__(self,myvar):
      self._myvar = myvar # 

  @property
  def myvar(self):
      return self._myvar

  @myvar.setter
  def myvar(self,newvar):
      assert newvar%2 == 0
      self._myvar = newvar


class EvenOnly_B:
  def __init__(self,myvar):
      self.myvar = myvar

  @property
  def myvar(self):
      return self._myvar

  @myvar.setter
  def myvar(self,newvar):
      assert newvar%2 == 0
      self._myvar = newvar 

a = EvenOnly_A(3)
b = EvenOnly_B(3)
,
  1. python 中没有真正的私有属性。人们可以随时访问它,例如a._myvar = 2。这只是一个约定——“我们都是成年人,你不应该惹恼这个”(有关详细信息,请参阅 here
  2. 在 python 中使用 getter 和 setter 的原因是你想执行一些额外的代码。否则就不需要使用 getter 和 setter。

假设您在设置属性值时确实想要执行额外的代码,那么类 B 是正确的实现,因为类 A 不会执行额外的代码。

,

好吧,我想提请注意,您的代码有一些问题。例如 -

在您的 B 类中,您在 init 方法中将变量定义为本地变量,但在 setter 方法中您使用的是私有方法。

class B:
    def __init__(self,myvar):
        self.myvar = myvar

    @property
    def myvar(self):
        print("GET")
        return self._myvar

    @myvar.setter
    def myvar(self,newvar):
        print("SET")
        self._myvar = newvar

self.__myvarself.var 是两个不同的东西。

所以下面这段代码会导致无限循环


class B:
    def __init__(self,myvar):
        self.myvar = myvar

    @property
    def myvar(self):
        print("GET")
        return self.myvar

    @myvar.setter
    def myvar(self,newvar):
        print("SET")
        self.myvar = newvar
b = B(myvar=5)
print(b.myvar)


现在,我想强调的是,在 Python 中你需要小心私有变量。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。