在以下教程中,我们将讨论双下划线及其在Python编程语言中的用途。但在此之前,让我们简要讨论下划线的一些方面。

理解Python下划线

在Python中,字符下划线 (_) 不仅仅是一个简单的符号。有许多语言只使用下划线来命名函数和变量,采用蛇形命名法;然而,在Python中,它有更重要的用途。大多数人可能熟悉以下语法:

  1. for _ in range(20)
  2. init(self)
  3. _ = 10

下划线 (_) 字符在不同情况下传达不同的含义。

下划线 (_) 有多种用途,包括:

  1. 在解释器中使用下划线
  2. 使用下划线来忽略值
  3. 在循环中使用下划线
  4. 使用下划线来分隔数字的位数
  5. 用于命名的下划线

然而,我们只会讨论与双下划线一起使用的命名约定。

这些命名约定分为两种类型:

  1. 双前导下划线:__ var
  2. 双前导和尾随下划线: var

现在,让我们开始吧。

理解双前导下划线

双前导下划线 用于进行名称的修饰

双前导下划线的语法如下所示:

语法:

__var  

双前导下划线告诉Python解释器重写子类属性的名称,以避免命名冲突。

名称修饰: Python解释器以一种难以在类继承过程中混淆的方式更改变量的名称。

让我们通过一个基于此功能的示例来了解。

示例:1

# defining a class  
class mySample():  
    # using the __init__() function  
    def __init__(self):  
        self.first = 10  
        self._second = 15  
        self.__third = 20  
  
# instantiating the class  
myObj = mySample()  
# printing the directory of the object  
print(dir(myObj))  

输出:

 ['__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__',
'_mySample__third',
'_second',
'first']

解释:

在上面的代码段中,我们定义了一个名为 mySample() 的类,并使用初始化函数声明了一些值。然后,我们使用 myObj 对象实例化了类。最后,我们打印了对象的属性列表。

因此,上述代码块返回类对象的每个属性。现在,让我们观察属性列表中的变量。

变量 self.first 出现在列表中而没有进行任何更改。

变量 self._second 也出现在列表中而没有进行任何更改。

然而,在变量 self.__third 的情况下,我们可以观察到一些更改。

如果我们观察属性列表,将会注意到一个名为 _mySample__third 的属性。这就是名称修饰的情况。它发生是为了避免在子类中覆盖该变量。

让我们通过另一个示例来了解覆盖的工作原理,其中我们创建了另一个类,该类继承了 mySample 类的功能。

示例:

# defining a class  
class mySample():  
    # using the __init__() function  
    def __init__(self):  
        self.first = 10  
        self._second = 15  
        self.__third = 20  
# defining a child class  
class AnotherClass(mySample):  
    def __init__(self):  
        super().__init__()  
        self.first = "Variable Overridden"  
        self._second = "Variable Overridden"  
        self.__third = "Variable Overridden"  
# instantiating the child class  
myobj = AnotherClass()  
# printing the values of variables  
print(myobj.first)  
print(myobj._second)  
print(myobj.__third)  

输出:

 Variable Overridden
Variable Overridden
Traceback (most recent call last):
  File "D:\Python\ternarypy.py", line 24, in 
    print(myobj.__third)
AttributeError: 'AnotherClass' object has no attribute '__third'

解释:

在上面的代码段中,我们定义了一个名为 mySample() 的类,并使用初始化函数声明了一些变量。然后,我们为 mySample() 类定义了一个子类,使用 super() 函数从父类继承了变量并进行了覆盖。最后,我们实例化了子类,并打印了覆盖的变量的值。

结果是,前两个变量的消息成功打印出来;然而,在 "__third" 变量的情况下,程序引发了一个异常。这是因为名称修饰导致了将 myObj.__third 更改为 _AnotherClass__third

让我们考虑另一个示例,以便使用修改后的属性来打印该元素。

示例:2

# defining a class  
class mySample():  
    # using the __init__() function  
    def __init__(self):  
        self.first = 10  
        self._second = 15  
        self.__third = 20  
# defining a child class  
class AnotherClass(mySample):  
  
    def __init__(self):  
        super().__init__()  
        self.first = "Variable Overridden"  
        self._second = "Variable Overridden"  
        self.__third = "Variable Overridden"  
