Python 防止更改实例变量
我希望允许用户在实例化后更改self.path,但不允许更改任何其他实例变量。但是,如果更改了self.path,则应重新计算其他实例变量。这可能吗Python 防止更改实例变量,python,variables,instance-variables,Python,Variables,Instance Variables,我希望允许用户在实例化后更改self.path,但不允许更改任何其他实例变量。但是,如果更改了self.path,则应重新计算其他实例变量。这可能吗 class File(object): def __init__(self, path): self.path = os.path.abspath(path) self.name = os.path.basename(self.path) self.parent = os.path.dirn
class File(object):
def __init__(self, path):
self.path = os.path.abspath(path)
self.name = os.path.basename(self.path)
self.parent = os.path.dirname(self.path)
self.extension = self._get_extension()
self.category = self.get_category(self.extension)
self.exists = os.path.isfile(self.path)
def _get_extension(self):
extension = None
result = os.path.splitext(self.name)[1][1:]
if result:
extension = result
return extension
def get_category(self, extension):
if extension:
file_extension = extension.upper()
for key in fileGroups.keys():
common = set(fileGroups[key]) & set([file_extension])
if common:
return key
return 'UNDEFINED'
您要查找的是属性getter/setter模式。Python通过@property
和@member.setter
实现这一点,您可以在上面的答案示例中看到这一点
对于您的问题,您可以通过执行以下操作来解决:
class File(object):
def __init__(self, path):
self.__path = os.path.abspath(path)
self.__name = os.path.basename(self.path)
self.__parent = os.path.dirname(self.path)
self.__extension = self._get_extension()
self.__category = self.get_category(self.extension)
self.__exists = os.path.isfile(self.path)
@property
def path(self):
return self.__path
@path.setter
def path(self, value):
self.__path = value
# Update other variables here too
@property
def name(self):
return self.__name
etc for the rest of your properties
这意味着你可以做以下事情:
file = File("a path")
print(file.path)
file.path = "some other path"
# This will throw an AttributeError
file.name = "another name"
请注意,所有操作都是相同的,但是如果试图修改没有设置器的属性,则会抛出错误
这确实会使文件
类显著增大,但它会阻止用户更改路径
以外的成员,因为没有实现setter。从技术上讲,用户仍然可以执行文件。uu path=“something other”
但一般认为,前缀为双下划线的成员是私有的,不应被篡改。您要查找的是属性getter/setter模式。Python通过@property
和@member.setter
实现这一点,您可以在上面的答案示例中看到这一点
对于您的问题,您可以通过执行以下操作来解决:
class File(object):
def __init__(self, path):
self.__path = os.path.abspath(path)
self.__name = os.path.basename(self.path)
self.__parent = os.path.dirname(self.path)
self.__extension = self._get_extension()
self.__category = self.get_category(self.extension)
self.__exists = os.path.isfile(self.path)
@property
def path(self):
return self.__path
@path.setter
def path(self, value):
self.__path = value
# Update other variables here too
@property
def name(self):
return self.__name
etc for the rest of your properties
这意味着你可以做以下事情:
file = File("a path")
print(file.path)
file.path = "some other path"
# This will throw an AttributeError
file.name = "another name"
请注意,所有操作都是相同的,但是如果试图修改没有设置器的属性,则会抛出错误
这确实会使
文件
类显著增大,但它会阻止用户更改路径
以外的成员,因为没有实现setter。从技术上讲,用户仍然可以使用文件。uuu path=“something other”
但一般认为前缀为双下划线的成员是私有的,不应被篡改。Dilanm是正确的。如果需要将成员变量设置为只读,或在access上添加验证或其他任务,请使用属性。请注意,类声明中的(object)是可选的,因为在python类中没有强制私有成员的方法,所以我只想用“u”来强调我的意图,除非您确实有理由使用“u”
#!/usr/bin/env python3
import os.path
class File:
def __init__(self, path):
self._path = path
self.compute_others()
def compute_others(self):
self._parent = os.path.dirname(self._path)
pass # add other attributes to be computed
# getter, also makes .path read-only
@property
def path(self):
return self._path
# setter, allows setting but adds validation or other tasks
@path.setter
def path(self, path):
self._path = path
self.compute_others()
# other attributes only have getters (read-only)
@property
def parent(self):
return self._parent
def __str__(self):
return 'path:{}\nparent:{}\n\n'.format(self.path, self.parent)
f = File('/usr')
print(f)
f.path = '/usr/local'
#f.parent = '/tmp' # error, read-only property
print(f)
若要重写成员,只需在子类中再次定义它。属性也一样。迪兰姆是对的。如果需要将成员变量设置为只读,或在access上添加验证或其他任务,请使用属性。请注意,类声明中的(object)是可选的,因为在python类中没有强制私有成员的方法,所以我只想用“u”来强调我的意图,除非您确实有理由使用“u”
#!/usr/bin/env python3
import os.path
class File:
def __init__(self, path):
self._path = path
self.compute_others()
def compute_others(self):
self._parent = os.path.dirname(self._path)
pass # add other attributes to be computed
# getter, also makes .path read-only
@property
def path(self):
return self._path
# setter, allows setting but adds validation or other tasks
@path.setter
def path(self, path):
self._path = path
self.compute_others()
# other attributes only have getters (read-only)
@property
def parent(self):
return self._parent
def __str__(self):
return 'path:{}\nparent:{}\n\n'.format(self.path, self.parent)
f = File('/usr')
print(f)
f.path = '/usr/local'
#f.parent = '/tmp' # error, read-only property
print(f)
若要重写成员,只需在子类中再次定义它。属性也一样。谢谢,帮助很大。但是如何在文件的子类中重写path@property?(如果你不介意的话)@giantas这个答案应该也能帮你找到下面的答案,它使用了
Super
,实际上我只是自己测试了一下,你甚至不需要这么做,看看我制作的这个贴纸:(这不适用于骑自行车,但可能仍然有用)谢谢,帮助很大。但是如何在文件的子类中重写path@属性呢?(如果你不介意的话)@giantas这个答案应该也能帮助你找到下面的答案,它使用了Super
,事实上我只是自己测试了它,你甚至不需要这样做,看看我制作的这个粘贴:(这不适用于过度使用,但可能仍然有用)“注意(对象)在类声明中是可选的”:仅在Python 3.x中。在Python2.x中,它在技术上是“可选的”,但随后会生成一个“旧式类”,该类不能正确处理属性(以及一般的描述符),因此在本例中它不是可选的。“请注意,类声明中的(对象)是可选的”:仅在Python3.x中。在Python2.x中,它在技术上是“可选的”,但随后会生成一个“旧式类”,它不能正确处理属性(以及一般的描述符),因此在本例中它不是可选的。