赞
赏
封装是面向对象的三大特征之一,它指的是将 对象 的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该 类 所提供的 方法 来实现对内部信息的操作和访问。
封装机制保证了类内部数据结构的完整性,因为使用类的用户无法直接看到类中的数据结构,只能使用类允许公开的数据,很好地避免了外部对内部数据的影响,提高了程序的可维护性。
类的封装,其实是需要将对象的 属性 和实现细节隐藏起来,不允许外部直接访问。把方法暴露出来,让方法来控制对这些属性进行安全的访问和操作。因此,实际上封装有两个方面的含义:把该隐藏的隐藏起来,把该暴露的暴露出来。
在 Python 中,为了实现封装,我们需要将需要隐藏的属性 私有化,即使用双下划线修饰类的属性,即 __
。
使用 __
修饰类的方法,使类的方法私有化
print("嗨客网(www.haicoder.net)")
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print("Name =", self.name, "Age =", self.age)
person = Person("", -18)
person.info()
程序运行后,控制台输出如下:
我们定义了一个 Person 类,并且 Person 类有两个属性,分别为 name 和 age,接着,在实例化 Person 类时,我们给 Person 类实例的 name 字段设置为了 “”,age 字段设置了 -18。
这两个字段的值明显是不合理的,但此时我们没法控制这两个不合理的值,因此我们将程序修改如下:
print("嗨客网(www.haicoder.net)")
class Person(object):
def __init__(self, name, age):
if len(name) == 0:
self.name = "HaiCoder"
else:
self.name = name
if age < 1:
self.age = 1
else:
self.age = age
def info(self):
print("Name =", self.name, "Age =", self.age)
person = Person("", -18)
person.info()
程序运行后,控制台输出如下:
我们在 构造函数 里面,加了逻辑判断,如果传入的 name 属性是空,那么就将名字设置为 “HaiCoder”,如果 age 属性小于 1,那么就设置为 1,虽然不太合理,但至少避免了数据错。我们再次将程序修改如下:
print("嗨客网(www.haicoder.net)")
class Person(object):
def __init__(self, name, age):
if len(name) == 0:
self.name = "HaiCoder"
else:
self.name = name
if age < 1:
self.age = 1
else:
self.age = age
def info(self):
print("Name =", self.name, "Age =", self.age)
person = Person("", -18)
person.info()
person.name = ""
person.age = -18
person.info()
程序运行后,控制台输出如下:
我们发现,如果我们单独使用赋值的方式,来设置类的属性的值,还是可以设置不合理的值。我们再次将程序修改如下:
print("嗨客网(www.haicoder.net)")
class Person(object):
def __init__(self, name, age):
if len(name) == 0:
self.__name = "HaiCoder"
else:
self.__name = name
if age < 1:
self.__age = 1
else:
self.__age = age
def setname(self, val):
if len(val) == 0:
self.__name = "HaiCoder"
else:
self.__name = val
def getname(self):
return self.__name
name = property(getname, setname)
def setage(self, val):
if val < 1:
self.__age = 1
else:
self.__age = val
def getage(self):
return self.__age
age = property(getage, setage)
def info(self):
print("Name =", self.__name, "Age =", self.__age)
person = Person("", -18)
person.info()
person.name = "haicoder"
person.age = 109
person.info()
person.name = ""
person.age = -18
person.info()
程序运行后,控制台输出如下:
我们将类的 name 属性和 age 属性设置为了私有属性,同时,使用了 get 和 set 方法为这两个私有属性提供了设置值和访问的方法,在设置值的时候,我们判断了值的合法性,从而保证了数据的安全。
但是,我们发现,构造函数里面的 if 判断 与 set 方法里面的 if判断很类似,代码有点冗余,因此,我们再次将程序修改如下:
print("嗨客网(www.haicoder.net)")
class Person(object):
def __init__(self, name, age):
self.__setname(name)
self.__setage(age)
def setname(self, val):
self.__setname(val)
def getname(self):
return self.__name
name = property(getname, setname)
def setage(self, val):
if val < 1:
self.__age = 1
else:
self.__age = val
def getage(self):
return self.__age
age = property(getage, setage)
def info(self):
print("Name =", self.__name, "Age =", self.__age)
def __setname(self, val):
if len(val) == 0:
self.__name = "HaiCoder"
else:
self.__name = val
def __setage(self, val):
if val < 1:
self.__age = 1
else:
self.__age = val
person = Person("", -18)
person.info()
person.name = "haicoder"
person.age = 109
person.info()
person.name = ""
person.age = -18
person.info()
程序运行后,控制台输出如下:
我们将设置 name 属性和设置 age 属性的代码,抽象出来了,独立成为了一个私有的 __setname
方法和一个私有的 __setage
方法,然后,在构造函数和 set 函数里面,都调用私有的方法,从而避免了代码的冗余。
类的封装,其实是需要将对象的属性和实现细节隐藏起来,不允许外部直接访问。把方法暴露出来,让方法来控制对这些属性进行安全的访问和操作。因此,实际上封装有两个方面的含义:把该隐藏的隐藏起来,把该暴露的暴露出来。
在 Python 中,为了实现封装,我们需要将需要隐藏的属性私有化,即使用双下划线修饰类的属性,即 __
。