欢迎来到赛兔子家园

Python封装底层实现原理详解

事实上,Python 封装特性的实现纯属“投机取巧”,之所以类对象无法直接调用以双下划线开头命名的类属性和类方法,是因为其底层实现时,Python 偷偷改变了它们的名称。
前面章节中,我们定义了一个 PLanguage 类,定义如下:
class PLanguage:
    def set_name(self, name):
        if len(name) < 3:
            raise ValueError('名称长度必须大于3!')
        self.__name = name

    def get_name(self):
        return self.__name

    # 为 name 配置 setter 和 getter 方法
    name = property(get_name, set_name)

    def set_add(self, add):
        if add.startswith("http://"):
            self.__add = add
        else:
            raise ValueError('地址必须以 http:// 开头')

    def get_add(self):
        return self.__add

    # 为 add 配置 setter 和 getter 方法
    add = property(get_add, set_add)

    # 定义个私有方法
    def __display(self):
        print(self.__name, self.__add)


clang = PLanguage()
# 调用私有display()方法
clang.__display()
注意,在这个类中,有一个 __display() 方法,由于其是私有方法,且该类没有提供任何调用该方法的“接口”,因此在目前看来,此方法根本无法在类外部调用。也就是说,如下调用 __display() 方法是不可行的:
运行导致如下错误:
clang.__display()
AttributeError: 'PLanguage' object has no attribute '__display'
那么,是不是类似 display() 这种的私有方法,真的没有方法调用吗?如果你深入了解 Python 封装机制的底层实现原理,就可以调用它
事实上,对于以双下划线开头命名的类属性或类方法,Python 在底层实现时,将它们的名称都偷偷改成了 "_类名__属性(方法)名" 的格式。
就以 PLanguage 类中的 __display() 为例,Python 在底层将其方法名偷偷改成了“_PLanguage__display()”。例如,在 PLanguage 类的基础上,执行如下代码:
clang = PLanguage()
clang.name = "赛兔子"
clang.add = "http://www.cnblogs.com/qingchengzi"
# 直接调用隐藏的display()方法
clang._PLanguage__display()

输出结果:

赛兔子 http://www.cnblogs.com/qingchengzi

不仅如此,那些原本我们认为是私有的类属性(例如 __name 和 __add),其底层的名称也改成了“_类名__属性名”的这种格式。例如:

clang = PLanguage()
clang.name = "赛兔子"
clang.add = "http://www.cnblogs.com/qingchengzi"
# 直接调用name和add私有属性
print(clang._PLanguage__name,clang._PLanguage__add)

运行结果:

赛兔子 http://www.cnblogs.com/qingchengzi

总结

Python 类中所有的属性和方法,都是公有(public)属性,如果希望 Python 底层修改类属性或者类方法的名称,以此将它们隐藏起来,只需将它们的名称前添加双下划线(“__”)即可。

 

posted on 2024-08-21 10:44  赛兔子  阅读(80)  评论(0)    收藏  举报

导航