首页  >  文章  >  后端开发  >  探索 Python 中的名称修饰:它是什么以及它是如何工作的

探索 Python 中的名称修饰:它是什么以及它是如何工作的

Barbara Streisand
Barbara Streisand原创
2024-10-09 16:15:02270浏览

Exploring Name Mangling in Python: What It Is and How It Works

Python 以其简单性和可读性而闻名,但是当涉及到面向对象编程 (OOP) 时,有一些讨论较少的机制对于编写健壮的代码至关重要。其中一种机制是名称修改。本文将引导您了解名称修饰是什么、Python 使用它的原因以及它如何帮助防止复杂类层次结构中的名称冲突。

什么是名称修改

Python 允许子类覆盖类中的方法。但是,当子类无意中覆盖父类的属性或方法时,这有时会导致名称冲突。名称修改是 Python 用来避免这些冲突的一种机制,特别是对于那些应该是私有的属性。

Python 中的名称修改是解释器更改私有类属性的名称的功能,以最大限度地降低它们被错误访问和覆盖的风险。这在类属性中提供了一定程度的隐私,尽管没有严格执行。不过,这并不是严格执行。

技术定义

在 Python 中,任何具有两个前导下划线 (__) 且不超过一个尾随下划线的标识符都将进行名称修改。解释器通过在名称前添加类名来转换名称。

为什么 Python 使用名称重整

为了防止命名冲突,特别是在子类可能有自己的变量可能覆盖父类中的变量的情况下,Python 实现了名称修饰。名称修改解决了这个问题。

from datetime import datetime, timedelta
from time import time, sleep

class Machine:
    def __init__(self, id):
        self.id = id
        self._started = time()

    def uptime(self):
        return time() - self._started

class PetrolMachine(Machine):
    def __init__(self, id):
        super().__init__(id)
        self._started = datetime.now()

    def cost(self):
        duration = datetime.now() - self._started
        return duration/timedelta(seconds=60) *0.02

worked = PetrolMachine('12345')
sleep(0.123)
print(f"uptime : {worked.uptime():.2f}")

在此示例中,Machine 类使用 Python 的 time() 函数存储 ID 并记录开始时间。当您请求正常运行时间时,它会计算当前时间和开始时间之间的差值,该差值存储为浮点数。然而,子类 PetrolMachine 使用 datetime.now() 存储开始时间。当我们尝试计算正常运行时间时,程序会抛出错误,因为它期望 start_time 是浮点数,但它现在是日期时间对象。当子类属性无意中覆盖父类属性时,可能会发生这种命名冲突。名称修改有助于避免此问题。

名称修改如何工作

那么名称修改如何帮助解决这个问题呢?当类属性以两个下划线为前缀时,Python 在内部更改名称以包含类名作为前缀。以下是如何使用名称修改来修改 Machine 类以避免名称冲突:

我们可以通过对 Machine 类中的 __started 属性应用名称修改来解决该错误,如下所示:

from datetime import datetime, timedelta
from time import time, sleep

class Machine:
    def __init__(self, id):
        self.id = id
        self.__started = time()

    def uptime(self):
        return time() - self.__started  

class PetrolMachine(Machine):
    def __init__(self, id):
        super().__init__(id)
        self._started = datetime.now()

    def cost(self):
        duration = datetime.now() - self._started
        return duration/timedelta(seconds=60) *0.02


worked = PetrolMachine('12345')
sleep(0.123)
print(f"uptime : {worked.uptime():.2f}")

下面显示了表达名称修饰的简单方法。我有一个 ClassA 类,其中有一个 private_variable,其名称已损坏。

class MyClass:
    def __init__(self):
        self.__private_var = "I am private"

    def get_private_var(self):
        return self.__private_var

my_object = MyClass()
print(my_object.get_private_var())  # This works
print(my_object.__private_var)

第二个 print() 将引发 AttributeError,因为变量 __private_var 已被名称破坏。在内部,Python 已将名称更改为 _MyClass__private_var,使得从类外部访问变得更加困难。

访问损坏的名称

虽然 Python 的名称修饰是为了防止意外访问而设计的,但它并没有强制执行严格的隐私保护。您仍然可以使用完整的损坏名称来访问损坏的属性,但不鼓励这样做。它的工作原理如下: my_object._MyClass__private_var

print(my_object._MyClass__private_var)

Python 何时会损坏名称

我会通过一个简单的例子来解释它

class MyClass:
    def __init__(self):
        self._protected_var = "I'm protected"
        self.__private_var__ = "I'm not mangled"

在 Python 中,前导单下划线(例如 _protected_var)表示该属性是“受保护的”,不应直接从类外部访问。然而,Python 并不强制执行这一点。相反,带有两个前导下划线的名称(例如 __private_var)会被破坏,以防止意外覆盖。重要的是,两侧带有双下划线的名称(例如 __special__)不会被破坏,而是为特殊用例(例如魔术方法)保留。

Benefits and Limitations

Benefits

  • Helps prevent accidental overriding of class attributes in subclasses
  • Provides a lightweight mechanism for privacy without being too restrictive.

Limitations

  • It’s not truly private—other developers can still access the mangled name if they know how.
  • Can make debugging and reading code more complex if overused.

_ Despite these limitations, name mangling remains a useful tool in Python’s OOP toolkit. While it’s not a strict enforcement of privacy, it helps prevent naming conflicts and accidental attribute overriding. Understanding name mangling will enable you to write more robust, maintainable code, especially when working with complex class hierarchies. Give it a try in your projects, and share your experiences or questions in the comments below!_

以上是探索 Python 中的名称修饰:它是什么以及它是如何工作的的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn