这是我参与更文挑战的第 23 天,活动详情查看: 更文挑战
1. 概述
Python 对于类的成员没有严格的访问控制限制,默认可以公开访问。
那我们有些核心代码是属于机密的,不能提供给客户,但是也要帮客户要用,怎么办呢?
这个时候,我们想到了面向对象特征之一的封装。
什么是封装?
封装指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部的操作和访问。
封装本质是一个种黑盒方式对于外界。只用对外界提供可以使用的接口,而不用关心其内部实现。
所以,封装有什么好处?
- 隐藏类的实现细节
- 让使用者只能通过事先预定的方法来访问数据,从而可以在该方法里加入控制逻辑,限制属性的不合理访问
- 可以进行数据检查,从而有利于保证对象信息的完整性
- 便于修改,提高代码的可维护性
怎么是实现封装呢?
Python引入了私有属性和方法,将该隐藏的隐藏起来,不被外界访问。
好啦,xdm我们接下来学习私有属性和私有方法啦,小步快跑进场✌️
2. 私有属性(方法)介绍
私有属性和私有方法:
- 通常我们约定,两个下划线开头的属性是私有的(private)。其他为公共的(public).
- 类内部可以访问私有属性和方法
- 类外部不能直接访问私有属性(方法)
- 类外部可以通过__类名__私有属性(方法)名访问私有属性(方法)
注意:
方法本质上也是属性,只不过是可以通过()执行而已
3. 私有属性(方法)底层机制
python默认的成员函数和成员变量都是公开的,没有提供public、private等关键词来修饰
在python中我们定义私有变量或者方法是,需要在名字前加上__两个下划线。
在Python内部使用了一种 name mangling 技术,将 __membername替换成 _classname__membername,所以你在外部使用原来的私有成员的名字时,会提示找不到
我们来举个栗子:
class Animal:
def __init__(self):
self.__name = 'Tom' # 私有属性
self.age = 3
def __get_name(self): ##私有方法
print("名字是{0}".format(self.__name))
def get_age(self): #普通方法,可以调用私有属性和方法
print("{0} 的年龄是{1}".format(self.__name,self.age))
cat = Animal()
cat.get_age()
cat.__get_name() #实例直接访问私有方法会抛出异常
cat._Animal__get_name() # 实例直接调用Python内部改名之后的私有方法,就能正常访问
- 在堆内存中会创建Animal类.构造函数实例属性有公有属性age和私有属性__name;实例方法中__get_name私有方法和get_age公有方法
- 通过Animal()创建cat实例,并且初始化实例属性,由于__name是私有属性,因此python内部会对该属性进行替换成_Animal__name.
- 同类私有方法也会被python内部更改名字。私有方法__get_name就会被更改成_Animal__get_name()。公有方法则不会被更改名字
- 如我们执行上面代码结果。实例对象调用普通方法能正常执行,调用私有方法或者属性,Python内部则会抛出异常提示找不到
- 如果我们要让外界访问私有方法或者属性,我们可以通过python改名之后进行访问_classname__私有方法(私有属性)。
详细说明
__name是私有属性,__get_name()是私有方法。
如果直接访问的话,会提示找不到相关的属性或者方法,但是如果你真要访问私 有的相关数据的话, 也是可以访问的,严格地说,私有方法在它们的类外是可以访问的,只是不容易处理。
在 Python 中没有什么是真正私有的;在内部,私有方法和属性的名字被忽然改变和恢复,以致于使得它们看上去用它们给定的名字是无法使用的
总结
Python并没有提供类似其他语言如C++等private修饰符,因此 Python并不能真正支撑隐藏。为了更好隐藏类成员,私有属性和私有方法。
私有属性和私有方法,可以更好提高代码的可维护性,便于修改,而不会影响公有的方法,我们在日常工作中,要多实践~
好啦,以上是本期内容,欢迎大佬在评论区指正,下次见