一、封装
封装是指隐藏对象中一些不希望被外部所访问到的属性或方法。(我个人理解其具体的隐藏方法或者思路,实际上就是在定义属性名的时候,属性名不要取的太常规)
出现封装的原因:我们需要一种方式来增强数据的安全性
• 1. 属性不能随意修改
• 2. 属性不能改为任意的值
比如:
class Car():
def __init__(self,name,color):
self.name=name
self.color=color
def run(self):
print(self.name,'汽车开动了')
car1=Car('法拉利','红色')
car1.run()
car1.name='兰博基尼'
car1.run()
car1.name='中华田园犬'
car1.run()
结果:
中华田园犬 和汽车开动了,明显是不合适的,所以我们就不想要car1的name属性被轻易的修改。
为了防止数据被更改,我们引入封装,以告诉协同开发者,某个属性很重要,不要轻易修改。
由此:
class Car():
def __init__(self,name,color):
self._name=name #这个‘_’就告诉别人,这是个私有属性,不要轻易修改
self.color=color
def run(self):
print(self._name,'汽车开动了')
car1=Car('法拉利','红色')
car1.run()
car1.name='中华田园犬'#也能顺利运行,没有报错,这相当于创建了一个新的属性
car1.run()
print(car1.name)
结果:
这样就修改不了了。
但实际上,想要修改也可以。所以说“防君子,不防小人”
如下:
class Car():
def __init__(self,name,color):
self._name=name #这个—就告诉别人,这是个私有属性,不要轻易修改
self.color=color
def run(self):
print(self._name,'汽车开动了')
car1=Car('法拉利','红色')
car1.run()
car1.name='中华田园犬'#也能顺利运行,没有报错,这相当于创建了一个新的属性
car1.run()
print(car1.name)
car1._name='中华田园犬'
car1.run()
结果:
1、完全封装(隐藏属性):即用__name(双下划线后属性名)来定义属性。
class Car():
def __init__(self,name,color):
self.__name=name
self.color=color
def run(self):
print(self.__name,'汽车开动了')
car1=Car('法拉利','红色')
car1.run()
结果:
完全封装时,若要访问到该属性,用print(car1.__name)将报错报错’Car’ object has no attribute ‘__name’
因为双下划线开头的属性,是对象的隐藏属性,隐藏属性只能在类的内部访问,无法通过对象访问
其实隐藏属性只不过是Python自动为属性改了一个名字: _类名__属性名
如下访问隐藏属性:
class Car():
def __init__(self,name,color):
self.__name=name
self.color=color
def run(self):
print(self.__name,'汽车开动了')
car1=Car('法拉利','红色')
car1.run()
print(car1._Car__name)#完全封装时调用属性的方法(实例对象._类名__属性名)
结果:
2、getter和setter方法
getter方法用来查看私有属性,实际上就是在类的内部定义一个函数来访问私有属性。
setter方法用来修改私有属性。
如果只有一个getter方法而没有setter方法,那这个属性是一个只读属性。
class Car():
def __init__(self,name,color):
self.__name=name
self.__color=color
def run(self):
print(self.__name,'汽车开动了')
def get_name(self):
return self.__name
def set_name(self,name):
self.__name=name
car1=Car('法拉利','红色')
car1.run()
print(car1.get_name())
print(car1.set_name('宝马'))
print(car1.get_name())
结果:
二、property装饰器
我们可以使用@property装饰器来创建只读属性,@property装饰器会将方法转换为相同名称的只读属性,可以与所定义的属性配合使用,这样可以防止属性被修改。
class Person():
def __init__(self,name):
self._name=name
def name(self):
print('name方法执行了')
return self._name
p1=Person('邱淑贞')
print(p1.name())
结果:
用@property装饰器的代码为:
class Person():
def __init__(self,name):
self._name=name
@property
def name(self):
print('name方法执行了')
return self._name
p1=Person('邱淑贞')
print(p1.name)
和前一段代码的不同之处是: @property 以及最后一行。
结果:
效果和前一段代码的效果一样。@property装饰器将后面的name方法转换成了name属性。
而当我们要修改这个name属性时:
报错:AttributeError: can’t set attribute(无法设置属性)
又当我们调用@property装饰器后面的name方法时:
报错:TypeError: ‘str’ object is not callable('str’对象是不可调用的)
也就是说@property装饰器保护了name方法(属性)不被(调用)修改。
那我们要如何yoga装饰器来修改name属性呢?如下:
class Person():
def __init__(self,name):
self._name=name
@property
def name(self):
print('get方法执行了')
return self._name
@name.setter
def name(self,name):
print('set方法执行了')
self._name=name
p1=Person('邱淑贞')
print(p1.name)
p1.name='刘亦菲'
print(p1.name)
结果: