fso*_*ety 1 python class object
我正在阅读我们如何确保python中的数据封装.博客中的一篇文章说"数据封装意味着,我们应该只能通过getter和setter访问私有属性"
请考虑以下来自博客的片段:
class Robot:
def __init__(self, name=None, build_year=None):
self.name = name
self.build_year = build_year
Run Code Online (Sandbox Code Playgroud)
现在,如果我创建类的对象如下:
obj1=Robot()
obj1.name('Robo1")
obj1.build_year("1978")
Run Code Online (Sandbox Code Playgroud)
目前,我可以直接访问属性,因为我已将它们公开定义(没有__表示法)
现在为了确保数据封装,我需要使用__符号将属性定义为私有,并通过getter和setter访问私有属性.
所以新的类定义如下:
class Robot:
def __init__(self, name=None, build_year=2000):
self.__name = name
self.__build_year = build_year
def set_name(self, name):
self.__name = name
def get_name(self):
return self.__name
def set_build_year(self, by):
self.__build_year = by
def get_build_year(self):
return self.__build_year
Run Code Online (Sandbox Code Playgroud)
现在我将类实例化如下:
x = Robot("Marvin", 1979)
x.set_build_year(1993)
Run Code Online (Sandbox Code Playgroud)
这样,我就不再直接访问私有数据成员,而只能通过类方法访问它们.
Q1:我们为什么要这样做?我们是谁保护代码?谁是外部世界?拥有源代码的任何人都可以根据他们的要求调整它,那么为什么我们要添加额外的方法(获取/设置)来修改/调整属性?
Q2:上面的例子是否被考虑过了data encapsulation?
数据封装比访问保护略胜一筹.name并且无论您如何定义属性,build_year都由类封装Robot.Python采取的立场是,除了访问或分配给底层属性之外什么都不做的getter和setter是不必要的.
即使使用双下划线前缀也只是建议,并且更关心防止子类中的名称冲突.如果你真的想__build_year直接获取属性,你仍然可以使用
# Prefix attribute name with _Robot
x._Robot__build_year = 1993
Run Code Online (Sandbox Code Playgroud)
Python中更好的设计是使用一个属性,这会导致Python在直接定义属性时调用已定义的getter和/或setter.例如:
class Robot(object):
def __init__(self, name, by):
self.name = name
self.build_year = by
@property
def name(self):
return self._name
@name.setter
def name(self, newname):
self._name = newname
@property
def build_year(self):
return self._build_year
@build_year.setter
def build_year(self, newby):
self._build_year = newby
Run Code Online (Sandbox Code Playgroud)
您实际上不会如此简单地定义这些属性函数,但是一个很大的好处是您可以从允许直接访问name属性开始,如果您稍后决定在获取/设置值中需要更多逻辑并且您想要要切换到属性,您可以这样做而不会影响现有代码.代码就像
x = Robot("bob", 1993)
x.build_year = 1993
Run Code Online (Sandbox Code Playgroud)
无论是否直接x.build_year = 1993分配,build_year或者它是否真的触发了对属性设置器的调用,它都将工作相同.
| 归档时间: |
|
| 查看次数: |
3161 次 |
| 最近记录: |