今天遇到一个很有意思的情况
大家应该都知道,在Python中,私有成员变量和私有成员方法通过 在方法名或者属性名前加上 __ 两根下划线即可实现,并且在类外部无法访问
举个栗子
class Phone:
IMEI = None
producer = None
__current_voltage = None # 当前电压
def call_by_5g(self):
print("5G通话已开启")
def __keep_single_core(self):
print("让CPU以单核模式运行以节省电量")
这里我定义了一个“电话”类,它有两个非私有成员变量IMEI 和 producer ,一个私有成员变量 __current_voltage ,一个非私有成员方法call_by_5g(),一个私有成员方法__keep_single_core()。
现在我直接在类外部,通过一个实例对象尝试去获取私有成员变量以及使用私有成员方法
OK, 和它的名字一样,我们不能直接用,对于私有成员方法没啥好说的,但是下面这种情况,你有碰见过没
phone = Phone()
phone.__current_voltage = 30
print(phone.__current_voltage)
这里我强行给私有成员变量赋上了一个值30,然后我又强行输出,解释运行,结果如下
OK,神奇的事情出现了,没报错,而且30 居然输出了
Why?
这里存在了一个“伪私有属性的概念”
Python类中的私有成员(私有函数,私有变量)
在内部,python使用一种 name mangling 技术,将 __membername替换成 _classname__membername,所以你在外部使用原来的私有成员的名字时,会提示找不到。
我们来试试直接输出这样一个东西
print(phone._Phone__current_voltage)
和解释的一样,这个东西确实存在,
所以这和我们讨论的问题有什么关系呢?
现在我们试着写一个测试:
class Person(object):
__count_of_class = "原始的count_of_class"
def __init__(self, name):
self.name = name
print("在类里面, count_of_class = ", Person.__count_of_class) # 类里面可以正常访问私有属性
p1 = Person("DingJiaxiong")
p1.__count_of_class = "我不是原始count_of_class"
print("对于p1来说, _Person__count_of_class = ", p1._Person__count_of_class)
print("对于p1来说, __count_of_class = ", p1.__count_of_class)
# 直接通过Person类去修改私有变量的属性值
Person.__count_of_class = "我不是原始的count_of_class"
# Person._Person__count_of_class = '我不是原始的_Person__count_of_class'
print("对于Person类来说, _Person__count_of_class = ", Person._Person__count_of_class)
print("对于Person类来说, __count_of_class = ", Person.__count_of_class)
这段代码的运行结果
从结果中可以看出,虽然我们用p1.__count_of_class 给私有成员变量赋值了,但是在类中真正的属性 _Person__count_of_class 这个原始值是没有变的。
但是如果将Person._Person__count_of_class赋值,那么类属性定义的原始值就真正地被覆盖了
所以,__count_of_class和_Person__count_of_class不是同一个东西。
回到我们的问题
如果不先给p1.__count_of_class赋值,直接打印它又会触发AttributeError,这是为什么?
这是因为给p1.__count_of_class赋值的操作,其实是在p1中定义了一个名为__count_of_class的变量(Python中的都是动态变量)。
动态的意思是什么呢?【就算我定义类的时候没有定义,但我仍然可以在外部,通过赋值的形式,来为类创造属性】
举个栗子
class Person:
pass
p1 = Person()
p1.haha = "我是p1对象搞出来的一个新属性"
print(p1.haha)
Person.heihei = "我是Person类搞出来的一个新属性"
print(p1.heihei)
运行结果
OK, 了然了。
现在我甚至有一种方法可以直接在类外通过对象直接调用私有成员方法,如下:
谈谈Python:为什么类中的私有属性可以在外部赋值并访问