Python :数据模型

news/2025/3/14 9:38:51/

一. 什么是数据模型?

Python数据模型是Python对象系统的抽象,通过一组特殊方法​(如__init____len__等)和协议​(如迭代协议、上下文管理协议),定义了对象如何与语言的内置功能(如len()for循环等)交互。

核心思想

  • 统一性:所有对象(如列表、字典、自定义类)的行为都通过相同的特殊方法实现。
  • 灵活性:通过实现特殊方法,可以让自定义对象支持内置操作(如+in、切片等)。

例子

python">import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])
class FrenchDeck:ranks = [str(n) for n in range(2, 11)] + list('JQKA')suits = 'spades diamonds clubs hearts'.split()def __init__(self):self._cards = [Card(rank, suit) for suit in self.suitsfor rank in self.ranks]def __len__(self):return len(self._cards)def __getitem__(self, position):return self._cards[position]
解释
  1. 模块导入

    import collections

    导入了 Python 标准库中的 collections 模块。

  2. 命名元组定义:Card

    Card = collections.namedtuple('Card', ['rank', 'suit'])

    使用 namedtuple 创建了一个名为 Card 的简单类,表示扑克牌的一张牌。每个 Card 对象有两个属性:

    • rank:表示牌的点数(如 '2''J''A' 等)。
    • suit:表示牌的花色(如 'spades''diamonds' 等)。
  3. 类定义:FrenchDeck

    • 定义了一个名为 FrenchDeck 的类,表示一副标准的 52 张扑克牌。
    • 类属性:

      ranks = [str(n) for n in range(2, 11)] + list('JQKA') suits = 'spades diamonds clubs hearts'.split()

      • ranks:表示牌的所有点数,包括数字牌('2' 到 '10')和字母牌('J''Q''K''A')。
      • suits:表示牌的所有花色('spades' 黑桃、'diamonds' 方片、'clubs' 梅花、'hearts' 红心)。
    • 构造函数 __init__

      def __init__(self): self._cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks]

      初始化时创建了一副完整的扑克牌,存储在 _cards 列表中。通过列表推导式生成所有可能的牌组合。
    • 方法 __len__

      def __len__(self): return len(self._cards)

      实现了特殊方法 __len__,使得可以通过 len(deck) 获取扑克牌的数量。
    • 方法 __getitem__

      def __getitem__(self, position): return self._cards[position]

      实现了特殊方法 __getitem__,使得可以通过索引访问扑克牌,例如 deck[0]

常用特殊方法

方法对应操作
__init__对象初始化
__repr__ / __str__字符串表示
__len__len(obj)
__getitem__obj[key](支持索引和切片)
__iter__for x in obj(迭代)
__enter__ / __exit__with语句(上下文管理)

迭代协议

实现__iter____next__方法,让对象支持for循环:

python">class CountDown:def __init__(self, start):self.current = startdef __iter__(self):return selfdef __next__(self):if self.current <= 0:raise StopIterationelse:self.current -= 1return self.current + 1for num in CountDown(3):print(num)  # 输出: 3 2 1

 

 解释
  1. 类定义:CountDown

    • 定义了一个名为 CountDown 的类,用于实现倒计时功能。

    • 构造函数 __init__

      def __init__(self, start): self.current = start

      初始化时接收一个参数 start,表示倒计时的起始值,并将其赋值给实例属性 self.current

    • 方法 __iter__

      def __iter__(self): return self

      实现了可迭代协议,使得该类的实例可以作为迭代器使用。返回自身(self)。

    • 方法 __next__

      def __next__(self): if self.current <= 0: raise StopIteration else: self.current -= 1 return self.current + 1

      实现了迭代器协议中的 __next__ 方法:

      • 如果当前值 self.current 小于或等于 0,则抛出 StopIteration 异常,表示迭代结束。
      • 否则,将 self.current 减 1,并返回减 1 前的值(即当前值)。
  2. 使用场景

    • 该类可以通过 for 循环或手动调用 next() 方法进行倒计时。
    • 示例:
      python">countdown = CountDown(5)
      for value in countdown:print(value)
      输出结果:

      5 4 3 2 1

上下文管理协议

实现__enter____exit__方法,支持with语句:

