不知道这5种下划线的含义,你就不算真的会Python!


Posted in Python onOctober 09, 2018

什么是 Python? Python 之父 Guido van Rossum 说:Python是一种高级程序语言,其核心设计哲学是代码可读性和语法,能够让程序员用很少的代码来表达自己的想法。

对于我来说,学习 Python 的首要原因是,Python 是一种可以优雅编程的语言。它能够简单自然地写出代码和实现我的想法。

另一个原因是我们可以将 Python 用在很多地方:人工智能、数据科学、Web 开发和机器学习等都可以使用 Python 来开发。

国庆期间后台有小伙伴留言问我:“Python变量和方法名称中单下划线和双下划线的含义是什么?”我想一些初学者或者经验尚浅的朋友一定也会有这个疑问,所以今天我就来跟大家聊聊Python中这个很重要的“下划线”!

不知道这5种下划线的含义,你就不算真的会Python!

单下划线和双下划线在Python变量和方法名称中都各有其含义。有一些含义仅仅是依照约定,被视作是对程序员的提示 - 而有一些含义是由Python解释器严格执行的。

那么,下面就为大家介绍一下Python中单下划线和双下划线("dunder")的各种含义和命名约定,名称修饰(name mangling)的工作原理,以及它如何影响你自己的Python类。

下面将讨论以下五种下划线模式和命名约定,以及它们如何影响Python程序的行为:

单前导下划线:_var

单末尾下划线:var_

双前导下划线:__var

双前导和末尾下划线:__var__

单下划线:_

1、单前导下划线 _var

程序员使用名称前的单下划线,用于指定该名称属性为“私有”。这有点类似于惯例,为了使其他人(或你自己)使用这些代码时将会知道以“_”开头的名称只供内部使用。正如Python文档中所述:

以下划线“_”为前缀的名称(如_spam)应该被视为API中非公开的部分(不管是函数、方法还是数据成员)。此时,应该将它们看作是一种实现细节,在修改它们时无需对外部通知。

正如上面所说,这确实类似一种惯例,因为它对解释器来说确实有一定的意义,如果你写了代码“from <模块/包名> import *”,那么以“_”开头的名称都不会被导入,除非模块或包中的“__all__”列表显式地包含了它们。

看看下面的例子:

class Test:
def __init__(self):
self.foo = 11
self._bar = 23

如果你实例化此类,并尝试访问在__init__构造函数中定义的foo和_bar属性,会发生什么情况? 让我们来看看:

>>> t = Test()
>>> t.foo
11
>>> t._bar
23

你会看到_bar中的单个下划线并没有阻止我们“进入”类并访问该变量的值。

这是因为Python中的单个下划线前缀仅仅是一个约定 - 至少相对于变量和方法名而言。

但是,前导下划线的确会影响从模块中导入名称的方式。

假设你在一个名为my_module的模块中有以下代码:

# This is my_module.py:
def external_func():
return 23
def _internal_func():
return 42

现在,如果使用通配符从模块中导入所有名称,则Python不会导入带有前导下划线的名称(除非模块定义了覆盖此行为的__all__列表):

>>> from my_module import *
>>> external_func()
23
>>> _internal_func()
NameError: "name '_internal_func' is not defined"

顺便说一下,应该避免通配符导入,因为它们使名称空间中存在哪些名称不清楚。 为了清楚起见,坚持常规导入更好。

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

>>> import my_module
>>> my_module.external_func()
23
>>> my_module._internal_func()
42

我们知道这一点可能有点令人困惑。 如果你遵循PEP 8推荐,避免通配符导入,那么你真正需要记住的只有这个:

单个下划线是一个Python命名约定,表示这个名称是供内部使用的。 它通常不由Python解释器强制执行,仅仅作为一种对程序员的提示。

2、单末尾下划线 var_

有时候,一个变量的最合适的名称已经被一个关键字所占用。 因此,像class或def这样的名称不能用作Python中的变量名称。 在这种情况下,你可以附加一个下划线来解决命名冲突:

