为什么枚举,邮编,范围类型不属于types.GeneratorType?

时间:2018-10-24 13:20:45

标签: python python-3.x types generator

Python 3引入了类似生成器的对象,该对象将在调用range()zip()时返回。返回的对象就像生成器一样,可以被迭代一次,但是不能很好地“打印”,就像enumerate()返回参数一样。

然而,令我感到困惑的是,它们是不同的对象类型,不属于types.GeneratorType,或者至少这是types模块所显示的。一个可以运行的功能期望发电机不会检测到它们。他们的继承是什么?它们是否属于主要的“生成器”结构,以便它们例如可以与其他发电机一起被识别?

import types

a = [1,2,3]
b = [4,5,6]

# create some generator-type objects
obj_zip = zip(a,b)
obj_enu = enumerate(a)
obj_r = range(10)

print(type(obj_zip))
print(type(obj_enu))
print(type(obj_r))

# checking against types.GeneratorType returns False
print(isinstance(obj_zip,types.GeneratorType))
print(isinstance(obj_enu,types.GeneratorType))
print(isinstance(obj_r,types.GeneratorType))

# checking against their own distinct object types returns True
print(isinstance(obj_zip,zip))

3 个答案:

答案 0 :(得分:5)

the GeneratorType docs

  

types.GeneratorType

     
    

生成器迭代器对象的类型,由生成器函数创建。

  

生成器功能是该语言中的特定功能;它表示使用yieldyield from的函数(或生成器表达式,它们只是内联生成器函数的简写)。它是迭代器集的子集(可以调用next()的所有事物以获取新值),又是迭代器的子集(可以调用iter()的所有事物得到一个迭代器;迭代器本身就是可迭代的,其中iter(iterator)充当标识函数)。

基本上,如果您要测试“是否可以对此进行循环?”,请测试isinstance(obj, collections.abc.Iterable)。如果您正在检查“这是一个穷举的迭代器?” (也就是说,我会通过遍历它来耗尽它吗?),测试isinstance(obj, collections.abc.Iterator)或使用基于鸭型的方法,测试iter(obj) is obj(迭代器上的不变式 require iter(iterator)不变地产生原始迭代器对象。

请注意,range 不是生成器或迭代器。根据{{​​3}}:

  

范围实际上不是一个不变的序列类型,如the docsRanges所述。

成为不可变序列类型意味着可迭代的,仅此而已。通常将其当作迭代器使用,这一事实是无关紧要的。如果它是一个迭代器,那么这里的第二个循环将永远不会执行:

r = range(3)
for i in r:
    print("First", i)
for i in r:
    print("Second", i)

但它工作得很好,因为对iter(r)的每个(隐式)调用都会基于相同的底层itera ble返回一个 new itera tor

答案 1 :(得分:0)

文档说,枚举在功能上等同于生成器。实际上,它是用C实现的,并返回一个迭代器,而不是Does enumerate() produce a generator object中描述的生成器。 生成器和可迭代对象几乎相同。 Difference between Python's Generators and Iterators中对此进行了详细说明。

我假设您正在尝试解决一个实际的问题,例如找出是否可以迭代某些事物。为了解决该问题,您可以测试某物是否为collections.Iterable的实例。

a = enumerate([1,2,3])
isinstance(a, collections.Iterable)
>>> True

答案 2 :(得分:0)

并不是完整的答案(ShadowRanger answer已经解释了所有内容),而只是声明$ python3 Python 3.5.3 (default, Sep 27 2018, 17:25:39) [GCC 6.3.0 20170516] on linux Type "help", "copyright", "credits" or "license" for more information. import pandas pandas.read_csv('ccf_online_stage1_train.csv', nrows=11429827) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/pi/.local/lib/python3.5/site-packages/pandas/io/parsers.py", line 678, in parser_f return _read(filepath_or_buffer, kwds) File "/home/pi/.local/lib/python3.5/site-packages/pandas/io/parsers.py", line 446, in _read data = parser.read(nrows) File "/home/pi/.local/lib/python3.5/site-packages/pandas/io/parsers.py", line 1051, in read df = DataFrame(col_dict, columns=columns, index=index) File "/home/pi/.local/lib/python3.5/site-packages/pandas/core/frame.py", line 348, in __init__ mgr = self._init_dict(data, index, columns, dtype=dtype) File "/home/pi/.local/lib/python3.5/site-packages/pandas/core/frame.py", line 459, in _init_dict return _arrays_to_mgr(arrays, data_names, index, columns, dtype=dtype) File "/home/pi/.local/lib/python3.5/site-packages/pandas/core/frame.py", line 7364, in _arrays_to_mgr return create_block_manager_from_arrays(arrays, arr_names, axes) File "/home/pi/.local/lib/python3.5/site-packages/pandas/core/internals.py", line 4872, in create_block_manager_from_arrays blocks = form_blocks(arrays, names, axes) File "/home/pi/.local/lib/python3.5/site-packages/pandas/core/internals.py", line 4918, in form_blocks int_blocks = _multi_blockify(items_dict['IntBlock']) File "/home/pi/.local/lib/python3.5/site-packages/pandas/core/internals.py", line 4995, in _multi_blockify values, placement = _stack_arrays(list(tup_block), dtype) File "/home/pi/.local/lib/python3.5/site-packages/pandas/core/internals.py", line 5037, in _stack_arrays stacked = np.empty(shape, dtype=dtype) MemoryError 确实是非常有限的类型,如types.GeneratorType来源所示:

types.py

它仅限制生成器函数的类型。其他“类似于发电机”的对象不使用def _g(): yield 1 GeneratorType = type(_g()) ,因此它们不是匹配项。