python">class Timer:def __enter__(self):self.start = time.time()return selfdef __exit__(self, exc_type, exc_val, exc_tb):self.end = time.time()print(f"耗时: {self.end - self.start:.2f}秒")with Timer():time.sleep(1)  # 输出: 耗时: 1.00秒
 解释
  1. 类定义:Timer

    • 定义了一个名为 Timer 的类,用于测量代码块的执行时间。

    • 方法 __enter__

      def __enter__(self): self.start = time.time() return self

      • 实现了上下文管理协议中的 __enter__ 方法。
      • 在进入 with 语句块时,记录当前时间(以秒为单位)并存储在实例属性 self.start 中。
      • 返回自身(self),以便在 with 语句块中可以访问该对象。
    • 方法 __exit__

      def __exit__(self, exc_type, exc_val, exc_tb): self.end = time.time() print(f"耗时: {self.end - self.start:.2f}秒")

      • 实现了上下文管理协议中的 __exit__ 方法。
      • 在退出 with 语句块时,记录当前时间(以秒为单位)并存储在实例属性 self.end 中。
      • 计算执行时间(self.end - self.start),并以两位小数的格式打印到控制台。
  2. 使用场景

    • 通过 with 语句使用 Timer 类来测量代码块的执行时间。
    • 示例:

      with Timer(): time.sleep(1) # 输出: 耗时: 1.00秒

      • 在 with 语句块中调用了 time.sleep(1),模拟了一个耗时 1 秒的操作。
      • Timer 类会自动计算并打印出这段代码的执行时间。 

让自定义类支持切片

python">class MySequence:def __init__(self, data):self.data = datadef __len__(self):return len(self.data)def __getitem__(self, index):if isinstance(index, slice):return self.data[index.start : index.stop : index.step]else:return self.data[index]seq = MySequence([0, 1, 2, 3, 4])
print(seq[1:3])  # [1, 2](支持切片!)

鸭子类型(Duck Typing)​

Python不检查对象的类型,而是检查对象是否实现了特定的方法(即是否“像鸭子一样叫”)。

示例
python">class FakeList:def __len__(self):return 10def __getitem__(self, index):return index * 2fake = FakeList()
print(len(fake))       # 10(调用__len__)
print(fake[5])         # 10(调用__getitem__)
print(isinstance(fake, list))  # False,但行为类似列表!

 

 

 

 

 


http://www.ppmy.cn/news/1579007.html

相关文章

C++蓝桥杯基础篇(十一)

片头 嗨~小伙伴们&#xff0c;大家好&#xff01;今天我们来学习C蓝桥杯基础篇&#xff08;十一&#xff09;&#xff0c;学习类&#xff0c;结构体&#xff0c;指针相关知识&#xff0c;准备好了吗&#xff1f;咱们开始咯~ 一、类与结构体 类的定义&#xff1a;在C中&#x…

基于STM32F407ZGT6的硬件平台,(可选CubeMX) + PlatformIO软件开发的FreeRTOS部署指南

目录 前言 使用CubeMX生成代码的FreeRTOS移植方案 时钟选择 在Middlewares中选择FreeRTOS的版本支持 其他外设的支持 封装自己配置的任务 生成PIO代码 修改platformio.ini 第一步&#xff1a;指定我们的源码文件夹 第二步&#xff0c;解决FPU的选择问题 非CubeMX的Fr…

Linux各种命令大全

Linux课程笔记 目录结构 /&#xff1a;根目录&#xff0c;唯一顶级目录路径示例&#xff1a;/home/itheima/a.txt 表示根目录下的home/itheima文件夹内的a.txt 基础命令 ls&#xff1a;列出文件 ls [选项] [目录] # 选项&#xff1a; # -l 列表形式显示 # -h 人性化显示文…

SQL日期处理

个人学习比较 HIVE 返回所在日期当月天数 SELECT last_day(2025-03-12) as last_day; 结果&#xff1a;31 SELECT day(last_day(2025-03-12)) AS month_days; 结果&#xff1a;31 日期格式转换 SELECT from_unixtime(unix_timestamp(20250312, yyyyMMdd), yyyy-MM-dd) AS fo…

【物联网-WIFI】

物联网-WIFI ■ ESP32-C3-模块简介■ ESP32-C3-■ ESP32-C3-■ WIFI-模组■ WIFI-■ WIFI- ■ ESP32-C3-模块简介 ■ ESP32-C3- ■ ESP32-C3- ■ WIFI-模组 ■ WIFI- ■ WIFI-

Java 大视界 -- Java 大数据在智慧文旅虚拟导游与个性化推荐中的应用(130)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

C语言 第四章 数组(3)

目录 一维数组 内存分析 数组内存图 注意事项 错误举例1&#xff1a; 错误举例2&#xff1a; 变长数组 char型数组与字符串 char型数组 字符串的使用 字符串声明方式1&#xff1a;标准写法 字符串声明方式2&#xff1a;简化写法 实例 字符串的长度 gets()与puts()的使…

数据结构与算法效率分析:时间复杂度与空间复杂度详解(C语言)

1. 算法效率 1.1 如何衡量一个算法的好坏&#xff1f; 在计算机程序设计中&#xff0c;衡量算法优劣的核心标准是效率。但效率不仅指运行速度&#xff0c;还需要综合以下因素&#xff1a; 时间因素&#xff1a;算法执行所需时间 空间因素&#xff1a;算法运行占用的内存空间…