在Python开发中,我在视频里面看到很多方法或者属性通过前面加上双下划线来声明私有,但是我最近也看到网上使用但下划线,我自己也用过也是可以声明私有,所以我想问这两个的区别是什么,网上说的感觉有点模糊
声明私有属性或者方法,到底是加双下划线好还是单个下划线好,具体区别又在哪里
双下划线才是真正的private,单下划线是protected,这两个不一样
顺带一提我不太认同楼上的回答,私有就是私有,保护就是保护。具体情景可以考虑用私有还是保护但是该用私有的时候就是双下划线
代码里面有详细注释,有用记得采纳。
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内部改名之后的私有方法,就能正常访问
用单下划线好
Python没有类似于Java的private关键字, 但也可以为类定义私有属性. 只需将属性命名变为以__开头, 例如 __field.
示例代码:
class Vector2D(object):
def __init__(self, x, y):
self.__x = float(x)
self.__y = float(y)
self.xx = x
self.yy = y
def get_x(self):
return self.__x # 内部访问
if __name__ == "__main__":
v = Vector2D(3, 4)
print v.__dict__
print v._Vector2D__x, v.get_x()# 但是可以通过v._Vector2D__x 在外部访问
v.__x # 外部访问
输出:
{'yy': 4, 'xx': 3, '_Vector2D__x': 3.0, '_Vector2D__y': 4.0}
3.0 3.0
Traceback (most recent call last):
...
v.__x
AttributeError: 'Vector2D' object has no attribute '__x'
从上面的例子可以看出:
__field被编译器重命名为_className__field
在class外部不能访问obj.__field, 但在class内部可以
但是, 这只能防止无意间的调用, 不能防止恶意调用, 用Fluent Python的话来讲, 这是一种safety device, not security device, 用国语来讲, 就是防君子不防xr, 因为可以通过obj._className__field在外部访问obj的私有__field.
如果一个属性是以两个下划线开始 就标识这个这个属性是一个私有属性
self.__money = 1000000
https://blog.csdn.net/u014612521/article/details/122298168
在一个类中定义的属性(不管是类属性仍是实例属性),若是是以 双下划线 (__) 开头,那么这个属性是对外 (包括其子类中) 不可见的,相似于 java 中的 private 属性。如何作到这一点呢, 毕竟 Python 并无真正意义上的访问约束机制(好比 private, protected 修饰符)。Python 的作法是 name mangling, 姑且翻译成名称扭曲吧。具体作法是 若是你在某个类 clsA 中定义了一个属性,名称是 __a, 那么 python 会把这个属性改名成 _clsA__a, 可是改名后不影响你在内部使用,你在类的内部,仍是能够使用 self.__a 来范围。若是你非要在外部访问 这个属性,就只能使用 inst._clsA__a 来访问。 (详细的解释能够参考 pep-8: https://www.python.org/dev/peps/pep-0008/#naming-conventions)python
>>> class A():
... __clsattr = 'classattr'
... def __init__(self):
... self.__instattr = 5
... self.__instattr2_ = 'ending underscore'
...
... def get_instattr(self):
... print(self.__instattr)
...
... @classmethod
... def get_clsattr(cls):
... print(cls.__clsattr)
...
>>> A.get_clsattr()
classattr
>>> A.__clsattr
Traceback (most recent call last):
File "", line 1, in
AttributeError: type object 'A' has no attribute '__clsattr'
>>> A._A__clsattr
'classattr'
>>> obj = A()
>>> obj.get_instattr()
5
>>> obj.__instattr
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'A' object has no attribute '__instattr'
>>> obj._A__instattr
5
>>> obj._A__instattr2_
'ending underscore'