防止改变实例变量
Prevent altering instance variable
我想允许用户在实例化后更改 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.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"
请注意,一切都是一样的,但没有 setters 的属性在尝试修改时会抛出错误。
这确实会使您的 File
class 显着变大,但它会阻止用户更改 path
以外的成员,因为没有实施 setter。从技术上讲,用户仍然可以执行 file.__path = "something else"
,但通常认为以双下划线为前缀的成员是私有的,不应被篡改。
Dilanm 是对的。如果您需要将成员变量设置为只读或添加验证或其他访问权限任务,请使用属性。请注意 class 声明中的 (object) 是可选的,并且由于无法在 python classes 中强制执行私有成员,所以我只想用“_”强调我的意图,除非你真的有理由'__'。
#!/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)
要覆盖一个成员,只需在子 class 中再次定义它。属性没有什么不同。
我想允许用户在实例化后更改 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.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"
请注意,一切都是一样的,但没有 setters 的属性在尝试修改时会抛出错误。
这确实会使您的 File
class 显着变大,但它会阻止用户更改 path
以外的成员,因为没有实施 setter。从技术上讲,用户仍然可以执行 file.__path = "something else"
,但通常认为以双下划线为前缀的成员是私有的,不应被篡改。
Dilanm 是对的。如果您需要将成员变量设置为只读或添加验证或其他访问权限任务,请使用属性。请注意 class 声明中的 (object) 是可选的,并且由于无法在 python classes 中强制执行私有成员,所以我只想用“_”强调我的意图,除非你真的有理由'__'。
#!/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)
要覆盖一个成员,只需在子 class 中再次定义它。属性没有什么不同。