Python中下划线在变量名和方法名中的含义

Python中下划线在变量名和方法名中的含义

Python 中有一些异于其它语言的特色,初学者特别是有过使用其它编程语言经验的初次接触可能会有些晕。如下划线( _)有哪些用处,现在聊聊这个话题。

单下划线和双下划线在Python变量名和方法名中的含义,有些仅仅是作为约定,用于提示开发人员;而另一些则对Python解释器有特殊含义。

在Python中,下划线 _ 在变量名和方法名中的使用有几种不同的情况,每种情况都有其特定的含义或约定:

  1. 单个前导下划线 _variable:
    这通常用来表示一个变量或方法是受保护的(protected),是内部使用的。按照约定,这意味着它不应该被外部直接访问。然而,这只是一个约定,并不会在Python解释器层面强制实施。

  2. 单个后置下划线 variable_:
    这通常用来避免命名冲突。Python有一些内置关键字,如果你的变量名需要和这些关键字相同,你可以在变量名后加一个下划线来避免冲突。

  3. 双前导下划线 __variable:
    这是一种名称修饰(name mangling)的方式。Python解释器对内部变量名进行变形,以避免在子类中被覆盖。变形的方式是在变量名前加上_ClassName,例如在MyClass类中,__variable会被变形为_MyClass__variable

  4. 双前导和双后置下划线 __variable__:
    这种命名方式是为了定义Python的特殊方法。它们有特定的意义,被Python解释器特殊对待。例如,__init__是类的构造器,__str__是当对象被转换为字符串时调用的方法等。

  5. 单个下划线 _:
    在交互式环境中,单个下划线通常用来表示最后表达式的结果。此外,它也被用作临时或不重要的变量名(例如,在循环中,当循环变量的值不重要时)。在国际化(i18n)和本地化(l10n)中,单个下划线通常用作翻译函数的别名。

这些约定并不是强制性的,但它们是Python社区广泛接受的编码实践,遵循这些约定可以使代码更加清晰和一致。

下面举例解读之。

前置单下划线

class Test:
    def __init__(self):
        self.foo = 11
        self._bar = 23
#实例化这个类并尝试访问在__init__构造函数中定义的foo和_bar属性,会发生什么情况?
t = Test()
print(t.foo) #输出:11
print(t._bar) #输出:23

可以看到,_bar前面的单下划线并没有阻止我们“进入”这个类访问变量的值。

这是因为Python中的前置单下划线只是一个公认的约定,至少在涉及变量名和方法名时是这样的。但是前置下划线会影响从模块中导入名称的方式。

后置单下划线

有时,某个变量最合适的名称已被Python语言中的关键字占用。因此,诸如class或def的名称不能用作Python中的变量名。在这种情况下,可以追加一个下划线来绕过命名冲突:

def make_object(name, class_):

     pass

用一个后置单下划线来避免与Python关键字的命名冲突是一个约定。PEP 8定义并解释了这个约定。

前置双下划线

以双下划线开头的Python类属性(变量和方法)不是约定的意义,双下划线前缀会让Python解释器重写属性名称,以避免子类中的命名冲突,这也称为名称改写(name mangling)

class Test:
    def __init__(self):
        self.foo = 11
        self._bar = 23
        self.__baz = 42
#实例化这个类并用内置的dir()函数来看看这个对象的属性:
t = Test()
print(dir(t))
print(t._Test__baz) # 在外部访问__baz变量名时,应使用 _类名__变量名即_Test__baz

运行之,输出:

['_Test__baz', '__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__', '_bar', 'foo']

42

现在,看一看这个带有对象属性的列表,并留意原始变量名foo、_bar和_ bazi有何差异:

self.foo变量没有改动,在属性列表中显示为foo。

self._bar也一样,在类中显示为_bar。前面说了,在这种情况下前置下划线仅仅是一个约定,是对程序员的一个提示。

对于self.__baz,在该列表中找不到__baz这个变量。仔细观察就会看到,这个对象上有一个名为_Test__baz的属性。这是Python解释器应用名称改写之后的名称,是为了防止子类覆盖这些变量。

对于前置双下划线的变量,在外部访问该变量名时,应使用 _类名__变量名;直接访问__变量名是不存在的。

用双下划线修饰方法亦如此——名称改写也适用于方法名。

用双下划线修饰属性或者方法,会出发名称修饰,即在外部访问时,该方法名或变量名会变为_类名__变量名;直接访问__变量名是不存在的。例子:

class A(object):
    def __init__(self):
        self.__private=10
    def __private_method(self):
        return 'ABC'
t=A()
#下句输出:10,若用print(t.__private)报错:AttributeError: 'A' object has no attribute '__private'
print(t._A__private)
#下句输出:ABC,若用print(t.__private_method())报错:AttributeError: 'A' object has no attribute '__private_method'
print(t._A__private_method()) 

前后都有双下划线

由双下划线包围的变量,则不会发生名称改写,由双下划线包围的方法通常被称为魔法方法(特殊方法)。

前后由双下划线包围的变量不受Python解释器的影响:

class B(object):
    def __init__(self):
        self.__private__=10
t=B()
print(t.__private__) #输出:10

就命名约定而言,最好避免在自己的程序中使用以双下划线开头和结尾的名称,因为Python语言用于定义的特殊方法。

单下划线本身

_ 在Python REPLs【见附录】如IDLE Shell中是一个特殊变量(可以表示一个临时值),它表示解释器计算的最后一个表达式的结果。

例子:

一种习惯约定,在python程序文件中表示某个变量是临时的或无关紧要的,免去想一个具体的变量名称,一般不会在后面再次用到该名称。如:

for _ in range(3):
    print('Hello, World.')  #输出3行 Hello, World.


car = ('red', 'auto', 3812.4)
color, _,  mileage = car
print(_) # 输出 auto


 

参考;Python中下划线的5种含义

附录:REPL

是 4 个单词的首字母组:Read Eval Print Loop。
Read,读取用户输入
Eval, 执行输入内容(Eval 是 Evaluate 的简写)
Print,打印输出结果
Loop, 不断循环以上步骤
我们经常用的命令行或 Shell 就是这种模式。不过一般提起 REPL 的时候,都是特指编程语言的交互式运行环境。

  • 9
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习&实践爱好者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值