使用下划线
-
一个单下划线 (_)开头的变量或函数是一个私有变量或函数,表示该变量或函数应该在类的内部访问,而不应在类的外部直接访问。这不是强制的,可以在外部访问单下划线开头的变量和函数,但是规范上这样不推荐。
-
两个下划线(__)开头的变量或函数称为名称改编(Name Mangling),在类的内部会被重命名为
_ClassName__variable 或 _ClassName__function 。这样在外部不能直接访问,只能通过类的内部方法访问。这是为了防止子类中的命名冲突,保证类的私有属性的安全性。 -
一个双下划线开头和结尾的变量或函数(var)称为“魔法”属性或方法,这是 Python 自己用于特殊用途的属性或方法,比如 init
方法就是 Python 用来实现构造函数的方法。这只是一种约定,而不是一个真正的安全机制,在 Python 中如果你真的想要私有化你的变量和方法,你可以采用其他的方式。
如果真正想要私有化变量和方法,可以采用以下几种方式:
-
使用 Python 的 property 装饰器可以实现 getter 和 setter 方法,控制对变量的访问权限。
class MyClass: def __init__(self): self._x = None @property def x(self): return self._x @x.setter def x(self, value): if value < 0: raise ValueError("Negative value not allowed") self._x = value my_class = MyClass() my_class.x = 22 print(my_class.x)
在这个例子中,_x 变量是私有变量,不能直接访问,而 x 这个 property 可以被访问和设置。
-
使用模块级变量。
# mymodule.py _x = None def set_x(value): global _x _x = value def get_x(): return _x set_x(2) print(get_x())
在这个例子中,_x 是一个模块级变量,只能在 mymodule 模块中访问,通过 set_x 和 get_x 访问。
-
使用包装类。
class Wrapper: def __init__(self, obj): self._obj = obj def get_x(self): return self._obj.x def set_x(self, value): self._obj.x = value class MyClass: def __init__(self): self._x = None my_obj = MyClass() wrapper = Wrapper(my_obj) # 不能直接访问 MyClass 的私有变量_x print(my_obj._x) # AttributeError # 通过wrapper类访问 print(wrapper.get_x()) wrapper.set_x(3) print(wrapper.get_x())
这个例子中,Wrapper类包装了MyClass类的实例,并且提供了 get_x 和 set_x 方法来访问_x这个变量,隐藏了实际的实现细节。
总结来说, 选择哪种方式取决于你的需求和约束。比如如果你的项目需要使用属性来实现类似于Java中的getter和setter,那么使用property装饰器是一个很好的选择。如果你的项目需要隐藏模块的实现细节,那么使用模块级变量是一个好的选择。如果你的项目需要隐藏类的实现细节,那么使用包装类可能是一个很好的选择。