抛开语言层面,在通常的面向对象编程中(典型的C++),类都有私有属性。这是为了封装自己的属性,并且保证不会被外界调用修改而只能自己的方法调用修改。由于动态语言的特性,python中不存在严格封装特性,可以在外界随意调用类中任何属性和方法。一般我们想在类中申明一些不想被外界调用的私有属性时,通常约定俗成地会在属性名字的前面加上单下划线,如class._status.如果在使用别人写好的代码中看到了加了下划线的属性时,其实应该清楚最好不要调用甚至是修改它。
在其它代码中有时还会看到属性名字的前面加上了双下划线,如果还想通过双下划线调用属性时就会报错,说没有这个属性。注意,这和单下划线不同。在类的作用域中,当解释器遇到以双下划线开头的属性时,会在双下划线前面加上类的名字。这样做的目的就很明确了,就是强制要求这个属性被外界调用,而且连继承它的类的实例也不能使用。说白了,连继承都不行。
class C1(): def meth1(self): self.__x = ‘Hello World‘ def meth2(self): print(self.__x) class C2(): def meth3(self): self.__o__x = ‘Hello Python‘ def meth4(self): print(self.__o__x) class C3(C1, C2): pass c3 = C3() c3.meth1() c3.meth3() c3.meth2() c3.meth4()
输出为:
Hello World Hello Python
再调用c3的__x:
c3.__x # 如下所示,这个对象中没有__x这个属性
输出为:
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-7-777a67f96b15> in <module>() ----> 1 c3.__x # 如下所示,这个对象中没有__x这个属性 AttributeError: ‘C3‘ object has no attribute ‘__x‘
再执行:
print(dir(c3)) # 在下面中,注意看__x属性
输出为:
[‘_C1__x‘, ‘_C2__o__x‘, ‘__class__‘, ‘__delattr__‘, ‘__dict__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__init_subclass__‘, ‘__le__‘, ‘__lt__‘, ‘__module__‘, ‘__ne__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, 、 ‘__weakref__‘, ‘meth1‘, ‘meth2‘, ‘meth3‘, ‘meth4‘]
总结
在类中,加单下划线的属性可以被外界调用,但不推荐;加双下划线的属性更不能被外界调用,甚至继承它的类都不行。如果实在想调用,可以在双下划线前面加上_类的名字。这样就更不推荐,自己心里明白就行。
时间: 2024-10-15 21:41:02