1.封装
面向对象编程有三大特征:封装,继承,多态。
封装:将数据与功能打包写进一个对象中。
针对封装到对象或者类中属性,可以控件对它们的访问,分两步实现,隐藏与开放接口。
2.隐藏属性
Python的Class机制采用双下划线的方法将属性进行变形操作,从而隐藏起来,类中的所有双下划线开头的属性都会在定义阶段检测语法时自动变成 _类名__属性名称 的形式。
class Foo:
__name = 'kid' # 变形 _Foo__name
def __init__(self):
self.__age = 18 # 变形 _Foo__age
def __func(self): # 变形 _Foo__func
print('from __func run')
print(Foo.__name) # AttributeError: 类中没有这个属性
obj= Foo()
print(obj.__name) # AttributeError
原本的名称被进行了变形的处理 __属性名称 变为 _类名__属性名称。
以变形后名名称就可以正常访问了。这种操作没有严格意义上的限制访问,仅只是一种语法意义上的变形。
print(Foo._Foo__name)
obj= Foo()
print(obj._Foo__name)
obj._Foo__func()
print(Foo.__dict__)
{··· '_Foo__name': 'kid', '_Foo__func': <function Foo.__func at 0x00000000012C7430>,···}
在类内部是可以直接访问双下划线开头的属性,因为在类定义阶段内部双下划线开头的属性统一发生了变形。
class Foo:
def __func(self): # 变形 _Foo__func
print('from __func run')
def info(self):
self.__func() # 我也变形了嘿嘿
obj= Foo()
obj.info() # from __func run
通过info()来访问 __func。
变形操作只在定义阶段发生一次,在类定义之后的赋值操作,不会变形。
class Foo:
__x = 1
Foo.school = '桂电'
print(Foo.__dict__)
{···'_Foo__x': 1, 'school': '桂电'···}
3.开发接口
将属性隐藏就是限制类外部内类直接操作,然后再类的内部提供相对应的接口提供外部的间接访问、操作,在接口至上可以附加额外的逻辑来对数据的操作进行严格的控制。
3.1数据接口
class Student:
def __init__(self, name, age):
set_info(self, name, age)
def set_info(self, name, age):
if type(name) != str:
return print('名字必须是字符串!')
if type(age) != int:
return print('名字必须是数字!')
self.__name = name
self.__age = age
stu1 = Student('kid', 18)
stu1.set_info(1, 19) # 名字必须是字符串!
stu1.set_info('kid', '18') # 名字必须是数字!
stu1实例化后,stu1调用函数et_info()修改定制了限制。
class Student:
def set_info(self, name, age):
if type(name) != str:
return print('名字必须是字符串!')
if type(age) != int:
return print('名字必须是数字!')
self.__name = name
self.__age = age
def __init__(self, name, age):
self.set_info(name, age)
stu1 = Student('kid', 18)
3.2函数接口
将功能都隐藏,只开放接口,通过接口调用功能。
class ATM:
def __card(self): # 插入银行卡
print('插入银行卡')
def __auth(self): # 验证密码
print('用户认证成功')
def __input(self): # 输入金额
print('取款金额')
def __print_bill(self): # 打印小票
print('打印票据')
def __take_money(self): # 取钱
print('取款')
def withdraw(self): # ATM功能
self.__card()
self.__auth()
self.__input()
self.__print_bill()
self.__take_money()
obj=ATM()
obj.withdraw() # 调用接口操作每个功能
4.property
property装饰器,将类中函数属性伪装成数据属性,对象在访问特殊属性时就会触发功能的执行,然后将返回值作为本次访问就结果。
class Salary:
def __init__(self, money):
self.money = money
def annual(self):
return print(self.money * 12)
job = Salary(6000)
job.annual()
class Salary:
def __init__(self, money):
self.money = money
@property # 兄弟带上你的帽子
def annual(self):
return print(self.money * 12)
job = Salary(6000)
job.annual # 假装自己是一个属性
property装饰器还有两个配套功能。@伪装的函数名称.setter,设置属性,@伪装的函数名称.deleter,删除属性,注意名称一定需要一样。
class Student:
def __init__(self, name):
self.__name = name
@property
def name(self):
return self.__name
@name.setter
def name(self, name):
if type(name) != str:
return print('名字必须是字符串!')
self.__name = name
@name.deleter
def name(self):
return print('无法删除')
obj = Student('kid')
print(obj.name)
obj.name = 12 # 名字必须是字符串!
del obj.name
kid
名字必须是字符串!
无法删除