标签:val 意义 访问 function mon 变形 机制 cti 打印
封装是面向对象三大特性最核心的一个特性
封装指的就是把数据与功能都整合到一起,针对封装到对象或者类中的属性,可以严格控制对它们的访问,分两步实现:隐藏与开放接口
如何隐藏:
? 在属性名前加__前缀,就会实现一个对外隐藏属性效果.Python 的 class 机制采用了双下划线开头的方式将属性隐藏起来(设置成私有的),这其实仅仅只是一种变形的操作 ,类中所有双下划线的属性都会在类定义阶段检测语法时自动变成" __ 类名 __ 属性名"的形式:
该隐藏需要注意的问题:
? 1)在类外部无法直接访问双下划线开头的属性,但是知道了类名和属性名就可以拼出名字:类名 __ 属性,然后就可以访问了,如 _ Foo . __ A。所以说这种操作并没有严格意义上地限制外部访问,仅仅只是一种语法意义上的变形。
class Foo:
__x = 1 # _Foo__x
def __f1(self): #Foo_f1
print(‘from test‘)
print(Foo.__dict__)
#{‘__module__‘: ‘__main__‘, ‘_Foo__x‘: 1, ‘_Foo__f1‘: <function Foo.__f1 at 0x10ab1c400>, ‘__dict__‘: <attribute ‘__dict__‘ of ‘Foo‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Foo‘ objects>, ‘__doc__‘: None}
#print(Foo.__x) #报错,访问不到
print(Foo_Foo.__x) #1
print(Foo._Foo__f1) #<function Foo.__f1 at 0x10ab1c400>
? 2)这种隐藏是对外不对内,因为__ 开头的属性会在检查类体代码语法时统一发生变形
class Foo:
__x = 1 # _Foo__x = 1
def __f1(self): # _Foo__f1
print(‘from test‘)
def f2(self):
print(self.__x) # print(self._Foo__x)
print(self.__f1) # print(self._Foo__f1)
# print(Foo.__x) #type object ‘Foo‘ has no attribute ‘__x‘
print(Foo.__f1) #‘Foo‘ has no attribute ‘__f1‘
obj=Foo()
obj.f2() #<function Foo.__f1 at 0x107057400>
3) 这种变形操作只在检查类体语法的时候发生一次,之后定义的__开头的属性都不会变形
class Foo:
__x = 1 # _Foo__x = 1
def __f1(self): # _Foo__f1
print(‘from test‘)
def f2(self):
print(self.__x) # print(self._Foo__x)
print(self.__f1) # print(self._Foo__f1)
Foo.__y=3
print(Foo.__dict__)
#{‘__module__‘: ‘__main__‘, ‘_Foo__x‘: 1, ‘_Foo__
# f1‘: <function Foo.__f1 at 0x10793b400>,
# ‘f2‘: <function Foo.f2 at 0x10793b1e0>,
# ‘__dict__‘: <attribute ‘__dict__‘ of ‘Foo‘ objects>,
# ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Foo‘ objects>, ‘__doc__‘: None, ‘__y‘: 3}
print(Foo.__y) #3
class Foo:
__x = 1 # _Foo__x = 1
def __init__(self,name,age):
self.__name=name
self.__age=age
obj=Foo(‘egon‘,18)
print(obj.__dict__) #{‘_Foo__name‘: ‘egon‘, ‘_Foo__age‘: 18}
print(obj.name, obj.age) #‘Foo‘ object has no attribute ‘name‘
为何要隐藏属性
? 1)隐藏数据属性"将数据隐藏起来限制了类外部对数据的直接操作。
类内应该提供相应的接口来允许类外部间接地操作数据,接口之上可以附加额外的逻辑来对数据的操作进行严格地控制"
class People:
def __init__(self, name):
sel.__name = name
def get_name(self):
#通过该接口就可以间接地访问到名字属性
print(‘看什么看‘)
print(self.__name)
def set_name(self, val):
if type(val) is not str:
print(‘渣渣, 必须传入字符串类型‘)
return
self.__name = val
obj = People(‘egon‘)
#print(obj.name) #无法直接用名字属性
obj.set_name(‘EGON‘)
obj.set_name(123123)
obj.get_name()
定义属性就是为了使用,所以隐藏并不是目的
2)隐藏函数/方法属性:目的是为了隔离复杂度
例如 ATM 程序的取款功能,该功能有很多其他功能组成,不如插卡,身份认证,输入金额,打印小票,取钱等,而对使用者来说,只需要开发取款这个功能接口即可,其余功能我们可以隐藏起来。
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): #取款功能
self.__card()
self.__auth()
self.__input()
self.__print_bill()
self.__take_money()
obj = ATM()
obj.withdraw()
隐藏属性与开放接口,本质就是为了明确地区内外,类内部可以修改封装内的东西而不影响外部调用者的代码;而类外部只需要拿到一个接口,只要接口名,参数不变,则无论设计值怎么改变内部实现代码,使用者均无需改变代码。
标签:val 意义 访问 function mon 变形 机制 cti 打印
原文地址:https://www.cnblogs.com/xy-han/p/12663148.html