您的位置:

Python 中的双下划线

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

理解 Python 下划线

字符下划线(_) 在 Python 中并不简单。有许多语言只在 snake 中使用下划线来命名函数和变量;然而,Python 有一个更重要的用途。很可能,我们大多数人都熟悉以下语法:

  1. 为 _ in 范围(20)
  2. init(自我)
  3. _ = 10

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

下划线(_)有以下几种用法:

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

然而,我们将只讨论双下划线的命名约定。

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

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

因此,让我们开始吧。

理解双前导下划线

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

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

语法:


__var

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

名称 Mangling: 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() ,并使用初始化函数声明了一些值。然后,我们使用我的对象实例化了这个类。最后,我们打印了对象的目录。

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

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

变量自我。_ 第二个也出现在列表中,没有任何改动。

然而,我们可以观察到变量自身的一些变化。 第三。

如果我们观察属性列表,我们会注意到一个名为 _mySample__third 的属性。这是名字邙岭的情况。恰好避免了子类中变量的覆盖。

Let us understand the working of overriding using another example, where we have created another class that inherits the functionalities of the mySample class.

示例:


# 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() ,并使用初始化函数来声明一些变量。然后,我们为我的示例()类定义了一个子类,其中我们使用了 super() 函数从父类继承变量并覆盖它们。最后,我们已经实例化了子类并打印了覆盖变量的值。

结果,前两个变量的消息被成功打印;但是,程序在“ third”变量的情况下引发了异常。这是因为混淆这个名字改变了我的目标。 third to 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

说明:

在上面的代码片段中,我们可以观察到我们使用了" 另一个类 _ 第三个"变量而不是" 第三个"变量来访问变量的值。

借助类中的方法,我们可以访问双前导下划线变量。让我们考虑一个基于这个功能的例子。

例: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' 

说明:

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

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

例: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 这样的编程语言中,我们会发现以双下划线开头和结尾的各种名称。这些命名约定被称为魔法方法或邓德方法。

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

语法:


__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 。最后,我们已经实例化了这个类并打印了变量值。因此,该程序可以工作并产生所需的输出。然而,使用魔法方法作为变量的名称并不是一个好的做法,因为这会导致我们发生冲突。因此,最好远离他们。