Python中下划线“_”都有什么含义?

yizhihongxing

Python中下划线“_”有什么含义?

在Python的变量名和方法名中经常会看到下划线的使用,有时是单下划线,有时是双下划线。对此你可能有些疑惑:“Python中的下划线到底有什么含义?”

本文将竭力为您解释清楚Python中下划线到底有什么含义。

Python中基本上有以下5种下划线约定模式:

  • 前置的单下划线:_var
  • 后置单下划线:var_
  • 前置双下划线:__var
  • 前后双下划线:var
  • 单独的下划线:_

就影响而言,下划线分为以下两类:

  • 对程序运行没有影响:这种仅仅是一种约定,用于提示开发人员。
  • 对程序运行有影响:这种对Python解释器有特别的含义,随意更改会影响程序的运行。

接下来为您详细解释着5中下划线模式的涵义。

Python 前置单下划线:_var

一般情况下,前置的单下划线是程序员之间一种默契的约定。当它出现在变量名或方法名中时,意思是提示其他程序员:这个变量或方法是私有的,只在内部使用。(PEP 8(最常用的Python代码风格指南。)中定义了这个约定)。

不过,这个约定对Python解释器来说没有意义。与Java等高级语言不通,Python当中并没有“公共”或“私有”之类的概念,所以前置的单下划线对程序运行几乎没有影响(后续再解释这里为什么用“几乎”这个词)。

我们看以下代码:

class Site:
    def __init__(self):
        self.name = 'Python技术站'
        self._url = 'http://www.pythonjishu.com'

demo = Site()
#访问两个属性
print(demo.name)
print(demo._url)

运行结果:

Python技术站
http://www.pythonjishu.com

可以看到,_url前面的单下划线并没有影响我们访问这个变量的值。

基本上,我们对Python中的前置单下划线的认知,可以到此为止了。

前面我们讲过,前置的单下划线对程序运行几乎没有影响。之所以用“几乎”一词,是因为在某些时候,Python解释器又承认了前置单下划线表示的是“内部使用”的意思,导致使用前置单下划线的变量或方法无法访问!

这个特殊的情况是发生在我们从其他库中导入模块的时候。

当我们使用通配符导入方式导入模块时,Python不会导入带有前置单下划线的方法或变量。

举个例子,比如在一个名为demo_module的模块中有以下代码:

# demo_module.py:

def external_func():
    return 'Python技术站'
def _internal_func():
    return 'http://www.pythonjishu.com'

现在,如果使用通配符导入这个模块,Python不会把带有前置单下划线的方法导入进来。也就是说,无法访问到 demo_module 的 _internal_func 方法:

from demo_module import *
external_func()

输出:

Python技术站

_internal_func()

输出异常信息:

NameError: "name '_internal_func' is not defined"

与通配符导入不同,常规导入不受前置单下划线命名约定的影响:

import demo_module
demo_module.external_func()

输出:

Python技术站

demo_module._internal_func()

输出:

http://www.pythonjishu.com

所以我们在工作中最好遵循 PEP 8的建议,尽量避免使用通配符导入模块。

Python 后置下划线var_

有时候,某个变量最合适的名称已被Python中的关键字所占用,比如 class、def、for等名称都不能用作变量名。那么这时候,我们可以追加一个下划线来绕过命名冲突。

class = 'class-name'
print(class)

输出:SyntaxError: invalid syntax

class_ = 'class-name'
print(class_)

输出:class-name

总之,我们可以用一个后置单下划线来避免与Python关键字的命名冲突。PEP 8定义并解释了这个约定。

前置双下划线:__var

上文我们介绍的命名模式只有约定的意义,但使用双下划线开头的属性、变量或方法就不同了。

双下划线前缀的代表的含义是:此属性不允许被子类重写

但Python作为解释型语言,并没有某个关键字为父类属性做这种限制,解释器也无法分辨这种情况,怎么办呢?

很简单,Python解释器使用了名称改写(name mangling)的方式,改写了父类属性的名称,从而避免子类中出现命名冲突。

下面用代码实例来检验一下:

class Site():
    def __init__(self):
        self.name = 'Python技术站'
        self._domain = 'www.pythonjishu.com'
        self.__tech = 'python'
t = Site()
#输出__tech属性
print(t.__tech)

输出结果为:

AttributeError: 'Site' object has no attribute '__tech'

我们发现对象t根本没有__tech的属性所以报错了,这是什么原因呢?

其实是因为Python解释器改写了__tech的变量名。

我们使用内置函数dir()看看t的属性:

['_Sitetech', 'class', 'delattr', 'dict', 'dir', 'doc', 'eq', 'format', 'ge', 'getattribute', 'getstate', 'gt', 'hash', 'init', 'init_subclass', 'le', 'lt', 'module', 'ne', 'new', 'reduce', 'reduce_ex', 'repr', 'setattr', 'sizeof', 'str', 'subclasshook', 'weakref__', '_domain', 'name']

我们发现__tech属性被改写成了_Site__tech,也就是在前面增加了“_类名”。

输出看一看:

print(t._Site__tech)

输出:

python

通过这种方式,可以成功避免子类覆盖父类的属性。因为子类如果也定义一个 __tech 属性时,子类会将其改写为 _子类名_tech,而父类的_Site_tech属性还会保留。如下:

class ExtendedTest(Site):
    def __init__(self):
        super().__init__()
        self.__tech = 'AI'

t2=ExtendedTest()
print(dir(t2))

输出结果为:

['_ExtendedTesttech', '_Sitetech', 'class', 'delattr', 'dict', 'dir', 'doc', 'eq', 'format', 'ge', 'getattribute', 'getstate', 'gt', 'hash', 'init', 'init_subclass', 'le', 'lt', 'module', 'ne', 'new', 'reduce', '__reduce_ex', 'repr', 'setattr', 'sizeof', 'str', 'subclasshook', 'weakref__', '_domain', 'name']

可以看到,t2将 tech 属性改为了 _ExtendedTest__tech,,并且保留了 _Sitetech 的父类属性。

Python 前后双下划线:var

与前置双下划线不同,名字前后都使用双下划线,不会发生名称的改写。

一般来说,前后双下划线的名称主要由Python官方使用,比如像init 这样的构造函数,让对象可调用的 call 函数等。

对于程序员来说,应当尽量避免在自己的程序中使用以双下划线开头和结尾的名称,以避免与未来Python官方名称发生冲突。

Python 单下划线_var

按照约定,单下划线作为名称,用于表示变量是临时的或者不重要的。

比如,在for循环中,就可以使用_来表示它只是一个临时值:

for _ in range(10)
    print('Hello!')

在解包表达式中还可使用单下划线表示一个“被弃用”的变量。同样,这个含义也只是一个约定,不会影响任何程序。
举例如下:在以下代码中,将元组解包为单独的变量,但其中只关注color和mileage字段的值,可是为了执行解包表达式就必须为元组中的所有值都分配变量,此时_用作占位符变量:

car = ('red', 'auto', 18, 6988.4)
#_表示弃用的、不关心的变量
color, _, _, mileage = car
print(color)

总结

下划线分类 作用
前置单下划线_var 命名约定,用来表示该名称仅在内部使用。一般对Python解释器没有特殊含义(通配符导入除外),只能作为对程序员的提示。
后置单下划线var_ 命名约定,用于避免与Python关键字发生命名冲突。
前置双下划线__var 在类环境中使用时会触发名称改写,对Python解释器有特殊含义。
前后双下划线var 表示由Python语言定义的特殊方法。在自定义的属性中要避免使用这种命名方式。
单下划线_ 有时用作临时或无意义变量的名称(“不关心”)。此外还能表示Python REPL会话中上一个表达式的结果。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python中下划线“_”都有什么含义? - Python技术站

(0)
上一篇 2022年11月28日 下午8:56
下一篇 2023年2月4日

