---
title: "BP1 - Gun (Iterator) - Design Pattern From Simple Things"
description: "There are bullets that need to be fired one by one in a specific order. You need a tool to set it up neatly and easily upgrade later."
pubDate: "2022-11-17"
lang: "en"
slug: "bp1-gun-iterator-design-pattern-from-simple-things"
url: "https://hoangyell.com/bp1-gun-iterator-design-pattern-from-simple-things/"
author: "HoangYell"
categories: ["Software Craft"]
tags: ["design-patterns", "behavioral-patterns"]
heroImage: "https://raw.githubusercontent.com/HoangGeek/store/main/webp/1yD4V87.webp"
---

_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.

![Image](https://raw.githubusercontent.com/HoangGeek/store/main/webp/202880298-3a615160-fc79-47ac-a4f7-4c06b4ad4ebd.webp)

## 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._ 

![Image](https://media.tenor.com/C_qUzONv4skAAAAC/bush-throw-stone-at.gif)

## When to use Gun?

**Question:** _When I need to use `Gun`?_

**Answer:** _When you need to fire the `bullets`!_

### Input:
  - Having many bullets:
    - `1stBullet`
    - `2ndBullet`
    - `3rdBullet`
```python
# nothing here
```
### 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`
```shell
⬅️ Normal Gun 🔫:
🎯First Shoot: 1stBullet 
🎯The Rest: 2ndBullet-3rdBullet
🔄 LIFO Gun 🔫:
🎯First Shoot: 3rdBullet 
🎯The Rest: 2ndBullet-1stBullet
```
![Image](https://raw.githubusercontent.com/HoangGeek/store/main/webp/Zzrqrq2.webp)

## How to implement Gun?

### Non-Gun implementation:
```python
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:
```python
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](https://github.com/HoangYell/Design-Pattern-From-Simple-Things/blob/main/bp1_gun.py)
