首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Python 中各种下划线的用法

Python 中各种下划线的用法

作者头像
用户11081884
发布2026-07-20 20:11:32
发布2026-07-20 20:11:32
310
举报

下划线在 Python 里用途远不止“分隔单词”。一共有六种不同写法,每种都有明确的含义和约定,弄混了要么代码出 bug,要么让同事看不懂你在写什么。


1. 单个下划线(_

在交互式解释器里,_ 保存着上一次表达式的结果,临时运算很方便:

代码语言:javascript
复制
>>>10+20
30
>>>_
30  # _ 保存了上一次的结果
>>>_*2
60

写数字字面量时,_ 可以当千位分隔符用,纯粹是为了可读性,运行时会被忽略:

代码语言:javascript
复制
large_number = 1_000_000
print(large_number)  # 输出: 1000000

price = 9_999.99
print(price)  # 输出: 9999.99

循环里用 _ 表示“这个值我不用”:

代码语言:javascript
复制
# 只跑五次,不需要索引
for_inrange(5):
    print("Hello, Python!")

# 解包时丢掉不需要的位置
data = (1, 2, 3, 4, 5)
first, _, third, _, fifth = data
print(first, third, fifth)  # 输出: 1 3 5

2. 双下划线开头结尾(__xx__):魔法方法

这是 Python 内置的“特殊方法”专用命名空间,__init____str____len__ 这些都属于这一类:

代码语言:javascript
复制
classMyClass:
    def__init__(self, value):
        self.value = value
    
    def__str__(self):
        returnf"MyClass with value: {self.value}"
    
    def__len__(self):
        returnlen(str(self.value))

obj = MyClass(42)
print(obj)      # 调用 __str__
print(len(obj)) # 调用 __len__

不要自己定义 __xxx__ 格式的名字——这个命名空间是 Python 保留的,随版本迭代可能会和新增的内置方法撞名。


3. 单下划线开头(_xx):内部使用

_ 开头表示“这是内部实现,外部别直接用”。更实际的效果是:from module import * 不会导入这类名字。

mymodule.py

代码语言:javascript
复制
defpublic_func():
    return"This is public"

def_internal_func():
    return"This is internal"

导入行为的差异:

代码语言:javascript
复制
# 方式1:导入整个模块——两个都能用
importmymodule
print(mymodule.public_func())    # 正常
print(mymodule._internal_func()) # 技术上可以,但不推荐

# 方式2:通配符导入——只导入公共的
frommymoduleimport*
print(public_func())      # 正常
# print(_internal_func()) # NameError:压根没被导入进来

4. 单下划线结尾(xx_):绕过关键词冲突

变量名恰好和关键词撞了,后面加 _ 就能用:

代码语言:javascript
复制
# class = "MyClass"  # SyntaxError

class_ = "MyClass"
def_ = "function"
return_ = "value"

print(class_, def_, return_)  # 输出: MyClass function value

不过实际上能用的话,换一个完全不同的名字更好——class_ 读起来总归有点别扭。


5. 双下划线开头(__xx):名称修饰(Name Mangling)

__ 开头的属性,Python 会在背后把它改名为 _ClassName__xx,目的是防止子类无意间覆盖父类的属性:

代码语言:javascript
复制
classParent:
    def__init__(self):
        self.public = "公共属性"
        self.__private = "私有属性(经过名称修饰)"
    
    defget_private(self):
        returnself.__private

classChild(Parent):
    def__init__(self):
        super().__init__()
        self.__private = "子类的私有属性"  # 不会覆盖父类的 __private
    
    defshow_all(self):
        print(f"公共属性: {self.public}")
        print(f"尝试访问父类私有属性: {self.get_private()}")
        print(f"子类自己的私有属性: {self.__private}")

parent = Parent()
print(parent.public)          # 输出: 公共属性
# print(parent.__private)     # AttributeError

child = Child()
child.show_all()
# 公共属性: 公共属性
# 尝试访问父类私有属性: 私有属性(经过名称修饰)
# 子类自己的私有属性: 子类的私有属性

Parent 里的 __private 实际存储名是 _Parent__privateChild 里的是 _Child__private,两者互不干扰。


6. _ClassName__xx:直接访问被修饰后的名字

既然知道改名规则,就可以绕过去直接访问:

代码语言:javascript
复制
classMyClass:
    def__init__(self):
        self.__secret = "隐藏的秘密"

obj = MyClass()
# print(obj.__secret)         # AttributeError
print(obj._MyClass__secret)   # 输出: 隐藏的秘密

这只适合调试或测试场景。正常业务代码里这样写,基本意味着设计出了问题。

综合示例

六种写法放在一个类里看得更清楚:

代码语言:javascript
复制
classExample:
    def__init__(self):
        self.normal = "普通属性"
        self._internal = "内部属性"
        self.__private = "私有属性"
    
    defpublic_method(self):
        return"公共方法"
    
    def_internal_method(self):
        return"内部方法"
    
    def__private_method(self):
        return"私有方法"
    
    defshow_private(self):
        returnself.__private_method()

ex = Example()
print(ex.normal)              # 正常
print(ex._internal)           # 可以访问,但约定上别这么做
print(ex.show_private())      # 通过公共方法访问私有方法
# print(ex.__private)         # AttributeError
# print(ex.__private_method)  # AttributeError

六种规则里,__xx__ 不要碰(Python 的地盘),_xx__xx 是日常最有用的两种——前者表示“我打算内部用”,后者表示“子类别动”,理解这两个区别就够用了。

“无他,惟手熟尔”!有需要的用起来!

如果你觉得这篇文章有用,欢迎点赞、转发、收藏、留言、推荐❤!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-04-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Nicholas与Pypi 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 单个下划线(_)
  • 2. 双下划线开头结尾(__xx__):魔法方法
  • 3. 单下划线开头(_xx):内部使用
  • 4. 单下划线结尾(xx_):绕过关键词冲突
  • 5. 双下划线开头(__xx):名称修饰(Name Mangling)
  • 6. _ClassName__xx:直接访问被修饰后的名字
  • 综合示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档