a标签去下划线或文字添加下修饰_Python基础必备:最强字符——下划线,你的编程小帮手...

news/2024/7/7 12:46:23

刚开始学Python的时候会发现,Python里会出现各种各样的下划线 “_”,而且位置都不相同,有时候在名称后面,有时候在前面,有时候还会在数字中间......这些下划线都分别是什么意思呢?

这里我们将介绍的五种不同情况:

c8f19992880b3b63d265b1aeb3ff7b75.png

一.单下划线(_)

单下划线通常在3种情况下使用:

1.在解析程序中

按照习惯,有时候单个独立下划线是用作一个名字,来表示某个变量是临时的或无关紧要的。

_名称指向交互式解释器会话中,最后执行的语句结果。这首先是由标准CPython解释器完成的,其他解析器也紧随其后。

b5bc207e53daa3f1952d435b6f1de725.png

在下面的代码示例中,我将汽车元组拆分为单独的变量,但我只对颜色和里程值感兴趣。 但是,为了使拆分表达式成功运行,我需要将包含在元组中的所有值分配给变量。 在这种情况下,“_”作为占位符变量可以派上用场:

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

>>> color
'red'
>>> mileage
3812.4
>>> _
12

2.作为名称

这与上一点有些关联,_ 用作一次性的名称。这为了让阅读代码的人知道,这里分配了某个名称,但是不打算使用。例如,在下面的循环中,我们不需要访问正在运行的索引,我们可以使用“_”来表示它只是一个临时值:

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

3.i18n

我们可以看到 _ 还可以用作函数。在这种情况下,它通常用于执行国际化和本地化字符串转换查找的函数的名称。这似乎源于并遵循 C 语言的相关规则。如在Django文档中所见:

from django.http import HttpResponse
from django.utils.translation import gettext as _

def my_view(request):
    output = _("Welcome to my site.")
    return HttpResponse(output)

在任何还将 _ 用作 i18n 查找和翻译的代码块中,都应避免使用 _ 作为一次性使用的名称。

二.名称前加单下划线(例如_total)

名称前的单个下划线用于指定程序员将名称视为“私有”。这可以视为一种约定,下划线前缀的含义是告知其他程序员:以单个下划线开头的变量或方法仅供内部使用。。 正如Python文档所述:

带有下划线的名称(例如 _spam)应被视为 API 的非公开部分(无论是函数、方法还是数据成员)。它应被视为实现细节,如有更改,恕不另行通知。

*之所以说是一种约定,是因为它实际上对解析程序而言有着某种意义;如果我们从 <module / package> import *,除非以模块/软件包的 __all__ 列表明确包含它们,否则不会导入以 _开头的名称。看看下面的例子:

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

861a322f80679031b2f9b5f099712367.png

三. 名称后的单下划线(例如 total_)

一个变量的最合适的名称已经被一个关键字所占用,可以附加一个下划线来解决命名冲突:例如,如果你想命名某种格式,为了避免掩盖 Python 的内置格式,你可以将其命名为 format_。

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

>>> def make_object(name, class_):
...    pass

四. 数字字面中的单下划线(例如 100_000)

PEP 515 指数建议扩展 Python 的语法,以便下划线可以用作整体、浮点和复杂数字文本中数字分组的可视分隔符。

我们可以执行以下操作::

# 十进制数按千分组
amount = 10_000_000.0

# 按字对十六进制地址进行分组
addr = 0xCAFE_F00D

# 用二进制文字将位分组为半字节
flags = 0b_0011_1111_0100_1110

#相同,用于字符串转换
flags = int('0b_1111_0000', 2)

五. 姓名前的双下划线(例如__total)

在名称(特别是方法名称)前使用双下划线(__)不是约定,只是对解析程序有特殊的意义。双下划线前缀会导致Python解释器重写属性名称,以避免子类中的命名冲突。

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

这听起来很抽象。 因此,我组合了一个小小的代码示例来予以说明:

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

让我们用内置的dir()函数来看看这个对象的属性:

>>> t = Test()
>>> 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 - 我保证你会注意到一些有趣的变化。

  • self.foo变量在属性列表中显示为未修改为foo。
  • self._bar的行为方式相同 - 它以_bar的形式显示在类上。 就像我之前说过的,在这种情况下,前导下划线仅仅是一个约定。 给程序员一个提示而已。
  • 然而,对于self.__baz而言,情况看起来有点不同。 当你在该列表中搜索__baz时,你会看不到有这个名字的变量。

bfd794688d1fb34f11630c1a77d9d202.png

__baz出什么情况了?

如果你仔细观察,你会看到此对象上有一个名为_Test__baz的属性。 这就是Python解释器所做的名称修饰。 它这样做是为了防止变量在子类中被重写。

让我们创建另一个扩展Test类的类,并尝试重写构造函数中添加的现有属性:

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

现在,你认为foo,_bar和__baz的值会出现在这个ExtendedTest类的实例上吗? 我们来看一看:

>>> t2 = ExtendedTest()
>>> t2.foo
'overridden'
>>> t2._bar
'overridden'
>>> t2.__baz
AttributeError: "'ExtendedTest' object has no attribute '__baz'"

等一下,当我们尝试查看t2 .__ baz的值时,为什么我们会得到AttributeError? 名称修饰被再次触发了! 事实证明,这个对象甚至没有__baz属性:

>>> dir(t2)
['_ExtendedTest__baz', '_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', 'get_vars']

正如你可以看到__baz变成_ExtendedTest__baz以防止意外修改:

>>> t2._ExtendedTest__baz
'overridden'

但原来的_Test__baz还在:

>>> t2._Test__baz
42

双下划线名称修饰对程序员是完全透明的。 下面的例子证实了这一点:

class ManglingTest:
   def __init__(self):
       self.__mangled = 'hello'

   def get_mangled(self):
       return self.__mangled

>>> ManglingTest().get_mangled()
'hello'
>>> ManglingTest().__mangled
AttributeError: "'ManglingTest' object has no attribute '__mangled'"

名称修饰是否也适用于方法名称? 是的,也适用。名称修饰会影响在一个类的上下文中,以两个下划线字符("dunders")开头的所有名称:

class MangledMethod:
   def __method(self):
       return 42

   def call_it(self):
       return self.__method()

>>> MangledMethod().__method()
AttributeError: "'MangledMethod' object has no attribute '__method'"
>>> MangledMethod().call_it()
42

这是另一个也许令人惊讶地运用名称修饰的例子:

_MangledGlobal__mangled = 23

class MangledGlobal:
   def test(self):
       return __mangled

>>> MangledGlobal().test()
23

六. 在名称之前和之后加上双下划线(例如__init__)

这些是 Python 使用的特殊方法名称。对于我们来说,这只是一个约定,即 Python 系统使用与用户定义的名称不冲突的名称的一种方式。然后,我们通常会覆盖这些方法并为 Python 调用它们时定义所需的行为。例如,在编写类时__init__重写方法。

没有什么可以阻止我们编写自己的特殊方法名称(但是最好别这么做):

>>> class C(object):
...     def __mine__(self):
...         pass
...
>>> dir(C)
... [..., '__mine__', ...]

尽量不要使用这种命名方式,只需要让Python定义的特殊名称遵循该约定即可。


http://www.niftyadmin.cn/n/3938207.html

相关文章

dayjs format 变成12小时制_12月24日

(图片仅供参考&#xff0c;请以实物为准)今天免费赠送小零食&#xff1a;新增热饮&#xff1a;乳茶&#xff1a;10元 /乳酸菌饮料&#xff1a;5元 /康师傅奶茶&#xff1a;5元 / 暖柚/暖橙&#xff1a;5.5元 / 特仑苏&#xff1a;5元 /维他奶&#xff1a;4元 /三元纯牛奶…

a1 抛光等级spi_您合作的模具光学抛光厂家是否有达到以下的抛光效果

在模具光学抛光厂家中&#xff0c;我们常常会听到A0、A1、A2、A3等概念&#xff0c;那么这几个概念分别指的是什么呢&#xff1f;小编为帮助大家了解这几个概念&#xff0c;特地向深圳模具光学抛光厂家毅顺光学进行了详细的咨询。据毅顺模具光学抛光厂家的师傅介绍&#xff0c;…

rabbitmq取消自动重连_掌握Rabbitmq几个重要概念,从一条消息说起

RabbitMQ 是功能强大的开源消息代理。根据官网称&#xff1a;也是使用量最广泛的消息队列。就像他的口号“Messaging that just works”&#xff0c;开箱即用使用简单&#xff0c;支持多种消息传输协议(AMQP、STOMP、MQTT)。一个应用程序或者服务如何使用RabbitMq呢&#xff1f…

icmp回复报文_ICMP协议全解析

1、ICMP简介ICMP全名为(INTERNET CONTROL MESSAGE PROTOCOL)网络控制消息协议。ICMP的协议号为1。ICMP报文就像是IP报文的小弟&#xff0c;总顶着IP报文的名头出来混。因为ICMP报文是在IP报文内部的&#xff0c;如图&#xff1a;ICMP属于TCP/IP协议族&#xff0c;工作在网络层(…

maven 打包时缺少文件_jenkins+maven应如何动态打包不同配置文件

概述很多时候我们在用jenkins打包的时候&#xff0c;肯定有很多环境&#xff0c;例如生产环境、测试环境、开发环境等等&#xff0c;那么jenkinsmaven应如何动态打包不同配置文件呢&#xff1f;下面简单介绍下怎么设置和其中的配置是怎么关联起来的。1、pom.xml配置先看下pom.x…

为空 判断_Form表单submit提交时的非空判断

概要使用Form表单提交信息时&#xff0c;可能我们需要对输入的信息进行判断&#xff0c;如果没有输入内容或者全部输入空格则不能进行提交&#xff0c;从而达到简单的信息过滤&#xff0c;这里使用的是JS来进行判断。实例代码&#xff1a;# Form表单 <form class"form-…

tplink连接服务器失败_tplink路由器网络已连接但是上不了网怎么办?

问&#xff1a;本人家里用的tplink路由器&#xff0c;现在问题是电脑和手机都可以连接到tplink路由器网络&#xff0c;但是连接网络后却上不了网。请问大家这是什么原因造成的&#xff0c;我要怎么办&#xff1f;答&#xff1a;能够连接到tplink路由器的网络但上不了网&#xf…

Linux主要的常用命令(玩Linux的人士不得不学哦!)

Linux虽然是免费的&#xff0c;但它的确是一个非常优秀的操作系统&#xff0c;与MS&#xff0d;WINDOWS相比具有可靠、 稳定、速度快等优点,且拥有丰富的根据UNIX版本改进的强大功能。下面&#xff0c;作为Linux爱好者&#xff0c;让我们一起来学习Linux的一些主要命令&#xf…