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

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日

相关文章

  • Numpy报”ValueError:invalid literal for int()with base X “的原因以及解决办法

    问题描述 在使用Numpy时,出现了以下错误: ValueError: invalid literal for int() with base X: 'string' 其中,X表示进制数,string表示某个字符串。这个错误一般出现在将字符串转换为整数时。 问题分析 Numpy主要用于数值计算,在处理数据时,需要使用大量的数组操作。而在进…

    python-answer 2023年3月15日
    00
  • 如何在Pandas中读取一个文件夹中的所有CSV文件

    在Pandas中,我们可以使用read_csv()函数来读取CSV文件。为了读取文件夹中所有的CSV文件,我们需要使用Python的os库来获取文件夹中所有CSV文件的路径,并使用循环遍历路径列表,依次读取每个CSV文件。 下面是示例代码,演示如何读取文件夹中的所有CSV文件,并将它们合并成一个Pandas数据框: import os import pand…

    python-answer 2023年3月27日
    00
  • 基于标签的Pandas数据框架索引

    基于标签的索引(Label-based indexing)是Pandas数据框架中一种基于标签或名称的索引方式,其优点在于易于理解和使用,并且不容易产生歧义,因此得到广泛地应用。在本攻略中,我们将详细讲解如何使用基于标签的索引方式来操作Pandas数据框架。以下是我们的操作流程: 选择列标签 在Pandas数据框架中,我们可以通过列标签(也称为列名)来选择数…

    python-answer 2023年3月27日
    00
  • Pandas报”AttributeError:’DataFrame’object has no attribute’drop’“的原因以及解决办法

    问题描述 在使用Pandas的DataFrame时,当我们尝试使用drop函数时,报错提示如下: AttributeError: 'DataFrame' object has no attribute 'drop' 这个错误提示意味着DataFrame对象没有drop属性,也就是说,我们不能使用drop函数进行数据操作…

    python-answer 2023年3月14日
    00
  • PyTorch报”TypeError: Conv2d() missing 1 required positional argument: ‘out_channels’ “的原因以及解决办法

    问题描述 在使用 PyTorch 构建卷积神经网络时,当调用 torch.nn.Conv2d() 函数时可能会出现如下类型的报错: TypeError: Conv2d() missing 1 required positional argument: ‘out_channels’ 出错原因 这种类型的报错通常是由于使用函数时没有为 out_channels …

    python-answer 2023年3月19日
    00
  • 使用Python Pandas和Flask框架将CSV转换成HTML表

    请看下面的详细讲解。 准备工作 在实现这个功能之前,我们需要准备好以下工具和环境: Python环境和Pandas库; Flask框架; CSV文件。 确保你的电脑上已经安装了Python环境。如果还没有安装,可以去官网下载:https://www.python.org/downloads/。 然后,可以通过pip安装Pandas和Flask库,在终端或命令…

    python-answer 2023年3月27日
    00
  • 如何在Pandas中计算一个列的百分比

    在Pandas中,我们可以通过将列中的每个值除以该列的总和来计算列的百分比。下面是一个详细的攻略,包括代码和实例说明。 我们以如下数据框为例: import pandas as pd data = {‘Name’: [‘Alice’, ‘Bob’, ‘Charlie’, ‘David’, ‘Eva’], ‘Age’: [21, 22, 23, 24, 25]…

    python-answer 2023年3月27日
    00
  • Python 在Pandas DataFrame中改变列名和行索引

    修改Pandas DataFrame中的列名和行索引是一项常见的任务,可以通过以下方式实现。 修改列名:- 使用DataFrame的rename()方法,该方法可以使用字典形式或函数方式进行操作。- 使用DataFrame的columns属性,该属性可以修改全部列名,但需要一并指定所有列名。 例如,我们有以下DataFrame,需要修改其中两列的名称: im…

    python-answer 2023年3月27日
    00

评论列表(1条)

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

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

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