android开发实战 UEditor HTML框架 ssm templates memory sed yii coldfusion handlebarsjs vue请求 后台管理界面 sql视频教程 jquery点击事件 office2016修复 linux查询文件内容 python数据格式 python输入输出 python编程工具 python基础代码 python获取时间戳 java的继承 java字符串替换 java基础框架 Ext2Fsd ps插入表格 剑三醉猿 机械键盘个别键位失灵 早早省 大数据之路 屏幕录像专家注册机 无线网改密码 谷歌地球怎么用不了 电脑录屏工具 铁血统帅 js绑定事件的方法 迅捷pdf转换器官网 pygame安装教程 安装telnet 方正卡通
当前位置: 首页 > 学习教程  > 编程语言

Python中的下划线 _

2021/1/13 20:39:15 文章标签: 测试文章如有侵权请发送至邮箱809451989@qq.com投诉后文章立即删除

本文介绍了Python中单下划线和双下划线(“dunder”)的各种含义和命名约定,名称修饰(name mangling)的工作原理,以及它如何影响你自己的Python类。 单下划线和双下划线在Python变量和方法名称中都各有其含义…

本文介绍了Python中单下划线和双下划线(“dunder”)的各种含义和命名约定,名称修饰(name mangling)的工作原理,以及它如何影响你自己的Python类。

单下划线和双下划线在Python变量和方法名称中都各有其含义。有一些含义仅仅是约定俗称的习惯,而有一些含义是由Python解释器严格执行的。

  • 单前导下划线:_var
  • 单末尾下划线:var_
  • 双前导下划线:__var
  • 双前导和双末尾下划线:__var__
  • 单下划线:_

1. 单前导下划线:_var

这只是一种约定俗称的规定。下划线前缀的含义是:这样的的变量或方法仅供内部使用。 但并不是真的不能进行外部访问。

class Test:
   def __init__(self):
       self.foo = 11
       self._bar = 23
       t = Test()
>>> t._bar	# 可以访问没问题~
23

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

# 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

2. 单末尾下划线:var_

2.1 解决命名冲突

这只是一种约定俗成的编程规范。

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

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

2.2 inplace方法

有少量的操作仅作为张量对象的方法存在。你可以通过名称中的下划线来识别它们,例如zero_,下划线标识表明该方法是就地(inplace)运行的,即直接修改输入而不是创建新的输出并返回。例如,zero_方法会将输入的所有元素清零。任何不带下划线的方法都将保持源张量不变并返回新的张量:

a = torch.ones(3, 2)
a.zero_()	# 这种调用是合法的
a = torch.zero_(a)	# 这种调用不合法

3. 双前导下划线:__var

双下划线前缀会导致Python解释器重写属性名称,以避免子类中的命名冲突。

这也叫做名称修饰(name mangling):解释器自行变更变量的名称,以便在类被扩展的时候不容易产生冲突。

理论很抽象,看代码~

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

t = Test()

暂时不用关心__init__这个命名,就当作是个名字就好,下一节会讲。让我们用内置的dir()函数来看看这个对象的属性:

dir(t)
['_Test__baz', '__class__', '__delattr__', '__dict__', '__dir__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', '_bar', 'foo']

我们找到了foo _bar但是找不到__baz,可是却找到了一个_Test__baz。这就是Python解释器所做的名称修饰。 它这样做是为了防止变量在子类中被重写。其中_Test是你的类名。

再来创建一个继承自Test的类

class ExtendedTest(Test):
   def __init__(self):
       super().__init__()
       self.foo = 'overridden'
       self._bar = 'overridden'
       self.__baz = 'overridden'
      
t2 = ExtendedTest()

同样定义了三个相同的元素,看看结果如何

>>> t2.foo
'overridden'
>>> t2._bar
'overridden'
>>> t2.__baz
AttributeError: "'ExtendedTest' object has no attribute '__baz'"
>>> t2._ExtendedTest__baz
'overridden'
>>> t2._Test__baz
42

其中没有__baz这个元素,但是却有_ExtendedTest__baz,并且还有从Test中继承来的_Test__baz

这也被称为Python的私有变量,私有方法。

python中不存在protected的概念,只有public和private,但是python中的private不是真正意义上的private,通过name mangling(名称修饰,即前面加上“单下划线”+类名,eg:_Class__object)机制就可以访问private了。

4. 双前导和双末尾下划线:__var__

因为变量名__object__对Python 来说有特殊含义,对于普通的变量应当避免这种命名风格。

5. 单下划线:_

5.1 最近计算的结果

单下划线类似于MATLAB中的ans,是最近计算的答案。在交互式编程中(Python编程有两种,Jupyter式的交互式编程,使用PyCharm式的脚本式编程)如下所示:

>>> tax = 12.5 / 100
>>> price = 100.50
>>> price * tax
12.5625
>>> price + _
113.0625
>>> round(_, 2)
113.06

而在脚本式编程中,上述代码会报错。因为脚本式编程中,只有先显式的定义了_才能调用它,如:

tax = 12.5 / 100
price = 100.50
_ = price * tax		# 此处显示的定义了:_
print(price + _)
>>> 113.0625
print(round(_, 2))
>>> 113.06

5.2 临时变量

单个独立下划线是用作一个名字,来表示某个变量是临时的或无关紧要的。 比如,在下面的循环中,我们不需要访问正在运行的索引,我们可以使用“_”来表示它只是一个临时值:

for _ in range(32):
    print(_, 'Hello World!')

“_”作为占位符变量,用来忽略你不关心的变量

car = ('red', 'auto', 12, 3812.4)
color, _, _, mileage = car

本文链接: http://www.dtmao.cc/news_show_600391.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?