Skip to content

封装

封装

封装是面向对象编程中三大特征之一,指的是将数据和操作数据的方法打包在一起,形成一个类或对象。

封装的目的是隐藏对象的内部实现细节,提供一个安全且易于使用的接口,使得对象之间的交互更加简单和可靠。

封装主要包括以下几个方面的内容:

  1. 数据隐藏:通过将对象的数据属性设置为私有或受保护的,防止外部直接访问和修改对象的数据。这样可以确保对象的数据在被操作时不会被意外篡改或破坏。

  2. 方法封装:将对象对自身数据的操作封装在方法中,只通过方法来访问和修改对象的数据。这样可以确保对对象的操作符合预期,避免了外部错误地修改对象的数据。

  3. 接口定义:通过定义公共接口,将对象的功能暴露给外部使用者。使用者只需关心如何使用接口提供的方法,而不需要了解内部实现细节。这样可以提高代码的可读性和可维护性,同时也能够实现代码的模块化和复用。

封装的优势包括:

  1. 数据安全性:封装隐藏了对象的内部实现细节,保护了数据的完整性和安全性。外部无法直接访问或修改对象的数据,必须通过规定的方法进行操作,减少了意外错误的发生。

  2. 代码模块化:封装将对象的数据和操作打包在一起,实现了代码的模块化。不同的对象可以独立开发和测试,降低了代码的耦合性,增加了系统的可维护性和扩展性。

  3. 简化接口:封装将对象的功能通过公共接口暴露给外部,隐藏了内部实现细节。外部使用者只需了解接口的使用方法,而无需关心具体的实现。这降低了外部使用者的使用难度,也提高了代码的可读性和易用性。

访问控制

在 Python 中并没有像 Java,C++ 一样,提供了 public, protected, private 这样的访问控制修饰符,Python 通过一种称为 名称改写 的方式,实现其它语言中访问控制修饰符的作用。

但是要注意的是,在 Python 中 名称改写 只是一种约定,并没有真正的实现私有的作用,在 Python 中只要想访问,所有的数据都可以拿到,获取方法在这里不讨论。

无下划线前缀(公有权限)

Python 中默认定义的属性和方法,都是公有的方法。无论是在类外,还是在派生的子类中,都可以进行访问,类似其它语言中的 public 修饰符的作用。

class A(object):
    def __init__(self):
        # 公有属性
        self.a = 10


    # 公有方法
    def show(self):
        # 在类中使用公有属性
        print(f"A: {self.a}")

obj = A()
# 在类外使用公有属性
print(obj.a)

# 在类外使用公有方法
obj.show()

_ 单下划线前缀(保护权限)

Python 在类中使用 单下划线前缀 实现其它语言中 protected 保护权限的功能,在属性或方法(包括类属性和类方法,作用相同)前添加一个单下划线,该属性或方法,在当前类中可以访问,在类外理论上不可访问(使用时不提示,但写出来程序可以运行,但有警告),在通过继承派生的子类中可以访问(继承在后面讲解)。

class A(object):
    def __init__(self):
        # 公有属性
        self.a = 10
        # 保护属性
        self._b = 20

    # 公有方法
    def show(self):
        # 在类中使用公有属性
        print(f"A: {self.a}")
        # 在类中使用保护属性
        print(f"B: {self._b}")
        # 在类中使用保护权限的方法
        self._display()

    # 保护权限的方法
    def _display(self):
        print(f"B: {self._b}")


obj = A()
# 在类外使用公有属性
print(obj.a)
# 在类外无法使用保护仅限的属性(不建议这样使用)
print(obj._b)
# print(obj.__c)
# 在类外使用公有方法
obj.show()
# 在类外无法使用保护权限的方法(不建议这样使用)
obj._display()

__ 双下划线前缀(私有属性)

Python 在类中使用 双下划线前缀 实现其它语言中 private 私有权限的功能。

在属性或方法(包括类属性和类方法,作用相同)前添加一个双下划线,该属性或方法,只能在当前类中可以访问,在类外任何位置不可访问(只是理论上不可访问,通过某些方式,还是可以在类外访问,不建议这样使用)。

class A(object):
    def __init__(self):
        # 公有属性
        self.a = 10
        # 保护属性
        self._b = 20
        # 私有属性
        self.__c = 30

    # 公有方法
    def show(self):
        # 在类中使用公有属性
        print(f"A: {self.a}")
        # 在类中使用保护属性
        print(f"B: {self._b}")
        # 在类中使用私有属性
        print(f"C: {self.__c}")
        # 在类中使用保护权限的方法
        self._display()
        # 在类中使用私有方法
        self.__info()


    # 保护权限的方法
    def _display(self):
        print(f"B: {self._b}")

    # 私有权限的方法
    def __info(self):
        # 在类中使用私有属性
        print(self.__c)
obj = A()
# 在类外使用公有属性
print(obj.a)
# 在类外无法使用保护仅限的属性(不建议这样使用)
print(obj._b)
# 在类外使用私有属性,访问失败
# print(obj.__c)
# 在类外使用公有方法
obj.show()
# 在类外无法使用保护权限的方法(不建议这样使用)
obj._display()
# 在类外访问私有方法,访问失败
# obj.__info()

双下划线前缀与后缀

在 Python 中还有一种同时具有前后双下划线的变量或方法,这些方法是 Python 中的魔法属性或魔法方法,这些属性或方法名被赋予了特殊的作用。

比如:

  • 初始化方法 __init__()
  • 对象描述方法 __str__()
  • 迭代器方法 __iter__()
  • 迭代器方法 __next__()

这些都是魔法方法。