# instantiating the child class  
myobj = AnotherClass()  
# printing the value(s) of variable(s)  
print(myobj._AnotherClass__third)  

输出:

Variable Overridden

解释:

在上面的代码段中,我们可以看到我们使用 "_AnotherClass__third" 变量来访问变量的值,而不是使用 "__third" 变量。

我们可以使用类中的方法来访问双前导下划线变量。让我们考虑一个基于这个功能的示例。

示例:3

# defining the class  
class myClass:  
    # initializing function  
    def __init__(self):  
        self.__myVar = "Welcome"  
    # defining another method to return the variable  
    def get_Var(self):  
        return self.__myVar  
# instantiating the class  
myObj = myClass()  
# it returns the "Welcome" which is a __var  
print(myObj.get_Var())  
# here, an error is raised as stated before. It alters the variable's name  
print(myObj.__myVar)  

输出:

 Welcome
Traceback (most recent call last):
  File "D:\Python\ternarypy.py", line 15, in 
    print(myObj.__myVar)
AttributeError: 'myClass' object has no attribute '__myVar'

解释:

在上面的代码段中,我们定义了一个类,并使用初始化函数声明了一个变量。然后,我们定义了一个方法来返回变量的值。最后,我们实例化了该类,并使用两种方式打印变量的值。结果是,该程序在打印方法时返回了"Welcome"语句,但在打印其他方法时引发了异常,因为它更改了变量的名称。

我们还可以使用双前导下划线作为方法名称。让我们考虑一个基于这个功能的示例。

示例:4

# defining a class  
class myClass:  
    # defining a double-leading underscore function  
    def __myfunction(self):  
        return "Welcome"  
    # defining a function to call the above function  
    def call_function(self):  
        return self.__myfunction()  
# instantiating the class  
myObj = myClass()  
# printing the value within the function  
print(myObj.call_function())  
# raised an error  
print(myObj.__myfunction())  

输出:

 Welcome
Traceback (most recent call last):
  File "D:\Python\ternarypy.py", line 14, in 
    print(myObj.__myfunction())
AttributeError: 'myClass' object has no attribute '__myfunction'

解释:

在上面的代码段中,我们定义了一个函数,然后定义了一个双前导下划线函数。然后,我们定义了一个函数来调用从该函数返回的值,并为用户打印结果。

现在,让我们理解名称修饰的另一种方式。首先,我们将声明一个名为 _myClass__myVar 的变量,并尝试使用双前导下划线名称来访问该变量。

让我们考虑以下示例:

示例:5

# declaring a variable  
_myClass__myVar = "Welcome"  
# defining a class  
class myClass:  
    # defining a function to return the declared variable  
    def call_function(self):  
        return __myVar  
# instantiating the class  
myObj = myClass()  
# printing the value of the variable  
print(myObj.call_function())  

输出:

Welcome

解释:

在上面的代码段中,我们声明了一个变量并定义了一个类。然后,我们定义了一个函数来返回已声明变量的值。最后,我们实例化了该类并调用函数以打印该变量的值。

理解双前导和尾随下划线

在像Python这样的编程语言中,我们会发现许多以双下划线开头和结束的名称。这些命名约定称为魔术方法Dunder方法

双前导和尾随下划线的语法如下所示:

语法:

__var__  

让我们考虑一个基于魔术方法的示例。

示例:

# defining a class  
class myClass:  
    # using a magic method  
    def __init__(self):  
        # using a magic method as variable name  
        self.__myNum__ = 10  
# instantiating the class  
myObj = myClass()  
# printing the value of the variable  
print(myObj.__myNum__)  

输出:

10

解释:

在上面的代码段中,我们定义了一个类。我们在类中使用了一个魔术方法,即初始化函数 init()。然后,我们将变量命名为 num。最后,我们实例化了该类,并打印了变量的值。结果是,该程序可以正常运行并产生所需的输出。然而,使用魔术方法作为变量名不是一个好的实践,因为这会导致命名冲突。因此,最好避免使用它们。

标签: Tkinter教程, Tkinter安装, Tkinter库, Tkinter入门, Tkinter学习, Tkinter入门教程, Tkinter, Tkinter进阶, Tkinter指南, Tkinter学习指南, Tkinter进阶教程, Tkinter编程