封装之如何隐藏属性
在变量名和方法名之前加双下划线__,外部就访问不到;
class A:
__x = 1
def __init__(self, name):
self.__name = name
def __bar(self):
print(self.__name)
A.__x # 外部无法访问
这其实是在类定义的时候,将变量名和函数名进行了变形,我们可以打印类和对象的名称空间看一下变成了什么。
class A:
__x = 1
def __init__(self, name):
self.__name = name
def __bar(self):
print(self.__name)
print(A.__dict__)
obj = A('shi')
print(obj.__dict__)
输出结果:
{'__module__': '__main__', '_A__x': 1, '__init__': <function A.__init__ at 0x1039ea378>, '_A__bar': <function A.__bar at 0x1039ea158>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
{'_A__name': 'shi'}
我们可以看到,在定义类的时候,类已将将双下划线开头的变量和方法自动做了变形,由__x变成_A__x。
这种变形的特点:
1.在类外部无法直接访问变量和方法;
2.在类内部可以直接调用;
3.子类无法覆盖父类__开头的变量和方法
封装数据属性的目的
明确的区分内外,控制外部对隐藏属性的操作。
class People:
def __init__(self, name, age):
self.__name = name
self.__age = age
def tell_info(self):
print('<%s><%s>' % (self.__name, self.__age))
def set_info(self, name, age):
if not isinstance(name, str):
print('name必须是字符串')
return
if not isinstance(age, int):
print('age必须是数字')
return
self.__name = name
self.__age = age
p1 = People('shi', 18)
p1.tell_info()
p1.set_info('qian', 12)
p1.tell_info()
上面代码中我们就可以对外部去修改变量做一系列的控制。
封装方法的目的
隔离复杂度
class Atm():
def __card(self):
print('插卡')
def __auth(self):
print('认证')
def __input(self):
print('输入金额')
def __take_money(self):
print('取款')
def withdrow(self):
self.__card()
self.__auth()
self.__input()
self.__take_money()
a = Atm()
a.withdrow()
实现一个功能,我们只需要提供一个接口,而不需要关心内部是怎么实现的。
封装与可扩展性
调用者无需修改调用方法,而程序编写者可以任意修改方法的逻辑