TypeError: argument to reversed() must be a sequence
TypeError: argument to reversed() must be a sequence
为什么枚举不产生序列?
----> 1 BytesInt('1B')
12 def BytesInt(s):
13 suffixes = ['B','KB','MB','GB','TB','PB','EB','ZB','YB']
---> 14 for power,suffix in reversed(enumerate(suffixes)):
15 if s.endswith(suffix):
16 return int(s.rstrip(suffix))*1024**power
TypeError: argument to reversed() must be a sequence
enumerate()
生成一个 迭代器 ,而不是一个序列。序列是 addressable(可以用任何索引订阅),而迭代器不是。
要么不使用 enumerate()
,从 len(suffixes)
中减去,要么将 enumerate()
输出转换为列表。
减法的优点是避免具体化列表:
for index, suffix in enumerate(reversed(suffixes), 1):
power = len(suffixes) - index
演示:
>>> def BytesInt(s):
... suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
... for index, suffix in enumerate(reversed(suffixes), 1):
... power = len(suffixes) - index
... if s.endswith(suffix):
... return int(s.rstrip(suffix)) * 1024 ** power
...
>>> BytesInt('1B')
1
>>> BytesInt('1KB')
1024
>>> BytesInt('1TB')
1099511627776
enumerate
确实return不是一个序列,它是一个生成器。如果您的输入相对较小,您可以将其转换为列表:
for power, suffix in reversed(list(enumerate(suffixes))):
enumerate
不会产生序列,因为它可以枚举任何可迭代对象,而不仅仅是序列。例如,您可以枚举无限生成器。
from random import randint
def randgen(lo, hi):
while True:
yield randint(lo, hi)
for i, v in enumerate(randgen(1, 6)):
print(i, v)
if i == 20:
break
Martijn 通过调用 reversed
序列显示了一个很好的方法来做你想做的事。正如 Daniel 指出的那样,对于这样一个小序列,将 enumerate
生成的可迭代对象转换为列表是完全可以接受的,并且会产生紧凑的代码。
另一种选择是 zip
一个具有倒序的范围,但我认为 Daniel 和 Martijn 的方法在这里更好。
def BytesInt(s):
suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
for power, suffix in zip(range(len(suffixes) - 1, -1, -1), reversed(suffixes)):
if s.endswith(suffix):
return int(s.rstrip(suffix)) * 1024 ** power
for s in ('1B', '1KB', '1TB'):
print(BytesInt(s))
输出
1
1024
1099511627776
显然可以实现 enumerate
因此它在给定序列时生成序列,否则生成可迭代对象。序列可以安全地 reversed
。这通过替换内置函数来工作。其他类似的功能也可以这样实现。
class EnumeratedSequence:
def __init__(self, items):
self.items = items
def __getitem__(self, index):
return (index,self.items[index])
def __len__(self):
return len(self.items)
def enumerate(items):
if hasattr(items, '__getitem__'):
print 'Sequence detected'
return EnumeratedSequence(items)
else:
print 'Iterator detected'
return __builtin__.enumerate(items)
print list(reversed(enumerate('abcdef')))
print list(enumerate(reversed('abcdef')))
Sequence detected
[(5, 'f'), (4, 'e'), (3, 'd'), (2, 'c'), (1, 'b'), (0, 'a')]
Iterator detected
[(0, 'f'), (1, 'e'), (2, 'd'), (3, 'c'), (4, 'b'), (5, 'a')]
为什么枚举不产生序列?
----> 1 BytesInt('1B')
12 def BytesInt(s):
13 suffixes = ['B','KB','MB','GB','TB','PB','EB','ZB','YB']
---> 14 for power,suffix in reversed(enumerate(suffixes)):
15 if s.endswith(suffix):
16 return int(s.rstrip(suffix))*1024**power
TypeError: argument to reversed() must be a sequence
enumerate()
生成一个 迭代器 ,而不是一个序列。序列是 addressable(可以用任何索引订阅),而迭代器不是。
要么不使用 enumerate()
,从 len(suffixes)
中减去,要么将 enumerate()
输出转换为列表。
减法的优点是避免具体化列表:
for index, suffix in enumerate(reversed(suffixes), 1):
power = len(suffixes) - index
演示:
>>> def BytesInt(s):
... suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
... for index, suffix in enumerate(reversed(suffixes), 1):
... power = len(suffixes) - index
... if s.endswith(suffix):
... return int(s.rstrip(suffix)) * 1024 ** power
...
>>> BytesInt('1B')
1
>>> BytesInt('1KB')
1024
>>> BytesInt('1TB')
1099511627776
enumerate
确实return不是一个序列,它是一个生成器。如果您的输入相对较小,您可以将其转换为列表:
for power, suffix in reversed(list(enumerate(suffixes))):
enumerate
不会产生序列,因为它可以枚举任何可迭代对象,而不仅仅是序列。例如,您可以枚举无限生成器。
from random import randint
def randgen(lo, hi):
while True:
yield randint(lo, hi)
for i, v in enumerate(randgen(1, 6)):
print(i, v)
if i == 20:
break
Martijn 通过调用 reversed
序列显示了一个很好的方法来做你想做的事。正如 Daniel 指出的那样,对于这样一个小序列,将 enumerate
生成的可迭代对象转换为列表是完全可以接受的,并且会产生紧凑的代码。
另一种选择是 zip
一个具有倒序的范围,但我认为 Daniel 和 Martijn 的方法在这里更好。
def BytesInt(s):
suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
for power, suffix in zip(range(len(suffixes) - 1, -1, -1), reversed(suffixes)):
if s.endswith(suffix):
return int(s.rstrip(suffix)) * 1024 ** power
for s in ('1B', '1KB', '1TB'):
print(BytesInt(s))
输出
1
1024
1099511627776
显然可以实现 enumerate
因此它在给定序列时生成序列,否则生成可迭代对象。序列可以安全地 reversed
。这通过替换内置函数来工作。其他类似的功能也可以这样实现。
class EnumeratedSequence:
def __init__(self, items):
self.items = items
def __getitem__(self, index):
return (index,self.items[index])
def __len__(self):
return len(self.items)
def enumerate(items):
if hasattr(items, '__getitem__'):
print 'Sequence detected'
return EnumeratedSequence(items)
else:
print 'Iterator detected'
return __builtin__.enumerate(items)
print list(reversed(enumerate('abcdef')))
print list(enumerate(reversed('abcdef')))
Sequence detected
[(5, 'f'), (4, 'e'), (3, 'd'), (2, 'c'), (1, 'b'), (0, 'a')]
Iterator detected
[(0, 'f'), (1, 'e'), (2, 'd'), (3, 'c'), (4, 'b'), (5, 'a')]