Python技术迷

Python 隐藏法宝:双下划线 _ _Dunder_ _

昨天晚上在家里写代码写得脑壳发麻,结果小侄子跑过来问我:“叔叔,为什么你老敲那两个下划线啊,看着像打错了一样。”我一听差点没笑出来,但想了想,这问题其实不少刚学 Python 的人也都迷糊过。今天正好趁脑子还有点清醒,来聊聊这个 Python 里的隐藏小机关——双下划线,也叫 Dunder(Double Underscore)方法或者属性。

Dunder 是什么鬼?

这个词听起来跟哈利波特有点像,但其实是 Python 自己的一套“暗号”。你看到那种像 __init__、__str__ 这样包着两根下划线的东西,大多数时候,它不是你写错了,而是 Python 在搞特殊处理。这类名字基本都是给解释器看的,或者说是给类系统预留的钩子。

举个例子哈,比如最熟的 __init__:

classPerson:
def__init__(self, name):
        self.name = name

你 new 一个对象的时候,不是用什么 init 方法,而是 Person("小明"),这时候其实就是 Python 自动调用了 __init__,你手动去调也行,但没人这么干。

那 __str__ 呢?

这个我真是踩坑踩过,比如你写个类,然后 print 它的时候,看到的是一串 <__main__.Person object at 0x7f7c03>,感觉就像 Python 在嘲讽你“你连 __str__ 都不写?”

classPerson:
def__init__(self, name):
        self.name = name

def__str__(self):
returnf"这个人叫 {self.name}"

这样你 print 的时候,就能看出点人味儿了。

真正的隐藏玩法是“名称重整”

这个才是最阴的事儿。比如我写一个类,里面搞一个双下划线开头的变量,比如:

classSecret:
def__init__(self):
        self.__token = "123456"

你以为你在类外面 print(obj.__token) 会拿到值?错!你会被打脸的。

其实 Python 并不是让你完全不能访问这个变量,它只是偷偷改了个名字,在内部变成了 _Secret__token,你试试:

obj = Secret()
print(obj._Secret__token)  # 成功输出 123456

是不是有点像在公司代码里偷偷藏了个 backdoor……

为什么不推荐乱用?

因为这玩意其实没那么“私有”,它只是被“改了名字”。而且乱用容易坑死你团队的其他人,尤其是继承的时候,比如你子类想重写一个双下划线开头的方法,发现压根覆盖不了,因为名字被重命名了!

classA:
def__hello(self):
        print("A")

classB(A):
def__hello(self):
        print("B")

B()._B__hello()  # 打印 B
B()._A__hello()  # 打印 A

卧槽是不是看着就头大。

那单下划线呢?

单下划线比如 _name,就只是个“约定俗成”的私有,其实你想访问也能访问。它就是告诉你“喂,这个变量是内部用的哦,别乱碰”,但不是强制的。

什么时候该用双下划线?

就两种情况我觉得比较合理:

  1. 类库作者写库的时候,真怕别人乱碰内部接口。
  2. 某些特殊钩子函数,你不写不行,比如 __len__、__getitem__ 这种,要让对象支持 len(obj) 或 obj[0],你就得写。

比如这样:

classMyList:
def__init__(self, data):
        self._data = data

def__getitem__(self, index):
return self._data[index]

def__len__(self):
return len(self._data)

然后你可以这样玩:

lst = MyList([1, 2, 3])
print(lst[0])  # 输出 1
print(len(lst))  # 输出 3

很丝滑有没有。

不要被双下划线唬住,它不是魔法,只是语法糖背后的“潜规则”。如果你能读懂这些“糖衣炮弹”,你写 Python 就真的开始上道了。

-END-

我为大家打造了一份RPA教程,完全免费:https://www.songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领