[英]Is an attribute protected if initialized as public but setters & getters treat it as protected?
在学习 Python 中面向对象编程的基础知识时,我遇到了一些我无法有效搜索以找到匹配关键字的问题:
我为一个基础类Course
编写了验证检查,它有一个受保护的属性_level
。 getter 和 setter 将其视为受保护的属性。 验证确保self._level
在 0 到 100 之间。
class Course:
def __init__(self, level=None):
self._level = level if level else 0
@property
def level(self):
return self._level
@level.setter
def level(self, value):
if not isinstance(value, int):
raise TypeError('The value of level must be of type int.')
if value < 0:
self._level = 0
elif value > 100:
self._level = 100
else:
self._level = value
###
courses = [Course(), Course(10), Course(-10), Course(150)]
for c in courses:
print(c.level)
>>> 0
>>> 10
>>> -10
>>> 150
self._level
更改为公共属性self.level
。 我的 setter 和 getter 仍然引用受保护的属性self._level
。class Course:
def __init__(self, level=None):
self.level = level if level else 0
@property
def level(self):
return self._level
@level.setter
def level(self, value):
if not isinstance(value, int):
raise TypeError('The value of level must be of type int.')
if value < 0:
self._level = 0
elif value > 100:
self._level = 100
else:
self._level = value
courses = [Course(), Course(10), Course(-10), Course(150)]
for c in courses:
print(c.level)
>>> 0
>>> 10
>>> 0
>>> 100
令我惊讶的是,这个类不仅意识到它是相同的属性,而且现在我的验证已经实现了!
Python 如何协调self.level
与self._level
,为什么我必须将其初始化为公共属性才能启动验证?
问题是你没有在__init__
中使用你的property
,所以当然,永远不会调用属性设置器!
self._level = level if level else 0
应该:
self.level = level if level else 0
一些建议,不要再用“受保护”与“公共”来思考了。 Python 运行时无法识别这样的东西, Python 中没有访问修饰符。 这些仅仅是命名约定。 我认为这个命名约定让你感到困惑。 没有理由如果你有
@property
def level(self):
...
应该修改一个名为_level
的变量,同样,这只是一个约定。 你可以随心所欲地称呼它。 因此,请考虑以下事项:
class Course:
def __init__(self, level=None):
self.foo = level if level else 0
@property
def level(self):
return self.foo
@level.setter
def level(self, value):
if not isinstance(value, int):
raise TypeError('The value of level must be of type int.')
if value < 0:
self.foo = 0
elif value > 100:
self.foo = 100
else:
self.foo = value
这应该会让你更清楚为什么你的__init__
从来没有真正调用过 setter——因为你没有使用这个属性! 该属性是level
,而不是foo
。 当然,您可能永远不会使用像上面这样的命名方案,因为它会造成混淆,但它应该可以说明您的代码发生了什么。
现在,为什么我们将__init__
更改为:
def __init__(self, level=None):
self.level = level if level else 0
该属性被调用。 因为self.level
是属性,而不是self.foo
。 属性 setters/getters 只会在你使用 self.level 而不是 self.foo 的属性self.level
self.foo
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.