Gun (Iterator) is a behavioral design pattern:
🖤🖤🖤🖤🤍
Iterator
and Iterable
often confused me, so I renamed them. Gun
represents Iterator, Bullets
represents Iterable.
What is Gun and Bullets?
Bullets
(Iterable) is a group of bullets.
def __iter__()
helps us arrange bullets and other accessories to turn them into a gun.
Gun
(Iterator) is an object that can fire bullet one by one.
def __next__()
help us fire the bullets.
Why use Gun?
It makes shooting more manageable, more professional. Your gun can integrate other tools such as a compass, binoculars, and silencer…!
Question: Just throw the bullet to the target, the gun seems to just make it fancy!
Answer: It is more useful when you need to use plugins or customize many features with your gun.
When to use Gun?
Question: When I need to use Gun
?
Answer: When you need to fire the bullets
!
- Having many bullets:
1stBullet
2ndBullet
3rdBullet
Expected Output:
- Firing bullets in expected order by:
- Getting a
Normal Gun
- First Shoot will fire
1stBullet
- Then
2ndBullet, 3rdBullet
- Getting a
LIFO Gun
- First Shoot will fire
3rdBullet
- Then
2ndBullet, 1stBullet
1
2
3
4
5
6
|
⬅️ Normal Gun 🔫:
🎯First Shoot: 1stBullet
🎯The Rest: 2ndBullet-3rdBullet
🔄 LIFO Gun 🔫:
🎯First Shoot: 3rdBullet
🎯The Rest: 2ndBullet-1stBullet
|
How to implement Gun?
Non-Gun implementation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
if __name__ == "__main__":
bullets = []
# Input 1: Having many bullets:
bullets.append("1stBullet")
bullets.append("2ndBullet")
bullets.append("3rdBullet")
gun = iter(bullets)
first_fired_bullet = next(gun)
remaining_bullets = "-".join(gun)
# Expected Output 1: Firing bullets in expected order by: Normal Gun
print(
f"⬅️ Normal Gun 🔫:\n🎯First Shoot: {first_fired_bullet} \n🎯The Rest: {remaining_bullets}"
)
lifo_gun = iter(bullets[::-1])
first_fired_bullet = next(lifo_gun)
remaining_bullets = "-".join(lifo_gun)
# Expected Output 2: Firing bullets in expected order by: LIFO Gun
print(
f"🔄 LIFO Gun 🔫:\n🎯First Shoot: {first_fired_bullet} \n🎯The Rest: {remaining_bullets}"
)
|
Gun implementation:
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
|
from collections.abc import Iterable, Iterator
class Bullets(Iterable):
def __init__(self, bullets=None):
self._bullets = bullets or []
# to_normal_gun
def __iter__(self):
return Gun(self._bullets)
def to_lifo_gun(self):
return Gun(self._bullets, reverse=True)
def load(self, bullet):
self._bullets.append(bullet)
class Gun(Iterator):
_position = None
_reverse = False
def __init__(self, bullets, reverse=False):
self._bullets = bullets
self._reverse = reverse
self._position = -1 if reverse else 0
def __next__(self):
try:
value = self._bullets[self._position]
self._position += -1 if self._reverse else 1
except IndexError:
raise StopIteration()
return value
if __name__ == "__main__":
bullets = Bullets()
# Input 1: Having many bullets:
bullets.load("1stBullet")
bullets.load("2ndBullet")
bullets.load("3rdBullet")
gun = iter(bullets)
first_fired_bullet = next(gun)
remaining_bullets = "-".join(gun)
# Expected Output 1: Firing bullets in expected order by: Normal Gun
print(
f"⬅️ Normal Gun 🔫:\n🎯First Shoot: {first_fired_bullet} \n🎯The Rest: {remaining_bullets}"
)
lifo_gun = bullets.to_lifo_gun()
first_fired_bullet = next(lifo_gun)
remaining_bullets = "-".join(lifo_gun)
# Expected Output 2: Firing bullets in expected order by: LIFO Gun
print(
f"🔄 LIFO Gun 🔫:\n🎯First Shoot: {first_fired_bullet} \n🎯The Rest: {remaining_bullets}"
)
|
Source Code