• Python下划线中 _xx、__xx、__xx__ 的区别


    在Python中,一般情况下我们常见的变量大都属于公共变量,比如 xx = 13 中的 xx 就是一个公共变量,但有时候我们也会在一些Python代码中看到一些加下划线的变量/方法,比如 _xx__xx__xx__,我们今天就来学习下这几个的区别。

    1.前面有1个下划线 _xx

    如果在类中的变量/方法前面加 1 个下划线,那么这样的就称为保护变量/方法。

    class A:
        age1 = 10
        _age2 = 20
    
        def method_a1(self):
            print("类内部调用公共变量:{}".format(self.age1))
    
        def _method_a2(self):
            print("类内部调用保护变量:{}".format(self._age2))
    
    
    class B(A):  # B是A的子类
        def method_b(self):
            print("子类调用父类的公共变量:{}".format(self.age1))
            print("子类调用父类的保护变量:{}".format(self._age2))
    
    
    a = A()
    print(a._age2)  # 通过 实例对象.保护变量 调用
    print(A._age2)  # 通过 类对象.保护变量 调用
    
    b = B()
    b.method_b()
    b.method_a1()  # 子类的实例对象调用父类中的公共方法
    b._method_a2()  # 子类的实例对象调用父类中受保护的方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    执行结果如下:

    20
    20
    子类调用父类的公共变量:10
    子类调用父类的保护变量:20
    类内部调用公共变量:10
    类内部调用保护变量:20
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    从上面结果中可发现,当设置为保护变量后,我们在类内部和子类也是能够访问到这些变量的,总的来说和公共变量没有太大差别。我们设置为保护变量,一般是不希望其在类的外部被使用或直接访问。

    需要注意一点,保护变量不能通过 from module import * 方式导入,但这并不意味我们在外部就无法访问到保护变量了。

    • 如果是类内部的保护变量,我们可通过 实例对象.变量名 或 类名.变量名 进行调用
    • 如果是类外部的保护变量,我们可先通过 import 模块名 导入模块,然后再通过 模块名.变量名进行调用

    2.前面有2个下划线 __xx

    如果在类中的变量/方法前面加 2 个下划线,那么这样的就称为私有变量/方法,意味着只能在类内部能够访问到这些变量/方法,其子类也不能访问。

    然而在Python中,即使设置了私有变量/方法,如果我们真想要在外部访问,其实也是可以实现的,具体可以通过 _类名__私有变量/方法 来进行调用。

    '''
    学习中遇到问题没人解答?小编创建了一个Python学习交流群:711312441
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    class A:
        age1 = 10
        _age2 = 20
        __age3 = 30
    
        def method_a1(self):
            print("类内部调用公共变量:{}".format(self.age1))
    
        def _method_a2(self):
            print("类内部调用保护变量:{}".format(self._age2))
    
        def __method_a3(self):
            print("类内部调用私有变量:{}".format(self.__age3))
    
    
    class B(A):  # B是A的子类
        def method_b(self):
            print("子类调用父类的公共变量:{}".format(self.age1))
            print("子类调用父类的保护变量:{}".format(self._age2))
            # print("子类调用父类的私有变量:{}".format(self.__age3))  # 会报错,不能这样调用
            print("子类调用父类的私有变量:{}".format(self._A__age3))
    
    
    a = A()
    # print(a.__age3)  # 会报错,不能这样调用
    print(a._A__age3)  # 通过 实例对象._类名__私有变量 调用
    # print(A.__age3)  # 会报错,不能这样调用
    print(A._A__age3)  # 通过 类对象._类名__私有变量 调用
    
    b = B()
    b.method_b()
    b.method_a1()  # 子类的实例对象调用父类中的公共方法
    b._method_a2()  # 子类的实例对象调用父类中受保护的方法
    # b.__method_a3()  # 会报错,不能这样调用
    b._A__method_a3()  # 子类的实例对象调用父类中私有的方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    执行结果如下:

    30
    30
    子类调用父类的公共变量:10
    子类调用父类的保护变量:20
    子类调用父类的私有变量:30
    类内部调用公共变量:10
    类内部调用保护变量:20
    类内部调用私有变量:30
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    从上面可以看到,无论是保护变量还是私有变量,我们都可以在外部进行访问,Python中并不能真正控制变量/方法的访问权限。

    • 如果是类内部的私有变量,我们可通过 实例对象._类名__私有变量类名._类名__私有变量 进行调用
    • 如果是类外部的私有变量,我们可先通过 import 模块名 导入模块,然后再通过 模块名.__私有变量进行调用

    3.前后都有2个下划线 __xx__

    在Python中,类似 __xx__ __xx__() 这种前后都有 2 个下划线的变量或方法,通常是Python中内置的特殊变量属性或方法的标识,我们应尽量避免使用该方式来自定义变量或方法。
    在这里插入图片描述
    一般情况下,Python代码执行时会自动调用到这些内置属性或方法,比如当一个类对象实例化时,就会自动调用 __new__() __init__() 来完成构造和初始化。

  • 相关阅读:
    GPU架构变迁之AI系统视角:从费米到安培
    精美可视化:Python自动化生成漂亮的测试报告
    华为eNSP配置专题-NAT的配置
    Boost ASIO: Coroutines
    【打工日常】使用docker部署个人实时在线文档协助编辑器
    反向传播不香了?解读 Hinton 大佬的 Forward-Forward 算法
    Mysql主从复制
    【加油站会员管理小程序】01需求分析
    3.17 haas506 2.0开发教程-example - 低功耗模式 (2.2版本接口有更新)
    docker容器安装mysql
  • 原文地址:https://blog.csdn.net/qdPython/article/details/126143810