前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python专家编程系列: 5. 下划线在命名中的约定(Underscores in Python)

Python专家编程系列: 5. 下划线在命名中的约定(Underscores in Python)

原创
作者头像
AIFEx
修改2023-10-06 11:28:36
1800
修改2023-10-06 11:28:36
举报
文章被收录于专栏:AIFEx的专栏AIFEx的专栏

0. 标题

Python专家编程系列: 5. 下划线在命名中的约定(Underscores in Python)

代码语言:txt
复制
作者: quantgalaxy@outlook.com   
blog: https://blog.csdn.net/quant_galaxy  
欢迎交流

1. 介绍

在各种python编码规范中,都对命名规则做了很详细的约定。

但是下划线和变量名称的组合,在python中都有特定的含义。

这些含义有些是一种认为约定,有些是python解释器严格执行的准则。

有必要掌握这些约定,来写出专业的代码。

2. 下划线和变量的组合类型

  • 单前下划线(Single Leading Underscore): _variable
  • 单末尾下划线(Single Trailing Underscore): variable_
  • 双前导下划线(Double Leading Underscore): __variable
  • 双前导和末尾下划线(Double Leading and a Double Trailing Underscore): __variable__
  • 单下划线(Only Single Underscore): _

后面我们就针对这5种和下划线组合相关的变量约定,来详细说明。

3. 规范详解

3.1 单前下划线(Single Leading Underscore): _variable

根据 PEP8,变量名称中的单个前导下划线仅供内部使用。

举例:

代码语言:python
复制
class Single:
    def __init__(self):
        self.a = 1
        self._b = 2

实际访问方式:

代码语言:shell
复制
>>> obj = Single()
>>> obj.a
1
>>> obj._b
2

从上面的输出中可以看出,单前下划线可以从类外部访问。

因此此处单前下划线的含义是按照惯例,而不是由 Python 解释器强制执行。

再看一个文件变量命名的例子:

代码语言:shell
复制
# file1.py
a = 1
_b = 2

# file2.py
from file1 import *

print(a)
print(_b)

Output:

代码语言:shell
复制
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解释器强制执行的。

总结:

  1. 单前下划线在类成员命名中,约定是在类内部可见。实际访问是不受限制的。
  2. 单前下划线的变量和函数,在py文件中的定义,被其它py文件导入时是不可见的,这是被Python解释器执行的。

3.2 单末尾下划线(Single Trailing Underscore): variable_

在PEP-8的说明中,单末尾下划线用于避免与 Python 关键字冲突。

看下面这个例子:

代码语言: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关键字的名称。

我们可以用结尾单下划线来避免和语言的关键字冲突:

代码语言:python
复制
list_ = [1, 2, 3]
t = (5, 6, 7)

# Coverting tuple to list using list() constructor
t1 = list(t)

print (t1)
# [5, 6, 7]

总结:

  1. 单末尾下划线用于避免与 Python 关键字冲突。
代码语言:txt
复制
作者: quantgalaxy@outlook.com   
blog: https://blog.csdn.net/quant_galaxy  
欢迎交流

3.3 双前导下划线(Double Leading Underscore): __variable

使用带有变量的双前导下划线不是一种约定,它对 Python 解释器具有特定的含义。

Python 会对带有双前导下划线的变量进行名称重整,以避免主类与其子类之间的名称冲突。

根据PEP-8中的说明,解释器会做如下改变:

  1. self.__methodname() 会被解释器重写为:self._className__methodname()
  2. self.__attributename 会被解释器重写为:self._classname__attributename

为了更好地理解,让我们看以下示例:

代码语言:python
复制
class Double:
    def __init__(self):
        self.a = 1
        self.__b = 2
代码语言:shell
复制
>>> 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 解释器强制执行。

再看两个例子,先看类的成员变量使用双下划线前缀的例子:

代码语言: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

下面是类的方法命名使用双下划线前缀的例子:

代码语言:python
复制
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

通过上面两个例子可以看出,双下划线开头的变量名称和方法名称,都被改写了。

总结:

  1. 双下划线前缀会导致Python解释器重写属性名称,以避免子类中的命名冲突。这也叫做名称修饰(name mangling)- 解释器更改变量的名称,以便在类被扩展的时候不容易产生冲突。
  2. 双下划线前缀定义的变量和方法,不会被子类的同名变量和方法所覆盖。(我们可以使用 @property 装饰器来封装和访问这个变量。)

3.4 双前导和末尾下划线(Double Leading and a Double Trailing Underscore): __variable__

Python 中的特殊方法以双前导和双尾随下划线命名。

它们在Python中被称为magic methods / dunder methods。

Python保留了有双前导和双末尾下划线的名称,用于特殊用途。

比如:__init,__str,__repr,__len

这些神奇的方法在Python中具有特殊的意义。

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

我们可以使用 dir() 方法来查看一个类中所有的魔术方法:

代码语言: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) 
# karthi, 12

print (dir(Student))
'''
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_
'''

总结:

  1. 双前导和末尾下划线用于Python中的特殊方法,属于语言保留的特性,尽量避免在程序中使用这样的变量和方法定义。

3.5 单下划线(Only Single Underscore): _

  1. 单下划线在python解释器(Python interactive command prompt)中,用来访问上一次执行的结果:
代码语言:shell
复制
>>> 10 + 20
>>> _
30
  1. 在python语句中,单下划线主要用来记录临时变量:
代码语言:python
复制
# 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
  1. 用于忽略返回类型为元组时的一些元素的值:
代码语言:txt
复制
# 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)
  1. 在整数、浮点数和复数文字中,下划线可用作数字分组的视觉分隔符。下划线没有任何语义意义,对字面量的解析就像没有下划线一样:
代码语言:python
复制
# grouping decimal numbers by _
a = 10_000_000
print(a) # 10000000

总结:

  1. 单下划线在python解释器(Python interactive command prompt)中,用来访问上一次执行的结果。
  2. 单下划线在在python语句中,主要用来记录临时变量。
  3. 单下划线用于忽略元组一些元素的值
  4. 单下划线可用作数字分组的视觉分隔符,在这种情况下,下划线没有任何语义意义

4. 参考资源

  1. PEP 515 – Underscores in Numeric Literals
  2. Private Variables
  3. PEP 8 – Style Guide for Python Code

5. 作者信息

代码语言:txt
复制
作者: quantgalaxy@outlook.com   
blog: https://blog.csdn.net/quant_galaxy  
欢迎交流

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0. 标题
  • 1. 介绍
  • 2. 下划线和变量的组合类型
  • 3. 规范详解
    • 3.1 单前下划线(Single Leading Underscore): _variable
      • 3.2 单末尾下划线(Single Trailing Underscore): variable_
        • 3.3 双前导下划线(Double Leading Underscore): __variable
          • 3.4 双前导和末尾下划线(Double Leading and a Double Trailing Underscore): __variable__
            • 3.5 单下划线(Only Single Underscore): _
            • 4. 参考资源
            • 5. 作者信息
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档