-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstructions.txt
More file actions
179 lines (138 loc) · 5.26 KB
/
instructions.txt
File metadata and controls
179 lines (138 loc) · 5.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# 🧠 Python Iteration Behind the Scenes (BTS) – Conceptual Flow
📍 1. Iteration Tools (What we use to loop)
- for loop
- list/dictionary/set comprehensions
- while loop with manual iterators
- generator expressions
🔄 These tools require something to **iterate over** — they look for iterable objects.
📍 2. Iterable Objects (What we loop over)
- Examples: lists, tuples, strings, dictionaries, sets, file objects
- Internally, they implement the `__iter__()` method
➜ This method returns an **iterator object**
📍 3. Iterator (The worker behind the loop)
- This is the object that does the actual work of remembering position
- Has:
✅ `__iter__()` → returns itself
✅ `__next__()` → returns next item or raises `StopIteration`
📍 4. The Flow (BTS of a `for` loop):
for item in iterable:
# Do something
🔽 Internally executes like:
iterator = iter(iterable) # calls iterable.__iter__()
while True:
try:
item = next(iterator) # calls iterator.__next__()
# Do something with item
except StopIteration:
break
📍 5. Important Notes:
- `iter()` returns an iterator from an iterable
- `next()` fetches the next value from an iterator
- `StopIteration` tells Python when to stop looping
📍 6. Bonus: Files are iterators
- File objects implement both `__iter__()` and `__next__()`
- So you can directly do:
with open("file.txt") as f:
for line in f:
print(line)
📍 7. Visual Summary Flow:
Iteration Tool
↓
Iterable Object (e.g. list, file)
↓
Calls → __iter__()
↓
Returns Iterator Object
↓
Calls → __next__()
↓
Gets Next Item
↓
Continues Until → StopIteration
# ---------------------------------------------
# 📘 Topic: Behind the Scenes (BTS) in Python Loops
# ---------------------------------------------
# 🎯 Main Objective:
# Understand what happens *behind the scenes* (BTS) when we use `for` loops in Python.
# Learn how `iter()` and `next()` work to support loop iteration.
# ✅ Basic Definitions:
# Iterable:
# Any object in Python capable of returning its members one at a time.
# Examples: list, tuple, string, dictionary, set, etc.
# Iterator:
# An object that remembers the current position and produces the next value when asked (via `next()`).
# 🔁 BTS of a for-loop:
# Example:
myList = [10, 20, 30]
for item in myList:
print(item)
# 👉 What actually happens behind the scenes:
# Step 1: Python calls iter(myList) to get an iterator object
# Step 2: It repeatedly calls next(iterator) until StopIteration is raised
# Here's the equivalent code:
iterator = iter(myList)
while True:
try:
item = next(iterator)
print(item)
except StopIteration:
break
# 🧠 Important Concepts:
# 1. iter() returns a new iterator object
# It does not return the original list — they are different objects.
myNewList = [1, 2, 3]
print(iter(myNewList) is myNewList) # False
# Because: myNewList is a list, and iter(myNewList) is a list_iterator object
# You can check types:
print(type(myNewList)) # <class 'list'>
print(type(iter(myNewList))) # <class 'list_iterator'>
# 2. next() gives the next value in the sequence from an iterator:
itr = iter(myNewList)
print(next(itr)) # 1
print(next(itr)) # 2
print(next(itr)) # 3
# print(next(itr)) # Raises StopIteration
# 🔍 Key Difference:
# - Iterable: Can be looped over (but does not remember state)
# - Iterator: Can be looped using `next()` and *remembers* its position
# ✅ Check if object is Iterable or Iterator
from collections.abc import Iterable, Iterator
print(isinstance(myNewList, Iterable)) # True
print(isinstance(myNewList, Iterator)) # False
print(isinstance(iter(myNewList), Iterator)) # True
# ------------------------------
# 📚 Real-world Analogy:
# - Iterable: A playlist (you can start from beginning any time)
# - Iterator: A music player playing that playlist — it remembers the current song
# ------------------------------
# 🧪 Bonus: Creating Custom Iterators
class CountUpto:
def __init__(self, max):
self.max = max
self.current = 1
def __iter__(self):
return self
def __next__(self):
if self.current > self.max:
raise StopIteration
val = self.current
self.current += 1
return val
counter = CountUpto(3)
for num in counter:
print(num) # Output: 1 2 3
# ---------------------------------------------
# 🔑 Summary:
# - `for` loop in Python uses `iter()` and `next()` under the hood.
# - `iter(iterable)` creates a new iterator object.
# - `next(iterator)` fetches the next item.
# - When the iterator is exhausted, it raises `StopIteration`.
# - Lists, strings, etc., are iterable — but not iterators themselves.
# - This BTS logic helps you write custom iterators using `__iter__` and `__next__`.
# 🚀 Practice Tip:
# Try writing custom iterators or manually replicate loop logic using iter() and next().
# 💬 Test Yourself:
# 1. What does `iter()` return?
# 2. Why is `iter(myList) is myList` False?
# 3. What will happen if we keep calling `next()` after the iterator is exhausted?
# 4. How does Python know when to stop in a `for` loop?