Python第八课:面向对象高级特性(权限控制、属性管理、魔法方法、多态与抽象类)
Python面向对象高级特性:权限控制、属性管理、魔法方法、多态与抽象类
在Python中,面向对象编程(OOP)提供了丰富的特性,使得代码更加模块化、可维护和可扩展。本文将深入探讨Python中的权限控制、属性访问控制(getter/setter)、魔法方法、object类、多态(标准多态与鸭子类型) 以及抽象类。通过理论讲解和代码实例,帮助您掌握这些高级特性。
一、权限控制:公有、受保护与私有属性
Python通过命名约定来区分属性的访问权限,但这并非严格的强制机制,而是一种约定。
| 权限类型 | 命名方式 | 访问范围 | 示例 |
|---|---|---|---|
| 公有属性 | name |
任何地方均可访问(类内部、子类、外部) | self.name |
| 受保护属性 | _age |
类内部和子类内部可访问(外部不建议访问) | self._age |
| 私有属性 | __idcard |
仅当前类内部可访问(外部不能直接访问) | self.__idcard |
代码示例:
class Person:
def __init__(self, name, age, idcard):
self.name = name # 公有属性
self._age = age # 受保护属性
self.__idcard = idcard # 私有属性
def speak(self):
# 类内部可以访问所有属性
print(f'我是{self.name}, 今年{self._age},身份证{self.__idcard}')
class Student(Person):
def hello(self):
# 子类内部可以访问公有和受保护属性,但不能访问私有属性
print(f'我是{self.name}, 今年{self._age},身份证{self.__idcard}') # 这里会报错
p1 = Person('张三', 19, '123456789012345')
p1.speak() # 输出:我是张三, 今年19,身份证123456789012345
# 外部访问
print(p1.name) # 公有属性 -> 正常
print(p1._age) # 受保护属性 -> 可访问但不建议
# print(p1.__idcard) # 私有属性 -> 报错 AttributeError
print(p1.__dict__) # 查看实例属性字典,私有属性被重命名为 _Person__idcard
注意:私有属性实际上是通过名称修饰(name mangling)实现的,会被重命名为 _类名__属性名,因此外部仍可通过 p1._Person__idcard 访问,但这违背了封装原则,不推荐使用。
二、属性访问控制:getter和setter
为了对属性的读取和修改进行控制(如添加校验逻辑),可以使用 @property 装饰器实现getter和setter。
代码示例:
python
class Person:
def __init__(self, name, age, idcard):
self.name = name
self._age = age
self.__idcard = idcard
# age属性的getter
@property
def age(self):
return self._age
# age属性的setter(添加范围校验)
@age.setter
def age(self, a):
if a <= 120:
self._age = a
else:
print('年龄不合适')
# idcard属性的getter(返回脱敏后的身份证)
@property
def idcard(self):
return self.__idcard[:6] + '*******' + self.__idcard[-4:]
# idcard属性的setter
@idcard.setter
def idcard(self, idcard):
self.__idcard = idcard
p1 = Person('李四', 18, '1402456789123')
print(p1.age) # 通过getter获取 -> 18
p1.age = 21 # 通过setter修改
print(p1.age) # 21
print(p1.idcard) # 脱敏显示 -> 140245*******9123
p1.idcard = '1402456789111'
print(p1.idcard) # 140245*******9111
使用getter/setter可以在属性访问时添加业务逻辑,而不需要修改外部调用代码。
三、魔法方法
魔法方法(特殊方法)是以双下划线开头和结尾的方法,由Python在特定情况下自动调用。以下是常用魔法方法的总结:
| 魔法方法 | 触发时机 | 示例用途 |
|---|---|---|
__init__ |
创建对象时 | 初始化属性 |
__str__ |
print(对象)或str(对象) |
返回用户友好的字符串 |
__len__ |
len(对象) |
返回对象的长度 |
__lt__ |
对象1 < 对象2 |
定义小于比较逻辑 |
__gt__ |
对象1 > 对象2 |
定义大于比较逻辑 |
__eq__ |
对象1 == 对象2 |
定义相等比较逻辑 |
__getattr__ |
访问不存在的属性时 | 提供默认行为或抛出提示 |
代码示例:
python
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f'{self.name} {self.age}'
def __len__(self):
return len(self.__dict__) # 返回实例属性个数
def __lt__(self, other):
return self.age < other.age
def __gt__(self, other):
return self.age > other.age
def __eq__(self, other):
return self.__dict__ == other.__dict__
def __getattr__(self, item):
print(f'你访问的 {item} 不存在')
p1 = Person('王五', 20)
p2 = Person('赵六', 19)
print(p1) # 调用 __str__ -> 王五 20
print(p1 > p2) # 调用 __gt__ -> True
print(p1 < p2) # 调用 __lt__ -> False
print(p1 == p2) # 调用 __eq__ -> False
print(p1.height) # 访问不存在的属性 -> 触发 __getattr__,输出提示
四、object类:所有类的最终祖先
在Python中,每个类都隐式或显式地继承自 object。object 是所有类的基类,提供了许多默认实现的方法。
python
import types
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
print(issubclass(Person, object)) # True
print(issubclass(int, object)) # True
print(isinstance(Person(), object)) # True
# 查看 object 类的所有成员
for key in object.__dict__:
print(key)
所有内置类型(int、str、list等)也都是 object 的子类,因此Python中任何对象都是 object 的实例。
五、多态
多态允许不同的对象调用同一个方法,表现出不同的行为。Python支持两种多态形式:标准多态(继承关系中的方法重写)和鸭子类型多态(不关注类型,只关注行为)。
5.1 标准多态
python
class Animal:
def speak(self):
print('动物正在发出声音')
class Dog(Animal):
def speak(self):
print('汪汪汪')
class Cat(Animal):
def speak(self):
print('喵喵喵')
def make_sound(animal: Animal):
animal.speak()
a1 = Animal()
a2 = Dog()
make_sound(a1) # 动物正在发出声音
make_sound(a2) # 汪汪汪
5.2 鸭子类型多态
鸭子类型不关心对象的具体类型,只关心它是否有某个方法或属性。“如果它走起来像鸭子,叫起来像鸭子,那么它就是鸭子。”
python
class Pig:
def speak(self):
print('哼哼哼')
def make_sound(animal):
# 不限制类型,只要能调用 speak() 方法即可
animal.speak()
p = Pig()
make_sound(p) # 哼哼哼
只要传入的对象有 speak() 方法,就能正常工作,这就是鸭子类型的灵活性。
六、抽象类
抽象类用于定义规范,不能被实例化,通常作为父类让子类继承,并强制子类实现抽象方法。Python中通过 abc 模块实现。
| 关键元素 | 作用 |
|---|---|
ABC |
抽象类的基类 |
@abstractmethod |
装饰器,标记抽象方法,子类必须实现 |
代码示例:
python
from abc import ABC, abstractmethod
class MustRun(ABC):
@abstractmethod
def run(self):
"""子类必须实现 run 方法"""
pass
# m = MustRun() # 抽象类不能实例化,会报错
class Person(MustRun):
def __init__(self, name, age):
self.name = name
self.age = age
def run(self):
print(f'{self.name} 正在跑步,年龄 {self.age}')
p = Person('小明', 18)
p.run() # 小明 正在跑步,年龄 18
如果子类没有实现抽象方法,则实例化时会抛出 TypeError。
七、总结
本文详细介绍了Python面向对象的高级特性:
-
权限控制:通过命名约定实现公有、受保护、私有属性,保障封装性。
-
属性访问控制:使用
@property和setter对属性进行精细控制。 -
魔法方法:借助特殊方法让对象支持内置操作(字符串表示、比较、长度等)。
-
object类:所有类的根,提供基础功能。
-
多态:标准多态利用继承重写,鸭子类型强调行为而非类型。
-
抽象类:通过
ABC和@abstractmethod定义接口规范。
更多推荐


所有评论(0)