当我们使用Python面向对象编程时,封装就是隐藏了类的内部细节,不让外部代码随意修改类的属性和方法,让对象的使用更加安全和方便。接下来,我将详细讲解Python面向对象中的封装。
封装的基本原则
在Python面向对象中,封装主要体现在以下几个方面:
- 属性和方法的访问权限控制
- 使用属性访问器来访问对象的属性
- 将对象的复杂实现细节隐藏起来
封装的基本原则是:对外提供公共接口,而不关心接口的内部实现。这样可以确保类的修改不会影响外部代码的使用。在Python中,通过使用_
和__
前缀来控制类成员的访问权限,下面我们来详细讲解一下这些内容。
属性和方法的访问权限控制
在Python中,我们可以使用public
、protected
和private
属性来控制成员的访问权限。其中,public
属性的成员可以被任何外部代码访问;protected
属性的成员只能被子类和同一模块中的代码访问;private
属性的成员只能在类的内部被访问。
Python中使用下划线(_)来实现属性的控制。
- 使用一个下划线前缀的成员,表示这个成员属性和方法是保护的(protected),外部不应该访问到。
- 使用两个下划线前缀的成员,表示该成员是私有的(private),只有类内部可以访问,外部代码无法直接访问。
示例1:使用下划线前缀实现属性的保护(protected)
class Person:
def __init__(self, name, age):
self._name = name # 带下划线的名字表示受保护的属性
self._age = age # 带下划线的名字表示受保护的属性
def _show_info(self): # 带下划线的名字表示受保护的方法
print(f"姓名:{self._name},年龄:{self._age}")
class Student(Person):
def __init__(self, name, age, grade):
super().__init__(name, age)
self.grade = grade
def show_info(self):
self._show_info() # 通过受保护的方法访问父类的属性
print(f"年级:{self.grade}")
s = Student("小明", 18, "初一")
s.show_info()
输出结果为:
姓名:小明,年龄:18
年级:初一
示例2:使用双下划线前缀实现属性的封装(private)
class Person:
def __init__(self, name, age):
self.__name = name # 使用双下划线实现属性的私有化
self.__age = age # 使用双下划线实现属性的私有化
def __show_info(self): # 使用双下划线实现方法的私有化
print(f"姓名:{self.__name},年龄:{self.__age}")
class Student(Person):
def __init__(self, name, age, grade):
super().__init__(name, age)
self.grade = grade
def show_info(self):
self.__show_info() # 不能直接访问父类的私有方法
s = Student("小明", 18, "初一")
s.show_info()
这时运行代码会发现报错:
AttributeError: 'Student' object has no attribute '__show_info'
原因是在Python中,使用双下划线前缀(__)声明的成员,会自动转换为_类名__成员名
的格式,从而实现了私有成员的访问限制。修改show_info()
方法为_Person__show_info()
即可实现。
使用属性访问器
Python中属性的封装不止限于访问权限控制,还可以使用属性访问器来实现。
属性访问器可分为getter和setter两种,getter用于获取属性的值,而setter用于设置属性的值。属性访问器将属性的访问方式封装成一个函数,使其更方便灵活的使用。
示例3:使用属性访问器实现身份证号的封装
class Student:
def __init__(self, name, age, id_card):
self.name = name
self.age = age
self.__id_card = id_card # 使用双下划线实现身份证号的私有化
@property
def id_card(self): # getter方法
return self.__id_card
@id_card.setter
def id_card(self, value): # setter方法
if len(value) != 18:
raise ValueError("身份证号必须为18位")
self.__id_card = value
s = Student("小明", 18, "123456789012345678")
print(s.id_card) # 通过getter获取身份证号
s.id_card = "123456789012345678" # 通过setter设置身份证号
print(s.id_card)
输出结果为:
123456789012345678
123456789012345678
隐藏对象的复杂实现细节
在面向对象设计中,一个好的类不仅需要具备良好的封装性,同时还需要隐藏具体的实现细节,使类的使用者只需要关心类提供的功能就可以了,而无需关心其具体的内部实现。实现的方法可以使用大量的细节实现,但充分利用私有属性和方法能够提供类的一个好的外部接口为使用者隐藏细节的方式。
示例4:使用双下划线前缀实现购物车数量的封装
class ShoppingCart:
def __init__(self):
self.__items = [] # 使用双下划线实现购物车数量的私有化
def add_item(self, item):
self.__items.append(item)
def remove_item(self, item):
self.__items.remove(item)
def get_item_count(self):
return len(self.__items)
s = ShoppingCart()
for i in range(5):
s.add_item("item" + str(i))
print(s.get_item_count()) # 只能通过类的方法访问私有属性
s.__items = [] # 无法直接修改私有属性
print(s.get_item_count())
输出结果为:
5
5
在此示例中,ShoppingCart
类使用双下划线私有化__items
属性,只能通过类的方法进行访问,同时使用了add_item
和remove_item
方法来操作购物车内的商品。这样,类的使用者只需要关注商品数目的添加、移除和获取,而无需关心其内部的具体实现细节。
总结
Python中面向对象编程中的封装是保护类的内部实现,不让外部代码随意修改类的属性和方法,让对象的使用更加安全和方便。在Python中,使用下划线和双下划线前缀来控制成员的访问权限,同时使用属性访问器来获取和设置属性的值。此外,还可以使用私有属性和方法来隐藏类的内部实现细节。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python面向对象中的封装详情 - Python技术站