Python循环和迭代器怎么使用
时间:2023-05-20 22:32
在 Python 中,与大多数语言一样,有两个基本的循环: 在 Python 中,我们还有几个有用的关键字: 一旦我们遇到该 注意:如果你曾经使用过任何语言的循环,那么你已经熟悉了无限循环(死循环)。这通常是由 来自 Java、C++ 或许多类似的 ALGOL 风格的语言,你可能熟悉三方 Python 的 range()是 Python 中一个特殊的“函数”,它返回一个序列。(从技术上讲,它根本不是一个函数。) 这是 Python 令人印象深刻的地方——它迭代了一种特殊类型的序列,称为iterable,我们稍后会谈到。 目前,最容易理解的是我们可以迭代一个顺序数据结构,比如一个数组(在 Python 中称为“列表”)。 因此,我们可以这样做... 我们得到这个... Python 在其循环中还有另一个独特的小技巧: 由于“Mali”不在列表中,因此我们看到了“The villain got away again.”的消息。但是,如果我们将值更改 Python 没有 Python 有许多保存数据的容器或数据结构。我们不会深入讨论其中的任何一个,但我想快速浏览一下最重要的部分: list是一个可变序列(其实就是一个数组)。 它是用方括号定义的 尽管对它没有严格的技术要求,但典型的约定是列表只包含相同类型的元素(“同质”)。 tuple是一个不可变的序列。一旦你定义了它,你在技术上就不能改变它(回想一下之前不变性的含义)。这意味着在定义tuple后,你不能在tuple中添加或删除元素。 一个tuple是在括号中定义的 与列表不同,标准约定允许tuple包含不同类型的元素(“异构”)。 set是一个无序的可变集合,保证没有重复。记住“无序”很重要:不能保证单个元素的顺序! 一个集合在花括号中定义 对于要添加到集合中的对象,它也必须是可散列的(hash)。一个对象是可散列的,如果: 它定义了方法__hash__(),该方法将哈希值(hash)作为整数返回。(见下文) 它定义了__eq__()比较两个对象的方法。 对于同一个对象(值),一个有效的散列值(hash)应该总是相同的,并且它应该是合理的唯一的,因此另一个对象返回相同的散列是不常见的。(两个或多个具有相同哈希值的对象称为哈希冲突,它们仍然会发生。) dict(字典)是键值数据结构。 它在花括号中定义 只有可散列的对象可以用作字典键。(有关 除了基础之外,Python 还提供了额外的容器/数据结构。可以在内置模块collections中找到它们。 有一个重要的 Python 语法我们还没有讨论过,但很快就会派上用场。我们可以将容器中的每个元素分配给一个变量!这称为拆包。 当然,我们需要确切地知道我们要拆包多少才能结束,否则我们会得到一个 让我们看一个使用tuple元组的基本示例。 看第二行代码,我们可以列出多个要分配的变量,用逗号分隔。Python 将拆分等号右侧的容器,将每个值按从左到右的顺序分配给一个变量。 注意:记住, Python 提供了一个关键字 这适用于许多容器,包括列表、元组、集合,甚至是字典键(但不是字典值)。 如果你希望你的自定义类之一支持 Python 的循环是配合我之前提到的迭代器一起使用。前面提到的数据结构都是是可以使用迭代器迭代的对象。 好的,让我们从头开始。Python 容器对象,例如 方法 当 让我们再看一下 调用 对于循环的每次迭代,它都会调用 如果迭代器抛出了特殊异常 如果你尝试这两个循环,你会发现它们做的事情完全相同! 了解 注意:虽然将迭代器类与可迭代类分开定义都可以,但你不一定必须这样做!只要这两种方法都在你的类中定义,并且 值得注意的是迭代器本身是可迭代的:它们有一个 假设我们有一本想要使用的字典...... 如果我们只想查看其中的每个项目,我们只需使用 哎呀!这只向我们展示了键,而不是值。这并不是我们想要的,不是吗? 要同时获取键和值,我们需要调用 旧版说明:如果你使用的是 Python 2,则应改为调用 还记得刚才,当我们谈到拆包的时候吗?我们将每一对键值作为一个元组并拆分成成两个变量。 打印出以下内容: 现在我们可以处理数据了。例如,我想在另一个字典中记录重要信息。 这将找到 Loot、Warrant 和 Crook,并按正确顺序列出它们: 我之前已经提到你可以制作自己的迭代器和迭代器,但现在来实现它! 想象一下,我们想方便保留一个代理列表,以便我们始终可以通过代理编号来识别它们。但是,有些代理是我们不能谈论的。我们可以通过将代理 ID 和名称存储在字典中,然后维护分类代理列表来轻松完成此操作。 注意:请记住,在我们对类的讨论中,Python 中实际上没有私有变量这样的东西。如果你真的打算保密,请使用行业标准的加密和安全实践,或者至少不要将你的 API 暴露给任何 VILE 操作员。;) 对于初学者,这是该类的基本结构: 我们可以继续测试一下,只是为了后续: 太好了,这完全符合预期!现在,如果我们希望能够遍历整个字典怎么办。 但是,我们不想直接访问 正如我之前提到的,我们可以让这个类也作为它自己的迭代器,这意味着它有一个 在这个例子中,我实际上将字典变成了一个元组列表,这将允许我使用索引。(请记住,字典是无序的。)我还将计算出有多少代理未分类。当然,所有这些逻辑都属于该 要成为迭代器,类必须有 我将定义 现在我们返回到 只需要一点点操作,现在我们的 产生的结果如下... 以上就是Python循环和迭代器怎么使用的详细内容,更多请关注Gxl网其它相关文章!循环概述
while
和for
。while
while
循环是非常基本的。clue = Nonewhile clue is None: clue = searchLocation()
clue is None
在这种情况下,只要循环条件的计算结果为True
,就会执行循环的代码。break
立即停止循环,同时continue
跳到循环的下一次迭代。break
最有用的方面之一是如果我们想要运行相同的代码,直到用户提供有效的输入。while True: try: age = int(input("Enter your age: ")) except ValueError: print(f"Please enter a valid integer!") else: if age > 0: break
break
语句,我们就退出循环。当然,上面是一个较复杂的例子,但它证明了这一点。你还经常看到while True:
在游戏循环中使用。while
条件计算结果为True
并且循环中没有break
语句引起的。for
for
循环:for i := 1; i < 100; i := i + 1
。 我不了解你,但当我第一次遇到这种情况时,它吓坏了我。我现在对它很满意,但它不具备 Python 的优雅简洁。for
循环看起来大不相同。与上述伪代码等效的 Python 代码是...for i in range(1,100): print(i)
places = ['Nashville', 'Norway', 'Bonaire', 'Zimbabwe', 'Chicago', 'Czechoslovakia']for place in places: print(place)print("...and back!")
NashvilleNorwayBonaireZimbabweChicagoCzechoslovakia...and back!
for...else
else
子句!循环完成后,没有遇到break
语句,就会运行else
。但是,如果手动中断循环,它将else
完全跳过。places = ['Nashville', 'Norway', 'Bonaire', 'Zimbabwe', 'Chicago', 'Czechoslovakia']villain_at = 'Mali'for place in places: if place == villain_at: print("Villain captured!") breakelse: print("The villain got away again.")
villain_at
为Norway
,我们将看到“Villain captured!” ,而看不到了“The villain got away again.”。存在do...whiel吗?
do...while
循环。如果你正在寻找这样的循环方式,典型的 Python 是使用while True:
带内部break
条件的 ,就像我们之前演示的那样。数据结构(容器)
list
[ ]
,你可以通过索引访问它的元素。foo = [2, 4, 2, 3]print(foo[1])>>> 4foo[1] = 42print(foo)>>> [2, 42, 2, 3]
tuple
( )
,你可以通过索引访问它的元素。foo = (2, 4, 2, 3)print(foo[1])>>> 4foo[1] = 42>>> TypeError: 'tuple' object does not support item assignment
set
{ }
,但如果你想要一个空集合,你可以使用foo = set()
, 或者foo = {}
创建一个空的dict
. 你不能通过索引访问它的元素,因为它是无序的。foo = {2, 4, 2, 3}print(foo)>>> {2, 3, 4}print(foo[1])>>> TypeError: 'set' object does not support indexing
dict
{ }
,:
用于分隔键和值。它是无序的,所以你不能通过索引访问它的元素;但是你可以通过[ ]
加键值访问元素。foo = {'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4}print(foo['b'])>>> 2foo['b'] = 42print(foo)>>> {'a': 1, 'b': 42, 'c': 3, 'd': 4}
set
哈希性的更多信息,请参阅官网的部分。)其他
拆包
ValueError
的异常。fullname = ('Carmen', 'Sandiego')first, last = fullnameprint(first)>>> Carmenprint(last)>>> Sandiego
set
是无序的!虽然你可以在技术上使用集合来执行此操作,但你无法确定将什么值分配给什么变量。不保证按顺序进行分配,集合的值的分配顺序通常是偶然的!in
in
,用于检查是否在容器中找到了特定元素。places = ['Nashville', 'Norway', 'Bonaire', 'Zimbabwe', 'Chicago', 'Czechoslovakia']if 'Nashville' in places: print("Music city!")
in
运算符,你只需要定义__contains__(self, item)
方法,它应该返回True
or False
。迭代器
list
,也是一个可迭代对象,因为它的__iter__()
方法,返回一个迭代器对象。__next__()
也是一个迭代器,在容器迭代器的情况下,返回下一项。即使是无序的容器,例如set()
,也可以使用迭代器进行遍历。__next__()
不能返回任何其他内容时,它会抛出一个名为StopIteration的特殊异常。这可以使用try...except
捕获异常。for
遍历 list
的循环,例如...dossiers = ['The Contessa', 'Double Trouble', 'Eartha Brute', 'Kneemoi', 'Patty Larceny', 'RoboCrook', 'Sarah Nade', 'Top Grunge', 'Vic the Slick', 'Wonder Rat']for crook in dossiers: print(crook)
dossiers
是一个list
对象,它是一个可迭代的对象。当 Python 到达for
循环时,它会做三件事:iter(dossiers)
,依次执行dossiers.__iter__()
。这将返回一个我们将调用的迭代器对象list_iter
。这个迭代器对象将被循环使用。next(list_iter)
,执行list_iter.__next__()
并将返回的值分配给crook
。StopIteration
,则循环结束,退出。while True:
如果我在循环中重写该逻辑可能会更容易理解......list_iter = iter(dossiers)while True: try: crook = next(list_iter) print(crook) except StopIteration: break
__iter__()
,__next__()
和StopIteration
异常的工作原理后,你现在可以使自己的类可迭代!__next__()
行为适当,你就可以定义__iter__()
为return self
.__iter__()
方法返回self
。字典案例
locations = { 'Parade Ground': None, 'Ste.-Catherine Street': None, 'Pont Victoria': None, 'Underground City': None, 'Mont Royal Park': None, 'Fine Arts Museum': None, 'Humor Hall of Fame': 'The Warrant', 'Lachine Canal': 'The Loot', 'Montreal Jazz Festival': None, 'Olympic Stadium': None, 'St. Lawrence River': 'The Crook', 'Old Montréal': None, 'McGill University': None, 'Chalet Lookout': None, 'Île Notre-Dame': None }
for
循环。所以,这应该有效,对吧?for location in locations: print(location)
dict.__iter__()
返回一个dict_keyiterator
对象,该对象执行其类名的操作:它遍历键,但不遍历值。locations.items()
返回dict_items
对象。dict_items.iter()
返回 dict_itemiterator
,它将字典中的每个键值对作为元组返回。locations.iteritems()
。for key, value in locations.items(): print(f'{key} => {value}')
Parade Ground => NoneSte.-Catherine Street => NonePont Victoria => NoneUnderground City => NoneMont Royal Park => NoneFine Arts Museum => NoneHumor Hall of Fame => The WarrantLachine Canal => The LootMontreal Jazz Festival => NoneOlympic Stadium => NoneSt. Lawrence River => The CrookOld Montréal => NoneMcGill University => NoneChalet Lookout => NoneÎle Notre-Dame => None
information = {}for location, result in locations.items(): if result is not None: information[result] = location# Win the game!print(information['The Loot'])print(information['The Warrant'])print(information['The Crook'])print("Vic the Slick....in jaaaaaaaaail!")
Lachine CanalHumor Hall of FameSt. Lawrence RiverVic the Slick....in jaaaaaaaaail!
自定义迭代器
class AgentRoster: def __init__(self): self._agents = {} self._classified = [] def add_agent(self, name, number, classified=False): self._agents[number] = name if classified: self._classified.append(name) def validate_number(self, number): try: name = self._agents[number] except KeyError: return False else: return True def lookup_agent(self, number): try: name = self._agents[number] except KeyError: name = "<NO KNOWN AGENT>" else: if name in self._classified: name = "<CLASSIFIED>" return name
roster = AgentRoster()roster.add_agent("Ann Tickwitee", 2539634)roster.add_agent("Ivan Idea", 1324595)roster.add_agent("Rock Solid", 1385723)roster.add_agent("Chase Devineaux", 1495263, True)print(roster.validate_number(2539634))>>> Trueprint(roster.validate_number(9583253))>>> Falseprint(roster.lookup_agent(1324595))>>> Ivan Ideaprint(roster.lookup_agent(9583253))>>> <NO KNOWN AGENT>print(roster.lookup_agent(1495263))>>> <CLASSIFIED>
roster._agents
字典,因为这将忽略这个类的整个“分类”方面。我们如何处理?__next__()
方法。在这种情况下,我们只会 return self
。但是,这里是超简单Python教程,所以让我们跳过烦人步骤,简化内容,实际创建一个单独的迭代器类。__init__()
方法:class AgentRoster_Iterator: def __init__(self, container): self._roster = list(container._agents.items()) self._classified = container._classified self._max = len(self._roster) - len(self._classified) self._index = 0
__next__()
方法;这是唯一的要求!请记住,一旦我们没有更多数据要返回,该方法就需要抛出StopException
异常。AgentRoster_Iterator
的__next__()
方法如下:class AgentRoster_Iterator: # ...snip... def __next__(self): if self._index == self._max: raise StopIteration else: r = self._roster[self._index] self._index += 1 return r
AgentRoster
类,我们需要在其中添加一个__iter__()
返回迭代器对象的方法。class AgentRoster: # ...snip... def __iter__(self): return AgentRoster_Iterator(self)
AgentRoster
类的行为与循环的预期完全一样!这段代码如下...roster = AgentRoster()roster.add_agent("Ann Tickwitee", 2539634)roster.add_agent("Ivan Idea", 1324595)roster.add_agent("Rock Solid", 1385723)roster.add_agent("Chase Devineaux", 1495263, True)for number, name in roster: print(f'{name}, id #{number}')
Ann Tickwitee, id #2539634Ivan Idea, id #1324595Rock Solid, id #1385723