简述Python中"_"的使用常识

来源:互联网 发布:有哪些软件管家 编辑:程序博客网 时间:2024/06/04 20:02

0. 背景

Python里面的下划线“_”使用频率明显比其他主流语言要多的多,而且在Python中,它也有自己独到的用处。本文主要简述:下划线在python中的使用常识。

1. 单下划线-将名称封装到类中

如果想将类中的“私有”数据封装到类的实例上,但是又需要考虑到Python缺乏对属性的访问控制问题。与其依赖语言特性来封装数据,Python程序员们更期望通过特定的命名规则来表达出对数据和方法的用途。

第一个规则是任何以单下划线(_)开头的名字应该总是被认为只属于内部实现。

比如:

class A:    def __init__(self):        self._internal = 0  # 前缀加入"_",是类中的一个“内部(internal)”属性        self.public = 1     # 类中一个“公开(public)”属性    def public_method(slef):        '''        一个public方法        '''        pass    def _internal_method(self):        '''        一个内部(internal)方法        '''        pass

Python本身并不会阻止其他人访问内部名称。但是如果有人这么做了,则被认为是粗鲁的,而且可能导致产生出脆弱不堪的代码。应该要提到的是,以下划线为前缀的标识也可用于模块名称和模块级的函数。比如,如果见到有模块名以下划线前缀(例如,_socket),那么它就属于内部实现。同样的,模块级函数比如sys._getframe()使用起来也要格外小心。

2. 双下划线-名称重整(name mangling)

我们应该在类定义中也见到过以双下滑线(__)为前缀的名称。例如:

class B:    def __init__(self):        self.__private = 0  # 名称重整后为:_B__private    def __private_method(self):        '''        名称重整后为:_B__private_method        '''        pass    def public_method(self):        self.__private_method()

以双下划线为前缀的名称会导致出现名称重整(name mangling)的行为。这样的属性不能通过继承而覆盖。

具体来说就是上面这个类中的私有属性会被分别重命名为_B__private_B__private_method。其实类似这样的名称重整的目的就是为了继承——这样的属性不能通过继承而覆盖。

class C(B):    def __init(self):        super().__init()        self.__private = 1 # 此语句不会覆盖B.__private    ''' 此方法不会覆盖 B.__private_method(),    因为名称重整后会成名称重整后为:_B__private_method,    而此函数重整后为: _C__private_method    '''    def __private_method(self):        pass

这里,私有名称__private__private_method会被重命名为_C__ptvate_C_private_method,这和基类B中的重整名称不同。

“私有”属性存在两种不同的命名规则(单下划线和双下划线),这一事实引出了一个显而易见的问题:应该使用那种风格?

对于大部分代码而言,我们应该让非公有名称以单下划线开头。但是,如果我们知道代码中会涉及子类化处理,而且有些内部属性应该对子类进行隐藏,那么此时就应该使用双下划线开头。

3. 后缀单下划线-避免关键字冲突

此外还应该指出的是,有时候可能想定义一个变量,但是名称可能会和保留字产生冲突。基于此,应该在名称最后加上一个单下划线以示区别。比如:

lambda_ = 2.0 # 添加后缀下划线_ ,以避免与关键字"lambda"冲突

这里不采用以下划线前缀的原因是避免在使用意图上发生混淆,如果采用下划线开头的形式,那么可能会被解释为私有变量,而不是被认为是避免关键冲突。

1 0
原创粉丝点击