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日

相关文章

  • 如何在Python中对CSV进行多列排序

    可以使用Python的内置库csv和operator来对CSV进行多列排序。 首先,我们需要读取CSV文件并将其转换为list对象: import csv with open(‘data.csv’, ‘r’) as file: reader = csv.reader(file) data = list(reader) 接下来,我们可以使用sorted()函数…

    python-answer 2023年3月27日
    00
  • Numpy报”TypeError:unsupported operand type(s)for-:’numpy.ndarray’and’int’ “的原因以及解决办法

    这个错误通常意味着你把numpy数组和整数进行了非法的操作。下面是一些常见的原因和对应的解决办法来解决这个错误。 错误原因:在数组中使用非数组操作 如果您的代码旨在执行非数组操作,例如将整数从数组中减去,则会收到此错误。例如,以下代码将返回上述错误: import numpy as np a = np.array([1, 2, 3]) b = a – 1 本…

    python-answer 2023年3月15日
    00
  • Python reduce()归约数据集

    首先,Python中有个内置的函数reduce(),它可以迭代序列并对它的成员归约为一个单一的总和。reduce的工作原理为,将列表中的一对乘积相乘并返回乘积。接着,将这个乘积和列表中的下一个数字相乘,一直执行到列表中没有剩余对象。reduce函数的语法如下: reduce(function, sequence[, initial]) 其中,参数functi…

    python-answer 2023年3月25日
    00
  • PyTorch报”AttributeError: ‘function’ object has no attribute ‘requires_grad_’ “的原因以及解决办法

    问题原因 出现“AttributeError: ‘function’ object has no attribute ‘requiresgrad’”错误的原因一般是将函数名与变量名混淆,导致调用了函数对象的属性,而函数对象并没有这个属性。具体来说,可能是在使用代码时将函数名作为变量名重复定义了。 解决方案 检查代码中是否有变量名与函数名冲突的情况,如果发现了…

    python-answer 2023年3月19日
    00
  • 从Pandas数据框架中的行创建一个列表

    从Pandas数据框架中的行创建一个列表通常有以下几个步骤: 步骤1:导入必要的库 在使用Pandas数据框架创建列表之前,需要导入Pandas库和任何其他需要使用的库。可以使用以下语句导入它们: import pandas as pd 步骤2:创建数据框 在创建行的列表之前,需要先创建一个数据框。数据框是Pandas库中最常用的数据结构之一,可以是二维的表…

    python-answer 2023年3月27日
    00
  • Django报”EmptyResultSet “的原因以及解决办法

    会出现EmptyResultSet的原因 Django中的QuerySet有些操作会导致EmptyResultSet异常的出现,比如以下情况: QuerySet对象调用first、last,但是查询的结果集为空。 使用filter或exclude方法过滤查询结果时,没有符合条件的结果集。 使用Q对象或Q对象的“|”、"&"等运算符…

    python-answer 2023年3月17日
    00
  • 详解Python PIL ImageDraw.Draw.chord()

    Python PIL库中的ImageDraw模块提供了一些常用的图片绘制方法,其中包括了绘制扇形和弧形的功能,即chord()方法。本文将为大家详细介绍Python PIL ImageDraw.Draw.chord()的完整攻略。 1. 简介 ImageDraw.Draw.chord(xy, start, end, fill=None, outline=No…

    python-answer 2023年3月25日
    00
  • scikit-learn报”ValueError: Length of values does not match length of index “的原因以及解决办法

    问题原因 这个错误表示值的长度与索引的长度不匹配。通常情况下,这是由于以下原因引起的: 给某个参数传递了不正确的值 输入数据的维度不一致 数据中有缺失值 数据类型不匹配 解决办法 根据具体的情况,可以采取以下措施解决这个问题: 检查参数值是否正确 检查代码,看看是否有错误使用了参数中的某个值。如果有,请将其更正。 检查输入数据的维度是否一致 在使用 scik…

    python-answer 2023年3月19日
    00

发表回复

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

评论列表(1条)

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

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

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