相关文章

  • Python 编写高阶归约

    Python编写高阶归约是使用函数式编程(Functional Programming)的重要一环,对于使用Python进行数据分析和科学计算的程序员来说,学习这项技能可以提高应对各种数据操作的效率与灵活度。下面,本文将详细讲解Python编写高阶归约使用方法的完整攻略。 什么是高阶归约? 在函数式编程中,高阶函数(Higher-order function…

    python-answer 2023年3月25日
    00
  • Python 用排序构建映射

    Python中,用排序构建映射可以使用内置的sorted()函数和zip()函数完成。具体方法是将需要构建映射的两个列表先按照某一关键词进行排序,然后使用zip()函数将已排序的两个列表一一对应起来,最后以字典的形式返回对应关系。 以下是使用方法的完整攻略: 排序构建映射 使用排序构建映射的一般流程为: 通过sorted()函数将需要构建映射的两个列表分别按…

    python-answer 2023年3月25日
    00
  • 详解TensorFlow报”ValueError: Shapes must be equal rank, but are and “的原因以及解决办法

    当在TensorFlow中执行操作时,输入的张量的形状必须满足一定的规则。其中之一是它们必须具有相同的秩或维数。如果不满足这个要求,则会抛出 "ValueError: Shapes must be equal rank, but are "异常。 这种异常通常发生在张量的维数(rank)不同的情况下,尝试将它们合并在一起。例如,在以下代码…

    python-answer 2023年3月19日
    00
  • 详解用Python对图片进行循环剪裁

    对于用Python对图片进行循环剪裁的攻略,可以按照以下步骤进行: 第一步:导入相关模块 使用Python对图片进行处理,需要用到一些第三方模块,比如: Pillow模块:是Python中用于图像处理的标准库,可以完成图片的剪裁、缩放、旋转、颜色调整等操作。 os模块:是Python中用于读取文件的标准库,可以获取指定目录下的所有文件名。 代码示例: fro…

    python-answer 2023年3月25日
    00
  • 如何在pandas中利用时间序列

    利用 Pandas 进行时间序列分析的完整攻略大致分为以下几个步骤: 导入 Pandas 和数据集; 将数据集中的日期转换为 Pandas 中的日期格式,并设置为索引; 对时间序列数据进行可视化; 对时间序列进行数据清洗和处理,包括处理缺失值,对数据进行填充等; 对时间序列进行重采样和聚合,比如对数据进行日、周、月等时间间隔的汇总; 对时间序列进行滚动计算,…

    python-answer 2023年3月27日
    00
  • 寻找两个NumPy数组之间的共同值

    寻找两个NumPy数组之间的共同值可以通过NumPy的函数intersect1d()实现。下面是查找过程的完整攻略: 导入NumPy库 在开始查找两个NumPy数组之间的共同值之前,需要先导入NumPy库来支持NumPy的数组操作。可以使用以下代码导入NumPy库: import numpy as np 创建两个NumPy数组 在这个例子中,我们创建两个Nu…

    python-answer 2023年3月25日
    00
  • 详解用Python将文本图像转换为手写文本图像

    下面是用Python将文本图像转换为手写文本图像的完整攻略: 1. 安装必要的库 首先需要安装必要的库,其中包括Pillow库(用于图像处理),Numpy库(用于数学计算),OpenCV库(用于图像处理和机器学习)。可以通过以下命令安装: pip install Pillow numpy opencv-python 2. 加载文本图像 使用Pillow库中的…

    python-answer 2023年3月25日
    00
  • 用Pandas的read_html()来抓取维基百科的表格

    当需要从互联网上获取数据时,网页上的表格是一个很好的数据源。而Python中的Pandas库提供了一个方便的方法来获取HTML表格。这个方法是read_html(),它可以从web页面上的table标签中提取出数据。 使用read_html()来抓取维基百科的表格有以下步骤: 1.导入所需的库 import pandas as pd 2.创建一个URL变量,…

    python-answer 2023年3月27日
    00

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

评论列表(1条)

  • Python标识符命名规范_Python技术站的头像
    Python标识符命名规范_Python技术站 2023年2月13日 下午2:14

    […] 以双下划綫作为开头和结尾的标识符(如init),是Python专用的标识符,每一种都代表不同的含义。关于下划线的使用请参阅:Python中下划线“_”都有什么含义? […]

合作推广
合作推广
分享本页
返回顶部