zoukankan      html  css  js  c++  java
  • 【转】Python中自定义可迭代对象

    python 中内置的可迭代的对象有 list、tuple、set、dict 等,那么我们自己怎么定义一个可迭代的对象呢?先来段代码吧

    import re
    import reprlib
    
    RE_WORD = re.compile('w+')
    
    
    class Sentence:
        def __init__(self, text):
            self.text = text
            self.words = RE_WORD.findall(text)
    
        def __getitem__(self, item):
            return self.words[item]
    
        def __iter__(self):
            for word in self.words:
                yield word
    
    
    sen = Sentence("abc def 123 456")
    for i in sen:
        print(i)
    
    运行这段代码,结果如下:
    E:python36python3.exe E:/python_demo/test1.py
    abc
    def
    123
    456
    
    Process finished with exit code 0`
    

    通过结果分析,我们已经看出 Sentence 对象已经是可迭代的了!
    此时我们可以注释掉 iter 函数

    class Sentence:
        def __init__(self, text):
            self.text = text
            self.words = RE_WORD.findall(text)
    
        def __getitem__(self, item):
            return self.words[item]
    
        # def __iter__(self):
        #     for word in self.words:
        #         yield word
    
    
    再次运行发现结果正常,接着注释  __getitem__ 函数
    class Sentence:
        def __init__(self, text):
            self.text = text
            self.words = RE_WORD.findall(text)
    
        # def __getitem__(self, item):
        #     return self.words[item]
    
        # def __iter__(self):
        #     for word in self.words:
        #         yield word
    
    发现报错了,报错信息很明朗,提示 Sentence 不是可迭代的对象
    Traceback (most recent call last):
      File "E:/python_demo/fluency_python/chapter14/test1.py", line 21, in <module>
        for i in sen:
    TypeError: 'Sentence' object is not iterable
    
    Process finished with exit code 1
    

    看到这,是不是可以说,对象只需要实现 getitem 函数,那么该对象就是可迭代的呢?先别下定论,我们接着放开注释掉的 iter 函数

    class Sentence:
        def __init__(self, text):
            self.text = text
            self.words = RE_WORD.findall(text)
    
        # def __getitem__(self, item):
        #     return self.words[item]
    
        def __iter__(self):
            for word in self.words:
                yield word
    

    发现运行结果又正确了,我们发现 __iter____getitem__ 中实现任意一个,对象就是可迭代的,怎么解释这种情况呢,Python 解释器中有这样的描述

    解释器需要迭代对象 x 时, 会自动调用 iter(x)。
    内置的 iter 函数有以下作用。

    1. 检查对象是否实现了 __iter__ 方法, 如果实现了就调用它, 获取一个迭代器。
    2. 如果没有实现 __iter__方法, 但是实现了 __getitem__ 方法,Python 会创建一个迭代器, 尝试按顺序(从索引 0 开始) 获取元素。
    3. 如果尝试失败, Python 抛出 TypeError 异常, 通常会提示“C object is not iterable”(C 对象不可迭代) , 其中 C 是目标对象所属的类。
      任何 Python 序列都可迭代的原因是, 它们都实现了 __getitem__ 函数。 其实, 标准的序列都实现了 __iter__ 函数, 因此你也应该这么做。
    总结
    1. 因此我们在自定义可迭代对象需要实现__iter__函数
    2. 严格来讲,我们还需要实现 __getitem__ 函数,这个函数的主要作用是当前对象可通过下标取值

    另外,如果有一个未知的对象,我们怎么判断该对象是否可迭代呢,两种方式:

    1. iter(x)
      这是最准确的判断方式,传入要判断的对象,只要对象实现了__getitem__ 、 __iter__中的其中一个,该对象都是可迭代的,否则抛出TypeError: 'C' object is not iterable 异常;这儿有个区别,如果仅仅实现了 getitem ,调用 iter(x) 返回的是迭代器对象,如果实现的是 iter ,那么调用 iter(x) 返回的是生成器对象;

    2. isinstance(x, abc.Iterable)
      该方式会自动忽略 getitem 函数,仅当对象实现了 iter 函数才返回 True,其他一律返回 False

    原文链接:https://www.jianshu.com/p/048d40d86759

  • 相关阅读:
    第一阶段冲刺总结
    读书笔记之梦断代码1
    第二次站立会议5
    第二次站立会议4
    第二次站立会议3
    第二次站立会议2
    Java学习
    项目冲刺第十天
    项目冲刺第九天
    项目冲刺第八天
  • 原文地址:https://www.cnblogs.com/byron0918/p/10196398.html
Copyright © 2011-2022 走看看