Python __variable__ 或 __method__()的双下划线名称重整”(name mangling)理解

双下划线开头和结尾的名称(比如 __variable____method__())是 Python 中的特殊命名约定,通常被称为“双下划线名称重整”(name mangling)。它主要有两个方面的作用:名称修饰和限制访问。

  1. 名称修饰:

    在类定义中,双下划线名称重整用于防止子类意外覆盖父类的属性或方法。当一个类的属性或方法以双下划线开头但不以双下划线结尾时(例如 __variable__method()),Python 会将其重整为 _ClassName__variable_ClassName__method() 的形式。这样做的目的是在子类中防止意外地覆盖父类的属性或方法。

    例如:

class SuperClass:
    def __init__(self):
        self.public_attr = "Public Attribute"
        self.__private_attr = "Private Attribute"

    def __private_method(self):
        print("This is a private method.")

    def public_method(self):
        print("This is a public method.")
        self.__private_method()
        print(self.__private_attr)


class SubClass(SuperClass):
    def __init__(self):
        super().__init__()
        self.__private_attr = "Subclass Private Attribute"

    def __private_method(self):
        print("This is a subclass private method.")

    def use_functions(self):
        self.public_method()
        # 在子类中访问父类的私有属性和方法
        print(self._SuperClass__private_attr)
        self._SuperClass__private_method()
        print(self.__private_attr)
        self.__private_method()


# 创建子类实例
sub_instance = SubClass()
sub_instance.use_functions()

在这个示例中:

SuperClass 定义了一个公有属性 public_attr、一个私有属性 __private_attr 和两个方法 __private_method()public_method()

SubClass 继承自 SuperClass,并重新定义了 __private_attr__private_method()

在 SubClass 的 use_functions() 方法中,我们调用了父类的 public_method(),并尝试访问父类的私有属性和方法。

由于名称重整的原因,在子类中无法直接访问父类的 __private_attr__private_method()。但是,我们可以使用 _SuperClass__private_attr_SuperClass__private_method() 来访问它们。

运行这个代码,输出结果如下:

This is a public method.
This is a private method.
Private Attribute
Private Attribute
This is a private method.
Subclass Private Attribute
This is a subclass private method.
  1. 限制访问:

    双下划线名称重整也可用于模拟私有成员,即限制对属性和方法的直接访问。虽然在 Python 中没有严格的私有性,但是通过名称重整可以模拟私有成员,使其不容易被外部访问。

    class MyClass:
        def __init__(self):
            self.__private_var = 10
    
        def __private_method(self):
            print("This is a private method.")
    
    obj = MyClass()
    print(obj.__private_var)  # 会报错,无法直接访问私有变量
    obj.__private_method()  # 会报错,无法直接访问私有方法
    

    在这个例子中,直接访问 obj.__private_varobj.__private_method() 会抛出错误,因为它们被重整为 _MyClass__private_var_MyClass__private_method(),而不是直接的名称。

双下划线名称重整的使用有助于确保代码的健壮性和安全性,尤其在大型项目中。然而,应该注意不要滥用双下划线名称重整,因为它可能会导致代码难以理解和维护。

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

  • 对于大部分代码而言,我们应该让非公有名称以单下划线开头
  • 但是,如果我们知道代码中会涉及子类化处理,而且有些内部属性应该对子类进行隐藏,那么此时就应该使用双下划线开头
  • 此外还应该指出的是,有时候可能想定义一个变量,但是名称可能会和保留字产生冲突。基于此,应该在名称最后加上一个单下划线以示区别。比如:
lambda_= 2.0  # Trailing _ to avoid clash with lambda keyword

这里不采用以下划线开头的原因是避免在使用意图上发生混淆(例如,如果采用下划线开头的形式,那么可能会被解释为这么做是为了避免名称冲突,而不是作为私有数据的标志)。在名称尾部加一个单下划线就能解决这个问题

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值