前面我们进一步介绍了类定义中属性的使用,今天我们对中关于属性私有化的话题稍微展开聊一下,顺便稍微理解一下Python设计的相关理念。
访问级别在其他编程语言中,比如Java,关于类中的属性和方法通过关键字定义明确的访问级别,比如private表示私有级别,protected表示保护级别,public表示公共级别。访问级别控制了属性和方法在不同场景下能否被访问到。当然,这些访问级别并不是无懈可击的,我们通过反射机制还是可以突破访问级别的限制。
Python中的访问级别相对来说比较简单,只有公共级别和私有级别。要区分一个属性和方法的访问级别,是通过属性或方法的名称来判断,当名称是以__打头时,在Python中就被当做是私有的属性或方法了。
从其他语言相对看似严谨的数据访问级别的使用习惯转到Python,刚开始可能会觉得Python中的这种规则有些别扭,多用几次,也就慢慢习惯了。
Python私有属性的访问当我们在Python中通过__打头定义一个属性或方法时,这个属性或方法就被定义为了私有,那么我们就不能通过对象名或者类名直接访问到这个私有的属性或方法了。
要实现私有属性或方法的访问,似乎就只能通过定义公有的方法间接进行访问了。以实际代码来举例说明一下私有属性的定义与访问:
执行结果:
可以看到,无法通过对象名.属性名的方式直接访问私有属性了,可以通过定义一个公有的方法间接来访问私有属性。
Python私有属性的实现机制在Python中,我们可以通过对象的__dict__属性,来查看一个对象中存在的属性。
回到前面的定义了私有属性的DaGongRen的代码,我们来查看一下__dict__属性:
执行结果:
可以看到,我们定义的两个公有属性name和age,同时多了一个莫名其妙的属性,_DaGongRen__salary,而这个属性的值刚好是私有属性__salary的值100。
其实在Python中是通过一种称之为“名称混淆(Name Mangling)”的机制来实现相关私有属性或方法的隐藏的。具体规则是在私有属性的名称前拼接上_类名作为最终的私有属性的名字。所以,我们直接对象名.属性名时,提示找不到这个属性,因为这个名字的属性确实不存在。
那么,如果我们是用名称混淆之后的私有属性名是否能直接访问到私有属性呢?通过代码来尝试一下:
执行结果:
自由与责任的理念为什么只是进行名称混淆,而没有增加更加严格的私有数据的保护机制呢。
其实,类比于Java等语言的数据访问级别的控制,仍然可以通过反射来突破。Python中,更习惯于把开发者当做成年人来对待。一个属性应不应该随意更改,成年人自己说得算。
很像是奈飞的企业文化中所倡导的“自由与责任”:承担相应的责任,同时获得对应的自由。
现实中,很多规章制度似乎也是防君子不防小人。那么,实际开发场景中,所谓的私有属性,真的很有必要吗?