目录
专栏列表
- Python教程(一):环境搭建及PyCharm安装
- Python 教程(二):语法与数据结构
- Python 教程(三):字符串特性大全
- Python 教程(四):Python运算符合集
- Python 教程(五):理解条件语句和循环结构
- Python 教程(六):函数式编程
- Python 教程(七):match...case 模式匹配
- Python 教程(八):高级特性【高逼格代码】
- Python 教程(九):内置模块与第三方模块
- Python教程(十):面向对象编程(OOP)
- Python教程(十一):单元测试与异常捕获
正文开始
,如果觉得文章对您有帮助,请帮我三连+订阅,谢谢
💖💖💖
前言
在学习了Python的基本面向对象编程(OOP)概念之后,本篇文章将深入探讨Python中的高级OOP特性。这些特性包括类的内部变量、特殊方法(Magic Methods)、装饰器、枚举类以及元类。通过对这些高级特性的介绍和实例演示,帮助你更好地掌握Python的面向对象编程。
变量命名规则说明:
单下划线、双下划线、头尾双下划线
-
_foo
: 以单下划线开头的表示的是protected 类型的变量
,即保护类型只能允许其本身与子类进行访问,不能用于from module import *
-
__foo__
: 定义的是特殊方法,一般是系统定义名字 ,类似__init__()
之类的。 -
__foo
: 双下划线的表示的是私有类型(private)的变量
, 只能是允许这个类本身进行访问了。
一、类的内部变量和特殊方法
1.1 内部变量
内部变量 (Internal Variables)是指以双下划线开头(__
)的变量,它们主要用于防止变量在子类中被意外覆盖。这种命名方式会触发Python的名称改写机制(Name Mangling),使变量名变得难以在类外部访问。
__init__
的特殊方法(构造方法),在生成对象时调用,这个我们已经在前文介绍过了__del__
: 析构函数,释放对象时使用__repr__
: 打印,转换__setitem__
: 按照索引赋值__getitem__
: 按照索引获取值__len__
: 获得长度__cmp__
: 比较运算__call__
: 函数调用__add__
: 加运算__sub__
: 减运算__mul__
: 乘运算__truediv__
: 除运算__mod__
: 求余运算__pow__
: 乘方__str__
:定义对象的字符串表示,print
函数调用时使用。
示例
py
class Container:
def __init__(self, *args):
self.container = list(args) # 初始化容器,接受可变数量的参数
def __del__(self):
print(f"对象 {id(self)} 正在被销毁。")
def __repr__(self):
return f"Container({self.container})"
def __setitem__(self, key, value):
self.container[key] = value # 索引赋值
def __getitem__(self, key):
return self.container[key] # 索引获取
def __len__(self):
return len(self.container) # 获取容器长度
def __cmp__(self, other):
if not isinstance(other, Container):
return NotImplemented
return (self.container > other.container) - (self.container < other.container)
def __call__(self, *args):
print(f"Container 对象被调用,参数为:{args}")
def __add__(self, other):
if isinstance(other, Container):
return Container(*(self.container + other.container)) # * 是用作解包操作,将list中的参数一个一个的传递,而不是传递一个list
return NotImplemented
def __sub__(self, other):
if isinstance(other, Container):
return Container(*(self.container[:-1] if len(self.container) >= len(other.container) else self.container))
return NotImplemented
def __mul__(self, other):
if isinstance(other, int):
return Container(*(self.container * other))
return NotImplemented
def __truediv__(self, other):
if isinstance(other, int) and other != 0:
return Container(*(x / other for x in self.container))
return NotImplemented
def __mod__(self, other):
if isinstance(other, int):
return Container(*(x % other for x in self.container))
return NotImplemented
def __pow__(self, power):
return Container(*(x ** power for x in self.container))
def __str__(self):
return f"Container 对象: {self.container}"
# 测试代码
if __name__ == "__main__":
c1 = Container(1, 2, 3)
c2 = Container(4, 5)
print(f"c1: {c1}") # 使用 __str__
print(f"c2: {c2}")
c1[1] = 20 # 使用 __setitem__
print(f"c1 修改后: {c1}")
print(c1[1]) # 使用 __getitem__
print(len(c1)) # 使用 __len__
c3 = c1 + c2 # 使用 __add__
print(f"c1 + c2: {c3}")
c4 = c1 - c2 # 使用 __sub__
print(f"c1 - c2: {c4}")
c5 = c1 * 2 # 使用 __mul__
print(f"c1 * 2: {c5}")
c6 = c1 / 2 # 使用 __truediv__
print(f"c1 / 2: {c6}")
c7 = c1 % 3 # 使用 __mod__
print(f"c1 % 3: {c7}")
c8 = c1 ** 2 # 使用 __pow__
print(f"c1 ** 2: {c8}")
c1(123) # 使用 __call__
测试结果:
1.2 __slots__
__slots__
是一个特殊的类属性,用于控制类实例的动态属性的添加。默认情况下,Python的类是基于字典的,这意味着每个实例可以动态地添加任意数量的属性。但是,使用__slots__
可以限制实例可以拥有的属性,只允许在__slots__
中明确定义的属性。
使用__slots__
有以下几个主要好处:
- 节省内存:通过限制属性的数量,可以减少内存的使用,因为不需要为每个实例创建一个字典来存储属性。
- 提高性能:访问预定义的属性比动态属性访问更快,因为预定义属性可以直接通过索引访问。
- 避免意外添加属性 :使用
__slots__
可以确保类的实例不会意外地添加未定义的属性。
未使用__slots__
python
class Person:
__init(self,*args)__:
pass
# 创建 Student 类的实例
p = Person()
p.name = '子羽'
print(p.name)
使用__slots__
在定义类时,你可以在类定义的顶部添加一个特殊的__slots__
属性,其值为一个包含允许属性名的元组或列表。
python
class Student:
__slots__ = ('name', 'age', 'grade') # 只允许 name, age, grade 三个属性
# 创建 Student 类的实例
s = Student()
s.name = 'Alice' # 正确,因为 'name' 在 __slots__ 中
s.age = 20 # 正确,因为 'age' 在 __slots__ 中
s.grade = 'A' # 正确,因为 'grade' 在 __slots__ 中
# 尝试添加未在 __slots__ 中定义的属性
s.address = '123 Main St' # 抛出 AttributeError
在上面的例子中,尝试给s
添加一个不在__slots__
列表中的属性address
将会抛出AttributeError
。
二、装饰器
2.1 函数装饰器
装饰器是一个高阶函数,用于在不改变原函数代码的情况下,动态地增加功能。装饰器通常用于日志记录、性能测试、事务处理等。
示例
python
def my_decorator(func):
def wrapper(world):
print("日志记录开始.")
func(world)
print("日志记录结束")
return wrapper
@my_decorator
def say_hello(world):
print(f"Hello {world}!")
say_hello('子羽')
2.2 @property
@property
是 Python 中的一个装饰器,用于将一个方法转变为属性访问的形式。这使得你可以使用点符号(.
)来访问一个方法,就像访问一个普通的属性一样。
@property
通常用于当你想要属性值的获取有特定的逻辑处理时,例如,当你需要在获取属性值之前进行验证或计算。
示例
使用 @property
非常简单,你只需要在方法前加上 @property
装饰器,然后在该方法内部定义获取属性值的逻辑。下面是一个简单的例子:
python
class Circle:
def __init__(self, radius):
self._radius = radius # 私有属性,用来存储圆的半径
@property
def radius(self):
"""获取圆的半径"""
return self._radius
@radius.setter
def radius(self, value):
"""设置圆的半径,可以包含验证逻辑"""
if value < 0:
raise ValueError("半径不能为负数")
self._radius = value
# 创建 Circle 类的实例
circle = Circle(5)
# 使用 @property 获取属性
print(circle.radius) # 输出: 5
# 使用 @setter 设置属性
circle.radius = 10
print(circle.radius) # 输出: 10
# 尝试设置非法的半径值
circle.radius = -1 # 抛出 ValueError
三、枚举类
3.1 枚举类概述
枚举(Enum)是一种特殊的类,用于表示一组相关的常量值。枚举类中的每个成员都是唯一的,可以使用名称或值进行访问。
3.2 枚举类定义
可以使用Python的 enum
模块定义枚举类。
示例
python
from enum import Enum, auto
class Color(Enum):
RED = auto() # 默认从 1 开始
GREEN = auto()
BLUE = auto()
YELLOW = 5
purple = 6
print(Color.RED) # 输出: Color.RED
print(Color.GREEN.name) # 输出: GREEN
print(Color.GREEN.value) # 输出: 2
print(Color.YELLOW.name) # 输出: YELLOW
print(Color.YELLOW.value) # 输出: 5
四、元类
4.1 什么是元类
元类 (Metaclass)是用于创建类的类。默认情况下,Python中的所有类都是由 type
元类创建的。通过自定义元类,可以改变类的创建行为。
4.2 自定义元类
自定义元类需要继承自 type
,并重写其方法,如 __new__
和 __init__
。
示例
python
class MyMeta(type):
def __new__(cls, name, bases, dct):
print(f"创建新类 :{name}")
return super().__new__(cls, name, bases, dct)
def __init__(cls, name, bases, dct):
print(f"初始化类: {name}")
super().__init__(name, bases, dct)
class MyClass(metaclass=MyMeta):
def __init__(self):
print("创建 Myclass 类的示例")
obj = MyClass()
结语
通过本篇文章,我们深入探讨了Python面向对象编程中的一些高级特性,包括类的内部变量、特殊方法、装饰器、枚举类和元类。这些高级特性能够帮助你编写更加灵活和强大的代码。如果你有任何疑问或想法,欢迎在评论区留言讨论。