沙师弟学Python之 _, __ 和 __xx__的区别

4,575 阅读2分钟

这几天本菜鸟在学习数据结构与算法,学习数据结构与算法免不了要手动实现这些数据结构与算法。在用类定义这些对象的时候,发现老是出现带有 _ ,__ 和__xx__ 的函数,一开始也没怎么在意,想着这些也学过,但是今天仔细思考一下这些用法与区别,才发现已经忘的七七八八了,就这样好奇心逼着我去找出他们的区别。阅读了几篇博客之后,本菜鸟知道了这三兄弟的区别。

1. "_" 单下划线

Python中是不存在真正的私有方法的,但是为了实现类似于c++中的私有方法,于是就在类的方法或者属性前加一个“_”,意味着该方法或者属性就不应该被调用了。

class A(object):
    def _test(self):
        print("这个函数不应该通过_tset调用,而应该通过test调用")

    def test(self):
        return self._test()


a = A()
a._test()
a.test()

结果

这个函数不应该通过_tset调用,而应该通过test调用
这个函数不应该通过_tset调用,而应该通过test调用

由此可得,这个方法是能被调用的,但出于某种约定,我们是一般不去调用的。

2. “__” 双下划线

双下划线表示的是私有类型的变量,既然是私有了,那肯定就不允许子类访问了,只允许这个类(self)自身访问。

class A(object):
    def __test(self):
        print("I am test in A")

    def test(self):
        return self.__test()


a = A()
a.test()

结果:

I am test in A

返回的结果是我们预料之中的。


接着,我们给A添加一个子类,并重新定义它的__test()方法。

class B(A):
    def __test(self):
        print("I am test in B")


b = B()
b.test()

现在,结果是这样的:

I am test in A

可见,子类B重新定义之后的__test()返回的依然是A类中的__method(),由此我们可以知道以“__"开头的方法是不能被重写的,只允许在内部使用

"__ xx __" 前后双下划线

这种方法被称为magic methods(魔术方法),一般是系统定义名字,类似于__init__(),一般是给Python调用的。

class WrongMethod(object):
    def __init__(self, n):
        self.n = n

    def __add__(self, other):
        return self.n - other

    def __sub__(self, other):
        return self.n + other

    def __str__(self):
        return str(self.n)


num = WrongMethod(20)
print("num = ", num)
print("num + 10 = ", num + 10)
print("num - 10 = ", num - 10)

结果

num =  20
num + 10 =  10
num - 10 =  30

上面的例子就能比较好的提现出来,"__ xx __" 这种方法一般是Python调用的。

结论

  1. ”_“ 是私有的,一般不应该被调用
  2. ”__“ 是为了避免子类重写某个函数而使用的
  3. ”__ xx __“ 一般是用于Python调用