Python :数据模子

[复制链接]
发表于 2025-10-16 02:28:06 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一. 什么是数据模子?

Python数据模子是Python对象体系的抽象,通过一组特别方法​(如__init__、__len__等)和协议​(如迭代协议、上下文管理协议),界说了对象怎样与语言的内置功能(如len()、for循环等)交互。
​焦点头脑


  • ​同一性:全部对象(如列表、字典、自界说类)的活动都通过雷同的特别方法实现。
  • ​机动性:通过实现特别方法,可以让自界说对象支持内置使用(如+、in、切片等)。
例子
  1. import collections
  2. Card = collections.namedtuple('Card', ['rank', 'suit'])
  3. class FrenchDeck:
  4.     ranks = [str(n) for n in range(2, 11)] + list('JQKA')
  5.     suits = 'spades diamonds clubs hearts'.split()
  6.     def __init__(self):
  7.         self._cards = [Card(rank, suit) for suit in self.suits
  8.         for rank in self.ranks]
  9.     def __len__(self):
  10.         return len(self._cards)
  11.     def __getitem__(self, position):
  12.         return self._cards[position]
复制代码
表明


  •         模块导入:
            import collections
            导入了 Python 尺度库中的 collections 模块。
  •         定名元组界说:Card:
            Card = collections.namedtuple('Card', ['rank', 'suit'])
            使用 namedtuple 创建了一个名为 Card 的简朴类,体现扑克牌的一张牌。每个 Card 对象有两个属性:

    • rank:体现牌的点数(如 '2', 'J', 'A' 等)。
    • suit:体现牌的花色(如 'spades', 'diamonds' 等)。
           
  •         类界说: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循环:
  1. class CountDown:
  2.     def __init__(self, start):
  3.         self.current = start
  4.     def __iter__(self):
  5.         return self
  6.     def __next__(self):
  7.         if self.current <= 0:
  8.             raise StopIteration
  9.         else:
  10.             self.current -= 1
  11.             return self.current + 1
  12. for num in CountDown(3):
  13.     print(num)  # 输出: 3 2 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 前的值(即当前值)。
                     
           
  •         使用场景:

    • 该类可以通过 for 循环或手动调用 next() 方法举行倒计时。
    • 示例:       
      1. countdown = CountDown(5)
      2. for value in countdown:
      3.     print(value)
      复制代码
              输出结果:                5 4 3 2 1
           
上下文管理协议

实现__enter__和__exit__方法,支持with语句:
  1. class Timer:
  2.     def __enter__(self):
  3.         self.start = time.time()
  4.         return self
  5.     def __exit__(self, exc_type, exc_val, exc_tb):
  6.         self.end = time.time()
  7.         print(f"耗时: {self.end - self.start:.2f}秒")
  8. with Timer():
  9.     time.sleep(1)  # 输出: 耗时: 1.00秒
复制代码
 表明


  •         类界说: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),并以两位小数的格式打印到控制台。
                     
           
  •         使用场景:

    • 通过 with 语句使用 Timer 类来丈量代码块的实行时间。
    • 示例:                with Timer(): time.sleep(1) # 输出: 耗时: 1.00秒

      • 在 with 语句块中调用了 time.sleep(1),模仿了一个耗时 1 秒的使用。
      • Timer 类会自动盘算并打印出这段代码的实行时间。 
                     
           
让自界说类支持切片
  1. class MySequence:
  2.     def __init__(self, data):
  3.         self.data = data
  4.     def __len__(self):
  5.         return len(self.data)
  6.     def __getitem__(self, index):
  7.         if isinstance(index, slice):
  8.             return self.data[index.start : index.stop : index.step]
  9.         else:
  10.             return self.data[index]
  11. seq = MySequence([0, 1, 2, 3, 4])
  12. print(seq[1:3])  # [1, 2](支持切片!)
复制代码
鸭子范例(Duck Typing)​

Python不查抄对象的范例,而是查抄对象是否实现了特定的方法(便是否“像鸭子一样叫”)。
​示例:
  1. class FakeList:
  2.     def __len__(self):
  3.         return 10
  4.     def __getitem__(self, index):
  5.         return index * 2
  6. fake = FakeList()
  7. print(len(fake))       # 10(调用__len__)
  8. print(fake[5])         # 10(调用__getitem__)
  9. print(isinstance(fake, list))  # False,但行为类似列表!
复制代码
 
 
 
 
 
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表