我是Python的新手,如果这是一个基础问题,请原谅我。我在互联网和SO上研究了这个主题,但是我找不到解释。我正在使用Anaconda 3.6发行版。
我想为属性创建一个简单的getter和setter。我将向您展示我遇到的错误。
class Person:
def __init__(self,name):
self.name=name
bob = Person('Bob Smith')
print(bob.name)
这将打印出第一个名字。我同意我没有覆盖print
或getattribute
方法。另外,这里没有属性。这是为了测试基本代码是否正常工作。
让我们修改代码以添加属性:
class Person:
def __init__(self,name):
self.name=name
@property
def name(self):
"name property docs"
print('fetch...')
return self.name
bob = Person('Bob Smith')
print(bob.name)
在PyCharm中编写上述代码后,我会得到一个黄色的小灯泡图标,提示变量必须是私有的。我不明白这个要求的原因。
如果忽略上述警告运行代码,将会得到以下结果:
Traceback (most recent call last): File "C:\..., in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "<ipython-input-25-62e9a426d2a9>", line 2, in <module> bob = Person('Bob Smith') File "<ipython-input-24-6c55f4b7326f>", line 4, in __init__ self.name=name AttributeError: can't set attribute
现在,我研究了这个话题,发现有两种解决方法(不知道为什么有效):
解决方法 #1: 将变量name
更改为_name
class Person:
def __init__(self,name):
self._name=name #Changed name to _name
@property
def name(self):
"name property docs"
print('fetch...')
return self._name #Changed name to _name
bob = Person('Bob Smith')
print(bob.name)
这个做法很好,它可以正确地输出结果。
修复方法2:将属性名从name(self)
改为_name(self)
,并将变量名从_name
恢复为name
。
class Person:
def __init__(self,name):
self.name=name #changed to name
@property
def _name(self): #Changed to _name
"name property docs"
print('fetch...')
return self.name #changed to name
bob = Person('Bob Smith')
print(bob.name)
现在,这个代码像预期的那样打印出结果。
接下来,我使用装饰器创建了setter
、getter
和deleter
属性。它们遵循与上述类似的命名约定——即在变量名或方法名前缀添加_
:
@_name.setter
def _name(self,value):
"name property setter"
print('change...')
self.name=value
@_name.deleter
def _name(self):
print('remove')
del self.name
bob = Person('Bob Smith')
print(bob.name)
bob.name = 'Bobby Smith'
print(bob.name)
del bob.name
问题:我不太确定为什么Python 3.x要强制在变量名或方法名中添加
_
。根据Python属性公共getter和私有setter、Python带下划线前后的属性有什么区别和https://www.python.org/dev/peps/pep-0008/#naming-conventions,下划线前缀是向用户表明这个变量是私有变量的一种弱指示符,但没有额外的机制(类似于Java所做的)来检查或纠正这种行为。
因此,现在的关键问题是为什么我需要在属性中使用下划线?我认为这些下划线前缀只是为了让用户知道这是一个私有变量。
我正在使用Lutz的书学习Python,上面的例子是受他的书启发的。
foo
的属性,当其实现访问foo
时,您认为会发生什么? - Ignacio Vazquez-Abrams