>>> def make_object(name, class):
SyntaxError: "invalid syntax"
>>> def make_object(name, class_):
... pass

总之,单个末尾下划线(后缀)是一个约定,用来避免与Python关键字产生命名冲突。 PEP 8解释了这个约定。

3、双前导下划线 __var

名称(具体为一个方法名)前双下划线(__)的用法并不是一种惯例,对解释器来说它有特定的意义。Python中的这种用法是为了避免与子类定义的名称冲突。Python文档指出,“__spam”这种形式(至少两个前导下划线,最多一个后续下划线)的任何标识符将会被“_classname__spam”这种形式原文取代,在这里“classname”是去掉前导下划线的当前类名。

例如下面的例子:

>>> class A(object):
... def _internal_use(self):
... pass
... def __method_name(self):
... pass
...
>>> dir(A())
['_A__method_name', ..., '_internal_use']

正如所预料的,“_internal_use”并未改变,而“__method_name”却被变成了“_ClassName__method_name”。此时,如果你创建A的一个子类B,那么你将不能轻易地覆写A中的方法“__method_name”。

>>> class B(A):
... def __method_name(self):
... pass
...
>>> dir(B())

['_A__method_name', '_B__method_name', ..., '_internal_use']

这里的功能几乎和Java中的final方法和C++类中标准方法(非虚方法)一样。

4、双前导和双末尾下划线 _var_

也许令人惊讶的是,如果一个名字同时以双下划线开始和结束,则不会应用名称修饰。 由双下划线前缀和后缀包围的变量不会被Python解释器修改:

class PrefixPostfixTest:
def __init__(self):
self.__bam__ = 42
>>> PrefixPostfixTest().__bam__
42

但是,Python保留了有双前导和双末尾下划线的名称,用于特殊用途。 这样的例子有,__init__对象构造函数,或__call__ --- 它使得一个对象可以被调用。

这些dunder方法通常被称为神奇方法 - 但Python社区中的许多人都不喜欢这种方法。

最好避免在自己的程序中使用以双下划线(“dunders”)开头和结尾的名称,以避免与将来Python语言的变化产生冲突。

5、单下划线 _

通常情况下,会在以下3种场景中使用:

1、在解释器中:在这种情况下,“_”代表交互式解释器会话中上一条执行的语句的结果。这种用法首先被标准CPython解释器采用,然后其他类型的解释器也先后采用。

>>> _ Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_' is not defined
>>> 42
>>> _
42
>>> 'alright!' if _ else ':('
'alright!'
>>> _
'alright!'

2、作为一个名称:这与上面一点稍微有些联系,此时“_”作为临时性的名称使用。这样,当其他人阅读你的代码时将会知道,你分配了一个特定的名称,但是并不会在后面再次用到该名称。例如,下面的例子中,你可能对循环计数中的实际值并不感兴趣,此时就可以使用“_”。

n = 42
for _ in range(n):
do_something()

3、国际化:也许你也曾看到”_“会被作为一个函数来使用。这种情况下,它通常用于实现国际化和本地化字符串之间翻译查找的函数名称,这似乎源自并遵循相应的C约定。

例如,在Django文档“转换”章节中,你将能看到如下代码:

from django.utils.translation import ugettext as _
from django.http import HttpResponse
def my_view(request):
output = _("Welcome to my site.")
return HttpResponse(output)

可以发现,场景二和场景三中的使用方法可能会相互冲突,所以我们需要避免在使用“_”作为国际化查找转换功能的代码块中同时使用“_”作为临时名称。

总结:

Python下划线命名模式 - 小结

以下是一个简短的小结,即“速查表”,罗列了本文中谈到的五种Python下划线模式的含义:

不知道这5种下划线的含义,你就不算真的会Python!

