zoukankan      html  css  js  c++  java
  • Python 下划线


    • 单前导下划线:_var
    • 单末尾下划线:var_
    • 双前导下划线:__var
    • 双前导和末尾下划线:__var__
    • 单下划线:_

    文章结尾有”速查表“。


    一、单前导下划线_var

    以单下划线开头的变量或方法理论上仅供内部使用,执行时不会强制执行

    class Test:
        def __init__(self):
            self.zhangsan = 11
            self._lisi = 22
    

    访问 foo_bar属性:

    t = Test()
    print(t.zhangsan)
    print(t._lisi)
    

    输出:

    11
    22
    

    单前导下划线没有阻止访问属性的值。



    单前导下划线会影响从模块中导入名称的方式。(除非模块定义了覆盖此行为的__all__列表)

    # age.py
    
    def zhangsan():
        return 11
    
    def _lisi():
        return 22
    

    使用通配符从模块导入所有名称:

    # test.py
    
    from age import *
    print(zhangsan())
    print(_lisi())
    

    输出:

    11
    NameError: name '_lisi' is not defined
    

    应避免通配符导入,因为导入哪些名称会不清楚。坚持常规导入。

    import age
    print(age.zhangsan())
    print(age._lisi())
    

    输出:

    11
    22
    


    二、单末尾下划线var_

    解决与关键字的命名冲突。

    def zhangsan(name, class):
        pass
    
    def zhangsan(name, class_):
        pass
    

    输出:

    SyntaxError: invalid syntax
    


    三、双前导下划线__var

    双前导下划线会使 Python 重写属性名称,为防止变量的属性在子类中被重写

    这也叫名称修饰。

    class Test:
        def __init__(self):
            self.zhangsan = 11
            self._lisi = 22
            self.__wangwu = 33
    
    t = Test()
    print(dir(t))   # 查看对象属性
    

    输出:

    ['_Test__wangwu', '__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__', '_lisi', 'zhangsan']
    

    从属性列表看出:

    self.zhangsanself._lisi变量的属性为zhangsan_lisi

    self.__wangwu属性为_Test__wangwu



    继承Test类:

    class Test:
        def __init__(self):
            self.zhangsan = 11
            self._lisi = 22
            self.__wangwu = 33
    
    class ExtendedTest(Test):
        def __init__(self):
            super().__init__()
            self.zhangsan = 111
            self._lisi = 222
            self.__wangwu = 333
    
    t = Test()
    t2 = ExtendedTest()
    print(t2.zhangsan)
    print(t2._lisi)
    print(t2.__wangwu)
    

    输出:

    111
    222
    AttributeError: 'ExtendedTest' object has no attribute '__wangwu'
    


    名称修饰被再次触发。这个对象没有__wangwu属性。而是_ExtendedTest__wangwu属性。

    print(dir(t2))
    

    输出:

    ['_ExtendedTest__wangwu', '_Test__wangwu', '__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__',
     '_lisi', 'zhangsan']
    

    _Test__wangwu属性还在:

    print(t._Test__wangwu)
    # 33
    


    双前导下划线名称修饰对程序员完全透明。

    class Name:
        def __init__(self):
            self.__name = 'zhangsan'
    
        def get_name(self):
            return self.__name
    
    print(Name().get_name())
    print(Name().__name)
    

    输出:

    zhangsan
    
    AttributeError: 'Name' object has no attribute '__name'
    


    名称修饰也适用于方法名称。

    其实,名称修饰会影响一个类中所有以两个下划线开头的名称。

    class People:
        def __age(self):
            return 44
    
        def call_it(self):
            return self.__age()
    
    print(People().__age())
    print(People().call_it())
    

    输出:

    AttributeError: 'People' object has no attribute '__age'
        
    44
    


    又一个令人惊讶的名称修饰的例子:

    _PeopleGlobal__age = 55
    
    class PeopleGlobal:
        def test(self):
            return __age
    
    print(PeopleGlobal().test())
    # 55
    

    声明一个全局变量_PeopleGlobal__age。然后在PeopleGlobal类中访问变量。

    由于名称修饰,能在test()方法内,以__age引用全局变量。Python 自动将__age扩展为_PeopleGlobal__age,因为他以两个下划线开头。

    这表明名称修饰不是专门与类属性关联的。它适用于类中所有以两个下划线开头的名称。



    四、双前导和双末尾下划线__var__

    同时以双下划线开始和结束,不会应用于名称修饰。即不会被 Python 修改。

    但用于特殊用途。比如:__init__是构造函数。__call__可以使一个对象被调用。

    最好避免使用以双下划线开头和结尾的名称,防止冲突。



    五、单下划线_

    表示变量是临时或无关紧要的。

    for _ in range(6):
        print('Hello, world!')
    

    也可用于拆分表达式中:

    # 只对颜色、里程感兴趣
    car = ('red', 'auto', 12, 3812.6)
    color, _, _, mile = car
    print(color, mile)
    

    _是交互式解释器的一个特殊变量,表示最近一个表达式的结果。

    >>> 20+3
    23
    >>> 20-3
    17
    >>> _
    17
    
    >>> list()
    []
    >>> _.append(1)
    >>> _.append(2)
    >>> _.append(3)
    >>> _
    [1, 2, 3]
    


    六、总结

    模式 含义
    _var 命名约定,理论上仅供内部使用。但不会强制执行,只作为对程序员的提示。
    var_ 避免与 Python 关键字命名冲突。
    __var 在类中触发 “名称修饰”。由 Python 强制执行。
    __var__ Python 定义的特殊方法。
    _ 临时、无关紧要的变量。
    在交互式解释器中,表示最近一个表达式的结果。

  • 相关阅读:
    Scala之eq,equals,==的区别
    Spark Streaming流计算特点及代码案例
    刷题50—水壶问题
    刷题49(力扣3道题)
    刷题48——最长回文串
    刷题47——矩形重叠
    刷题46——拼写单词
    刷题45(力扣两道题)
    刷题44——岛屿的最大面积
    刷题43——最长上升子序列
  • 原文地址:https://www.cnblogs.com/keye/p/15711769.html
Copyright © 2011-2022 走看看