Python中的双下划线

Python中的双下划线

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

理解Python下划线

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

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

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

    下划线的几个用途如下:

  4. 在解释器中使用下划线

  5. 使用下划线来忽略值
  6. 在循环中使用下划线
  7. 使用下划线来分隔数字的位数
  8. 使用下划线进行命名

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

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

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

双下划线开头和结尾的语法如下所示:

语法:

__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__ 。最后,我们实例化了这个类并打印出变量的值。结果,这个程序运行并输出了所需的结果。然而,将魔法方法作为变量名是不好的实践,因为这将导致命名冲突。因此最好避免使用它们。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程