以上所述是小编给大家介绍的不知道这5种下划线的含义,你就不算真的会Python!,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
Python 面向对象 成员的访问约束
Dec 23 Python
python脚本实现分析dns日志并对受访域名排行
Sep 18 Python
详解使用python crontab设置linux定时任务
Dec 08 Python
Python3简单实例计算同花的概率代码
Dec 06 Python
Python冲顶大会 快来答题!
Jan 17 Python
Python利用正则表达式实现计算器算法思路解析
Apr 25 Python
Python单元测试unittest的具体使用示例
Dec 17 Python
python无序链表删除重复项的方法
Jan 17 Python
python 装饰器功能与用法案例详解
Mar 06 Python
Python调用JavaScript代码的方法
Oct 27 Python
自己搭建resnet18网络并加载torchvision自带权重的操作
May 13 Python
Python实现双向链表基本操作
May 25 Python
详解利用django中间件django.middleware.csrf.CsrfViewMiddleware防止csrf攻击
Oct 09 #Python
详解如何将python3.6软件的py文件打包成exe程序
Oct 09 #Python
让代码变得更易维护的7个Python库
Oct 09 #Python
windows下cx_Freeze生成Python可执行程序的详细步骤
Oct 09 #Python
Python打包方法Pyinstaller的使用
Oct 09 #Python
Python如何发布程序的详细教程
Oct 09 #Python
python如何发布自已pip项目的方法步骤
Oct 09 #Python
You might like
PHP捕获Fatal error错误的方法
2014/06/11 PHP
php中的观察者模式简单实例
2015/01/20 PHP
Zend Framework分页类用法详解
2016/03/22 PHP
jquery中this的使用说明
2010/09/06 Javascript
基于jquery的内容循环滚动小模块(仿新浪微博未登录首页滚动微博显示)
2011/03/28 Javascript
jQuery中hide()方法用法实例
2014/12/24 Javascript
javaScript实现可缩放的显示区效果代码
2015/10/26 Javascript
Ext JS框架中日期函数的用法及日期选择控件的实现
2016/05/21 Javascript
简单掌握JavaScript中const声明常量与变量的用法
2016/05/21 Javascript
javascript数组常用方法汇总
2016/09/10 Javascript
js+css3制作时钟特效
2016/10/16 Javascript
js获取元素下的第一级子元素的方法(推荐)
2017/03/05 Javascript
node.js express中app.param的用法详解
2017/07/16 Javascript
js字符限制(字符截取) 一个中文汉字算两个字符
2017/09/12 Javascript
微信小程序实现折叠展开效果
2018/07/19 Javascript
Vue.js中provide/inject实现响应式数据更新的方法示例
2019/10/16 Javascript
十分钟教你上手ES2020新特性
2020/02/12 Javascript
vue+canvas实现拼图小游戏
2020/09/18 Javascript
js轮播图之旋转木马效果
2020/10/13 Javascript
vue 使用 sortable 实现 el-table 拖拽排序功能
2020/12/26 Vue.js
python获取当前用户的主目录路径方法(推荐)
2017/01/12 Python
python读取中文txt文本的方法
2018/04/12 Python
python给微信好友定时推送消息的示例
2019/02/20 Python
tensorflow入门:tfrecord 和tf.data.TFRecordDataset的使用
2020/01/20 Python
Pycharm打开已有项目配置python环境的方法
2020/07/03 Python
关于Python3的import问题(pycharm可以运行命令行import错误)
2020/11/18 Python
英国花园家具中心:Garden Furniture Centre
2017/08/24 全球购物
DJI美国:消费类无人机领域的领导者
2018/04/27 全球购物
会计学个人自荐信模板
2013/12/13 职场文书
教师批评与自我批评发言稿
2014/10/15 职场文书
2015年班级元旦晚会活动总结
2014/11/28 职场文书
个人先进材料范文
2014/12/30 职场文书
天坛导游词
2015/02/02 职场文书
史上最牛辞职信
2015/05/13 职场文书
python 爬取华为应用市场评论
2021/05/29 Python
win7配置本地ftp服务器的图文教程
2022/08/05 Servers