使用属性装饰器时,变量在__init__中应该声明为public还是private?
When using property decorator, should the variable be declared as public or private in __init__?
让我们考虑两种实现方式:
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__
我们在 class A 中初始化了 _myvar,在 class B
中初始化了 myvar
a = A(myvar=5)
print(a.myvar)
会输出
GET
5
和
b = B(myvar=5)
print(b.myvar)
会输出
SET
GET
5
总而言之,据我了解,这两种实现的唯一区别在于init. class A 的实例将直接设置 _myvar,而 class B 的实例将通过 myvar.setter 设置 _myvar。
所以我的问题如下:
哪个实现被认为更 pythonic ?有理由使用一个而不是另一个吗?
- python 中没有真正的私有属性。人们总是可以访问它,例如
a._myvar = 2
。这只是一个惯例——“我们都是成年人,你不应该惹这个”(更多细节见here。
- 在 python 中使用 getter 和 setter 的原因是您想执行一些额外的代码。否则就不需要使用 getters 和 setters.
假设您确实想要在设置属性值时执行额外的代码,class B是正确的实现,因为 class A 不会执行额外的代码。
class B
是更好的做法。
假设您在 setter
中有一些验证步骤,例如您要确保仅将特定范围内的值设置为 myvar
。 class 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)
好吧,我想提请注意您的代码有一些问题。例如-
在您的 Class 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.__myvar
和 self.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 中,您需要小心使用私有变量。
让我们考虑两种实现方式:
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__
我们在 class A 中初始化了 _myvar,在 class B
a = A(myvar=5)
print(a.myvar)
会输出
GET
5
和
b = B(myvar=5)
print(b.myvar)
会输出
SET
GET
5
总而言之,据我了解,这两种实现的唯一区别在于init. class A 的实例将直接设置 _myvar,而 class B 的实例将通过 myvar.setter 设置 _myvar。 所以我的问题如下: 哪个实现被认为更 pythonic ?有理由使用一个而不是另一个吗?
- python 中没有真正的私有属性。人们总是可以访问它,例如
a._myvar = 2
。这只是一个惯例——“我们都是成年人,你不应该惹这个”(更多细节见here。 - 在 python 中使用 getter 和 setter 的原因是您想执行一些额外的代码。否则就不需要使用 getters 和 setters.
假设您确实想要在设置属性值时执行额外的代码,class B是正确的实现,因为 class A 不会执行额外的代码。
class B
是更好的做法。
假设您在 setter
中有一些验证步骤,例如您要确保仅将特定范围内的值设置为 myvar
。 class 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)
好吧,我想提请注意您的代码有一些问题。例如-
在您的 Class 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.__myvar
和 self.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 中,您需要小心使用私有变量。