封装
广义上:面向对象的封装:代码的保护,面向对象的思想本身就是一种封装,只让自己的对象能调用自己类中的方法
狭义上:面向对象的三大特性之一 属性和方法都藏起来 不让你看见
正常的在外部调用属性:
class Person: def __init__(self,name,password): self.name = name self.password = password alex = Person('alex','alex3714') print(alex.password) # 可以正常调用
运行结果:
alex3714
(1)私有属性
将类里面的属性转换成私有属性:前面加双下划线
class Person: def __init__(self,name,password): self.name = name self.__password = password # 加上双下划线变成私有属性 alex = Person('alex','alex3714') print(alex.password) # 由于password变成了私有属性,此时不能在外部正常调用了
运行结果,报错,找不到对应的属性:
Traceback (most recent call last): File "<encoding error>", line 6, in <module> AttributeError: 'Person' object has no attribute 'password'
应用alex._dict_找出alex里面存储的属性:
class Person: def __init__(self,name,password): self.name = name self.__password = password # 加上双下划线变成私有属性 alex = Person('alex','alex3714') print(alex.__dict__)
运行结果可以找到对应的属性方法:
{'_Person__password': 'alex3714', 'name': 'alex'}
从结果可以看出,类里面的属性password不再是它自身,而是变成了_Person__password,所以当以alex.password去调用的时候是调不到的,这也体现了私有属性方法不能直接在外部调用的特性
class Person: def __init__(self,name,password): self.name = name self.__password = password # 加上双下划线变成私有属性 alex = Person('alex','alex3714') print(alex.__dict__) print(alex._Person__password) # 在外部可以这样调用私有属性:_类名__属性名
运行结果:
{'_Person__password': 'alex3714', 'name': 'alex'} alex3714
虽然我们可以通过alex._Person__password调用,但是这样的调用方法是在你知道私有方法这样存储的情况下的,一般也不会这样去调用,在外部调用私有属性的机制,我们只要求了解,但是不要使用,因为对于私有属性,只能在类的内部使用
class Person: def __init__(self,name,password): self.name = name self.__password = password # 加上双下划线变成私有属性 def get_password(self): print(self.__dict__) return self.__password # 只要在类的内部使用私有属性,就会自动的带上_类名 alex = Person('alex','alex3714') print(alex.__dict__) print(alex._Person__password) # _类名__属性名可以调用私有属性 alex.__hight = 1.78 # 在外部加上属性类似私有但是并不是私有的 print(alex.get_password()) # 在外部调用私有属性的机制,只能了解,一般不会去使用 print(alex.__hight) # 外部可以正常调用
运行结果:
{'_Person__password': 'alex3714', 'name': 'alex'} alex3714 {'_Person__password': 'alex3714', '__hight': 1.78, 'name': 'alex'} alex3714 1.78
(2)私有方法
类似私有属性,在方法前面加上双下划线—私有方法,变成私有方法后就不能在外部正常调用了
class Person: def __init__(self,name,password): self.name = name self.__password = password # 加上双下划线变成私有属性 def __get_password(self): # 私有方法,方法前面加上双下划线 print(self.__dict__) return self.__password # 只要在类的内部使用私有属性,就会自动的带上_类名 alex = Person('alex','alex3714') print(alex.get_password()) # 这样在外部调用就调不到了
运行结果:
Traceback (most recent call last): File "<encoding error>", line 9, in <module> AttributeError: 'Person' object has no attribute 'get_password'
可以在外部调用私有方法的机制:
class Person: def __init__(self,name,password): self.name = name self.__password = password # 加上双下划线变成私有属性 def __get_password(self): # 私有方法,方法前面加上双下划线 print(self.__dict__) # 从这里就可以看出存储出现变形机制 def login(self): # 公有方法,正常的方法去调用私有方法 self.__get_password() alex = Person('alex','alex3714') print(alex.login()) # 调用类里面的方法
运行结果:
{'name': 'alex', '_Person__password': 'alex3714'} None
(3)静态私有属性:外部不会看到这个静态属性,起到加密的效果
class Person: __key = 123 # 静态私有属性,外部不知道这个密码,起到加密的效果 def __init__(self,name,password): self.name = name self.__password = password # 加上双下划线变成私有属性 def __get_password(self): # 私有方法,方法前面加上双下划线 print(self.__dict__) # 从这里就可以看出存储出现变形机制 def login(self): # 公有方法,正常的方法去调用私有方法 self.__get_password() alex = Person('alex','alex3714') print(alex.login()) # 调用类里面的方法
(4)小结
所有的私有 都是在变量的左边加上双下划线
对象的私有属性
类中的私有方法
类中的静态私有属性
所有的私有的 都不能在类的外部使用