Python专家编程系列: 5. 下划线在命名中的约定(Underscores in Python)
作者: quantgalaxy@outlook.com
blog: https://blog.csdn.net/quant_galaxy
欢迎交流
在各种python编码规范中,都对命名规则做了很详细的约定。
但是下划线和变量名称的组合,在python中都有特定的含义。
这些含义有些是一种认为约定,有些是python解释器严格执行的准则。
有必要掌握这些约定,来写出专业的代码。
后面我们就针对这5种和下划线组合相关的变量约定,来详细说明。
根据 PEP8,变量名称中的单个前导下划线仅供内部使用。
举例:
class Single:
def __init__(self):
self.a = 1
self._b = 2
实际访问方式:
>>> obj = Single()
>>> obj.a
1
>>> obj._b
2
从上面的输出中可以看出,单前下划线可以从类外部访问。
因此此处单前下划线的含义是按照惯例,而不是由 Python 解释器强制执行。
再看一个文件变量命名的例子:
# file1.py
a = 1
_b = 2
# file2.py
from file1 import *
print(a)
print(_b)
Output:
python3 file_2.py
1
Traceback (most recent call last):
File "/test/file_2.py", line 6, in <module>
print(_b)
^^
NameError: name '_b' is not defined
在 file1.py 中定义了一个公共变量和一个私有变量,并尝试使用通配符导入访问file2.py中的两个变量。
此通配符导入不包括私有导入,这就是为什么在尝试访问单前下划线变量时引发异常的原因。除了变量以外,函数命名也是一样的规则。
所以这里它是由Python解释器强制执行的。
总结:
在PEP-8的说明中,单末尾下划线用于避免与 Python 关键字冲突。
看下面这个例子:
list = [1, 2, 3]
t = (5, 6, 7)
# Coverting tuple to list using list() constructor
t1 = list(t)
# TypeError: 'list' object is not callable
这个例子报错,是因为变量名覆盖了list关键字的名称。
我们可以用结尾单下划线来避免和语言的关键字冲突:
list_ = [1, 2, 3]
t = (5, 6, 7)
# Coverting tuple to list using list() constructor
t1 = list(t)
print (t1)
# [5, 6, 7]
总结:
作者: quantgalaxy@outlook.com
blog: https://blog.csdn.net/quant_galaxy
欢迎交流
使用带有变量的双前导下划线不是一种约定,它对 Python 解释器具有特定的含义。
Python 会对带有双前导下划线的变量进行名称重整,以避免主类与其子类之间的名称冲突。
根据PEP-8中的说明,解释器会做如下改变:
为了更好地理解,让我们看以下示例:
class Double:
def __init__(self):
self.a = 1
self.__b = 2
>>> double = Double()
>>> dir(double)
['_Double__b', ..., 'a']
>>> double.a
1
>>> double.__b
AttributeError: 'Double' object has no attribute '__b'
>>> double._Double__b
2
从上面的输出中,可以看到 self.a 没有改变并且行为方式相同。
但是__b为了避免名称与子类发生冲突而Double__id。
因此,双前导下划线由 Python 解释器强制执行。
再看两个例子,先看类的成员变量使用双下划线前缀的例子:
class Student:
def __init__(self,name,rollno):
self.name=name
self.__rollno=rollno
def __repr__(self):
return "{},{}".format(self.name,self.rollno)
s = Student("Karthi",12)
print (s.name)
# Unable to access attributes having leading double underscore.
print (s.__rollno)
# AttributeError: 'Student' object has no attribute '__rollno'
# Name Mangling - have to use class extension with variable name
print (s._Student__rollno)
# 12
下面是类的方法命名使用双下划线前缀的例子:
class A:
def __getmethod(self):
print ("Inside Class A")
class B(A):
def __getmethod(self):
print ("Inside Class B")
b = B()
# Accessing __getmethod() in Class A using Name Mangling
b._A__getmethod()
# Inside Class A
# Accessing __getmethod() in Class B using Name Mangling
b._B__getmethod()
# Inside Class B
通过上面两个例子可以看出,双下划线开头的变量名称和方法名称,都被改写了。
总结:
Python 中的特殊方法以双前导和双尾随下划线命名。
它们在Python中被称为magic methods / dunder methods。
Python保留了有双前导和双末尾下划线的名称,用于特殊用途。
比如:__init,__str,__repr,__len。
这些神奇的方法在Python中具有特殊的意义。
最好避免在自己的程序中使用以双下划线(“dunders”)开头和结尾的名称,以避免与将来Python语言的变化产生冲突。
我们可以使用 dir() 方法来查看一个类中所有的魔术方法:
class Student:
def __init__(self, name, rollno):
self.name = name
self.rollno = rollno
def __repr__(self):
return "{},{}".format(self.name, self.rollno)
s = Student("karthi", 12)
print(s)
# karthi, 12
print (dir(Student))
'''
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_
'''
总结:
>>> 10 + 20
>>> _
30
# Single underscore used in for loop
for _ in range(5):
print ("Python")
# Python
# Python
# Python
# Python
# Python
# Iterating through list
colors=["red", "blue", "green"]
for _ in colors:
print (_)
# red
# blue
# green
# tuple unpacking
t = ("red", "green", "blue")
# 忽略单个值
# ignoring value "green" while tuple unpacking
t1, _, t2 = t
print (t1) # red
print (t2) # blue
# ignoring multiple values in tuple unpacking
tt = (1, 2, 3, 4, 5, 6)
# 忽略一组值
# ignoring all values except first and last element in tuple.
t3, *_, t4 = tt
print(t3)
print(t4)
# grouping decimal numbers by _
a = 10_000_000
print(a) # 10000000
总结:
作者: quantgalaxy@outlook.com
blog: https://blog.csdn.net/quant_galaxy
欢迎交流
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。