在线运行和编辑此教程中的代码
运行代码2. 忽略值
下划线(_)也常用于忽略某些值。如果在解包时不打算使用某些元素,只需把它们赋给下划线(_)。
“忽略”的意思是把值赋给特殊变量下划线(_),表示我们后续代码不会使用它。
示例如下:
## ignoring a value
a, _, b = (1, 2, 3) # a = 1, b = 3
print(a, b)
## ignoring multiple values
## *(variable) used to assign multiple value to a variable as list while unpacking
## it's called "Extended Unpacking", only available in Python 3.x
a, *_, b = (7, 6, 5, 4, 3, 2, 1)
print(a, b)
1 3
7 1
3. 在循环中的用法
在循环中您也可以把下划线(_)当作变量使用。看下面的例子:
## lopping ten times using _
for _ in range(5):
print(_)
## iterating over a list using _
## you can use _ same as a variable
languages = ["Python", "JS", "PHP", "Java"]
for _ in languages:
print(_)
_ = 5
while _ < 10:
print(_, end = ' ') # default value of 'end' id '\n' in python. we're changing it to space
_ += 1
0
1
2
3
4
Python
JS
PHP
Java
5 6 7 8 9
4. 数字分组
当数字很长时,您可以用下划线按需分组,以便更易读。
例如:million = 1_000_000
此外,也可以用下划线(_)分隔二进制、八进制或十六进制数字的部分。
例如:binary = 0b_0010,octa = 0o_64,hexa = 0x_23_ab
运行以上示例查看结果。
## different number systems
## you can also check whether they are correct or not by coverting them into integer using "int" method
million = 1_000_000
binary = 0b_0010
octa = 0o_64
hexa = 0x_23_ab
print(million)
print(binary)
print(octa)
print(hexa)
1000000
2
52
9131
5. 使用下划线(_)进行命名
下划线(_)可用于变量、函数、类等的命名:
- 单前导下划线:_variable
- 单结尾下划线:variable_
- 双前导下划线:__variable
- 双前后下划线:__variable__
5.1. _single_pre_underscore
_name
单前导下划线用于表示内部使用。多数情况下我们正是因此而不去使用或访问它。
请看示例:
class Test:
def __init__(self):
self.name = "datacamp"
self._num = 7
obj = Test()
print(obj.name)
print(obj._num)
datacamp
7
单前导下划线并不会阻止您访问带有单前导下划线的变量。
但是,单前导下划线会影响从模块中导入的名称。
让我们在my_funtions文件中写下如下代码。
## filename:- my_functions.py
def func():
return "datacamp"
def _private_func():
return 7
现在,如果您从my_functions.py中导入所有方法和名称,Python不会导入以单前导下划线开头的名称。
>>> from my_functions import *
>>> func()
'datacamp'
>>> _private_func()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_private_func' is not defined
通过以常规方式导入模块可以避免上述错误。
>>> import my_functions
>>> my_functions.func()
'datacamp'
>>> my_functions._private_func()
7
单前导下划线仅用于表示内部使用。
5.2 single_postunderscore
name_
有时如果您想将Python 关键字用作变量、函数或类名,可以采用这种约定。
在您想用的名称末尾加一个下划线,即可避免与Python 关键字冲突。
来看示例:
>>> def function(class):
File "<stdin>", line 1
def function(class):
^
SyntaxError: invalid syntax
>>> def function(class_):
... pass
...
>>>
单结尾下划线用于当您的命名与Python 关键字冲突时,在变量名末尾添加下划线以避免冲突。
5.3. 双前导下划线
__name
双前导下划线用于名称改写(name mangling)。
双前导下划线会让Python解释器重写子类中的属性名,以避免命名冲突。
- 名称改写:Python解释器会以一种方式改写变量名,使其在类被继承时更不容易发生冲突。
看一个示例:
class Sample():
def __init__(self):
self.a = 1
self._b = 2
self.__c = 3
obj1 = Sample()
dir(obj1)
['_Sample__c',
'__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'_b',
'a']
上述代码会返回该类对象的所有属性。我们来看看变量在属性列表中的表现。
self.a 直接原样出现。
self._b 也原样出现。正如前文所述,它只是用于内部约定。
-
列表中有 self.__c 吗?
- 如果仔细看属性列表,会发现一个名为 _Sample__c 的属性。这就是名称改写,用于避免子类中对该变量的覆盖发生冲突。
我们通过继承 Sample类再创建一个类,看看覆盖时会发生什么。
class SecondClass(Sample):
def __init__(self):
super().__init__()
self.a = "overridden"
self._b = "overridden"
self.__c = "overridden"
obj2 = SecondClass()
print(obj2.a)
print(obj2._b)
print(obj2.__c)
overridden
overridden
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-2-4bf6884fbd34> in <module>()
9 print(obj2.a)
10 print(obj2._b)
---> 11 print(obj2.__c)
AttributeError: 'SecondClass' object has no attribute '__c'
这里再次体现了名称改写:它把 obj2.__c 改为 _SecondClass__c。现在用改写后的属性名来打印它。
print(obj2._SecondClass__c)
overridden
看,成功了。您也可以通过 _Sample__c 访问之前创建的变量。如下:
print(obj1._Sample__c)
3
在类的方法中也可以访问双前导下划线变量。看示例:
class SimpleClass:
def __init__(self):
self.__datacamp = "Excellent"
def get_datacamp(self):
return self.__datacamp
obj = SimpleClass()
print(obj.get_datacamp()) ## it prints the "Excellent" which is a __var
print(obj.__datacamp) ## here, we get an error as mentioned before. It changes the name of the variable
Excellent
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-5-8006c0a9b061> in <module>()
9 obj = SimpleClass()
10 print(obj.get_datacamp()) ## it prints the "Excellent" which is a __var
---> 11 print(obj.__datacamp) ## here, we get an error as mentioned before. It changes the name of the variable
AttributeError: 'SimpleClass' object has no attribute '__datacamp'
您也可以把双前导下划线用于方法名。示例如下:
class SimpleClass:
def __datacamp(self):
return "datacamp"
def call_datacamp(self):
return self.__datacamp()
obj = SimpleClass()
print(obj.call_datacamp()) ## same as above it returns the Dobule pre underscore method
print(obj.__datacamp()) ## we get an error here
datacamp
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-1-cd8ce2e83589> in <module>()
9 obj = SimpleClass()
10 print(obj.call_datacamp()) ## same as above it returns the Dobule pre underscore method
---> 11 print(obj.__datacamp()) ## we get an error here
AttributeError: 'SimpleClass' object has no attribute '__datacamp'
我们再用另一种方式看名称改写。先创建一个名为 _SimpleClass__name 的变量,然后尝试用双前导下划线的名字来访问它。
示例如下:
_SimpleClass__name = "datacamp"
class SimpleClass:
def return_name(self):
return __name
obj = SimpleClass()
print(obj.return_name()) ## it prints the __name variable
datacamp
理解这个概念了吗?如果还没有,建议再读一遍。
5.4. 双前后下划线
__name__
在Python中,您会看到很多以双下划线开头并结尾的名称。它们被称为魔术方法(magic methods)或dunder 方法。
class Sample():
def __init__(self):
self.__num__ = 7
obj = Sample()
obj.__num__
7
如果把这类名称用作您的变量名,可能会引发冲突。因此,最好避免使用它们。
结语
恭喜您!坚持看完了。这可能是Python里最乏味的概念之一,但在处理复杂代码时非常有用。
像我这样的大多数人第一次读并不一定能完全理解。所以别着急,如果第一次没看懂,就再读一遍。如果您对本文有任何疑问,欢迎在评论区提出。
如果您是Python初学者,建议先学习这门课程,然后再回过头来阅读本文,会更容易全面掌握。
参考资料:
许多Python 开发者并不了解 下划线(_)在Python中的用法。善用它能帮助您更高效地编写Python代码。
下划线(_)在Python中是一个很特殊的字符。
如果您是Python程序员,应该对下面的语法很熟悉:
for _ in range(100)
__init__(self)
在不同的场景下,它有一些特殊含义。我们一起来看一看。
您会发现下划线(_)大致有六种用法。了解这些之后,您也可以在合适的情境下灵活使用下划线(_)。
1. 在解释器中的用法
Python会自动把解释器中上一条表达式的值保存到名为“_”的特殊变量里。如果需要,您也可以把这个值再赋给其他变量。
它也可以像普通变量一样使用。看示例: