# Python 1 -  How Python Works Inside: Install, Shell, Memory, and Data Types

## Part 1: The Student Who Wanted to See Inside

Meet Aman. He is a second-year college student. He has written small Python programs before. He can print "Hello" and add two numbers. But one day his senior, Neha, asks him a simple question:

> "When you run `python hello.py`, what actually happens inside the computer?"

Aman has no answer. He only knows that the output appears. He does not know *how*.

Neha smiles and says, "Then let's start from the beginning. Install Python the right way, and then I will show you what happens under the hood."

This article is that journey. By the end of it, you will understand:

1. The best way to install Python
2. How Python runs your code (bytecode and the virtual machine)
3. How to use the Python shell
4. What "mutable" and "immutable" mean
5. The big picture of Python data types
6. How Python manages memory with references

Let's begin.

![](https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/1c1cb38b-b5ad-4515-82c5-711beae0b72e.png align="center")

---

## Part 2: The Best Way to Install Python

Aman already has Python on his laptop. But Neha asks, "Which Python? How did you install it?"

"I don't remember," he says. "Maybe Anaconda? Maybe something else."

This is the first lesson. **Many beginners install Python three or four times in different ways and then get confused.** Let's keep it clean.

### Step 1: Go to the official website

The best place is the official site: [**python.org**](http://python.org). Go to the *Downloads* page. It will show the latest stable version for your operating system (Windows, macOS, or Linux).

Download it and run the installer.

### Step 2: One important checkbox on Windows

On Windows, the installer has a checkbox that says **"Add Python to PATH"**. Tick this box.

Why? Because PATH tells your computer where to find the `python` command. If you skip this, you will type `python` in the terminal and get an error like *"python is not recognized."*

### Step 3: Check the installation

Open your terminal (Command Prompt or PowerShell on Windows, Terminal on Mac/Linux) and type:

```bash
python --version
```

On Mac and Linux, you may need to type:

```bash
python3 --version
```

You should see something like `Python 3.12.1`. If you see this, Python is installed correctly.

### "Why not Anaconda?"

Aman asks the question many people ask. Neha explains:

- **Anaconda** is a large package. It installs Python *plus* hundreds of data science libraries. It is heavy (several GB).
- It is great if you are doing data science right now.
- But if you are *learning Python*, it adds confusion. You have two Pythons, two package managers (pip and conda), and two sets of settings.

Her advice: **Start with plain Python from** [**python.org**](http://python.org)**.** You can always add Anaconda later when you need it.

### What about pyenv, Homebrew, and other tools?

You may hear about tools like `pyenv` (to manage many Python versions) or `brew install python` on Mac. These are good tools for professionals. For a beginner, they are one more thing to learn. Keep it simple at first.

### A good code editor

Neha also suggests installing **Visual Studio Code (VS Code)** and adding its **Python extension**. It gives you syntax colors, auto-complete, and a built-in terminal.

![](https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/a21bc4ca-78ff-4b85-aa28-0ffa4674b5a3.png align="center")

### Quick summary

| Choice | Good for | Beginner advice |
| --- | --- | --- |
| [python.org](http://python.org) installer | Everyone | ✅ Start here |
| Anaconda | Data science | Later, if needed |
| pyenv / Homebrew | Managing many versions | Later |
| VS Code + Python extension | Writing code | ✅ Install |

### Practice

1. Open your terminal and run `python --version` (or `python3 --version`). Write down the version you see.
2. Why should you tick "Add Python to PATH" on Windows?
3. True or False: Anaconda is the best way for a beginner to learn Python.

---

## Part 3: Python Inner Working (What Happens When You Run a File)

Now comes the question that started everything. Aman writes a small file:

```python
# hello.py
print("Hello, chai!")
```

He runs it:

```bash
python hello.py
```

The output appears. But what happened in between?

### Myth: "Python is an interpreted language"

Most people say Python is an *interpreted* language. Neha says, "That is only half true."

Here is the real picture. When you run a Python file, there are **two steps**:

#### Step 1: Compile to bytecode

Python first converts your source code (`hello.py`) into something called **bytecode**.

- Bytecode is a low-level form of your code.
- It is **not** machine code. Your CPU cannot run it directly.
- It is **platform independent**. The same bytecode works on Windows, Mac, and Linux.
- It is faster for Python to work with than your original text.

So yes, Python *does* compile. But it compiles to bytecode, not to machine code like C or C++.

#### Step 2: Run the bytecode on the Python Virtual Machine (PVM)

The bytecode is then given to the **Python Virtual Machine**, also called the PVM.

The PVM is the *runtime engine* of Python. Think of it as a big loop. It reads one bytecode instruction, does it, reads the next one, does it, and so on, until the program ends.

This is the "interpreter" part. So the truth is:

> **Python compiles your code to bytecode, and then interprets that bytecode.**

![](https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/76bae809-a67f-4b5d-b114-e8b65e016833.png align="center")

### Where is the bytecode saved? The `__pycache__` folder

Aman notices something. After he imports one file into another, a new folder appears: `__pycache__`.

Inside it is a file like:

```plaintext
hello.cpython-312.pyc
```

Let's read this name:

- `hello` → the name of your file
- `cpython` → the Python implementation used (more on this below)
- `312` → Python version 3.12
- `.pyc` → "Python compiled" bytecode file

Python saves bytecode here so that **next time, it does not need to compile again**. This makes imports faster.

Two important rules:

1. **The** `.pyc` **file is made only for imported modules.** The main file you run directly (the "top-level" file) is compiled in memory but its `.pyc` is not saved.
2. **Python checks if the source changed.** If you edit `hello.py`, Python sees the file's time has changed, and it compiles again. If the Python version changes, it also compiles again.

You can delete the `__pycache__` folder any time. Python will simply make it again.

### Does bytecode make Python fast?

Not really. Bytecode is only an *optimisation of the loading step*. Your code does not run faster because of bytecode. The PVM still runs it instruction by instruction.

### Different "Pythons": CPython, Jython, PyPy

Here Aman learns something surprising. "Python" is a *language*. The thing that runs Python is an *implementation*. There are several:

| Implementation | What it is |
| --- | --- |
| **CPython** | The standard, original one. Written in C. This is what you download from [python.org](http://python.org). |
| **Jython** | Runs Python on the Java Virtual Machine. |
| **IronPython** | Runs Python on Microsoft's .NET. |
| **PyPy** | Uses a JIT (Just-In-Time) compiler. Often faster for long-running programs. |
| **Stackless Python** | Focused on concurrency. |

When people say "Python", they almost always mean **CPython**. That is why the `.pyc` file name contains "cpython".

### Practice

1. Fill in the blanks: Python first converts source code into \_\_\_\_\_\_, and then the \_\_\_\_\_\_ runs it.
2. Is bytecode the same as machine code? Yes or No?
3. What does the `312` in `hello.cpython-312.pyc` mean?
4. You run `python main.py` directly. Will Python create `main.cpython-312.pyc` in `__pycache__`? Why or why not?

---

## Part 4: Python in the Shell

Neha opens the terminal and types just one word:

```bash
python3
```

Something new appears:

```plaintext
Python 3.12.1 (main, Dec  8 2023, 14:22:05)
Type "help", "copyright", "credits" or "license" for more information.
>>>
```

This is the **Python shell**, also called the **REPL** (Read, Evaluate, Print, Loop).

- **Read** → it reads what you type
- **Evaluate** → it runs it
- **Print** → it shows the result
- **Loop** → it waits for your next line

The `>>>` symbol is called the **prompt**. It means "Python is ready. Type something."

### Why use the shell?

The shell is a playground. You do not need to create a file. You type, you see the answer immediately.

```python
>>> 2 + 3
5
>>> "chai" + " code"
'chai code'
>>> name = "Aman"
>>> name
'Aman'
>>> len(name)
4
```

Notice: in the shell, you do not even need `print()`. If you type an expression, the shell shows its value.

### Exploring with the shell

Neha shows Aman a few useful tricks.

**Find the current folder:**

```python
>>> import os
>>> os.getcwd()
'/Users/aman/python-practice'
```

**See what a thing can do:**

```python
>>> dir("hello")
```

This prints a long list of all methods a string has (`upper`, `lower`, `split`, and many more).

**Read help:**

```python
>>> help(len)
```

This shows the documentation for `len`.

**Exit the shell:**

```python
>>> exit()
```

### Script vs shell

| Shell | Script file |
| --- | --- |
| Good for quick tests and learning | Good for real programs |
| Code disappears when you close it | Code is saved in a `.py` file |
| Shows results automatically | You must use `print()` |

Neha's rule: **"Not sure how something works? Try it in the shell first."**

![](https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/ec4b515c-22ea-46be-ab6e-c935940b02e9.png align="center")

### Practice

1. What does REPL stand for?
2. Open the Python shell and type `10 * 10`. What do you see?
3. In the shell, type `import os` and then `os.getcwd()`. What does it show?
4. Why do you not need `print()` in the shell for `2 + 3`?

---

## Part 5: Immutable and Mutable in Python

This is the part where Aman's mental model changes forever.

### Everything is an object

In Python, **everything is an object**. The number `10` is an object. The string `"chai"` is an object. A list is an object. Even a function is an object.

Each object lives somewhere in memory and has:

- a **type** (int, str, list, ...)
- a **value** (10, "chai", ...)
- a **reference count** (how many names are pointing to it — more on this later)

### Variables are labels, not boxes

Many beginners think a variable is a *box* that holds a value. Neha says, "No. A variable is a *label* (a name tag) that points to an object."

Look at this:

```python
score = 10
```

What happens:

1. Python creates an integer object `10` in memory.
2. Python creates the name `score`.
3. Python makes `score` *point to* `10`.

Now:

```python
score = 20
```

Python does **not** change the `10` into `20`. It creates a *new* object `20`, and moves the label `score` to point at it. The old `10` now has no label pointing to it, so Python can clean it up.

![](https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/6d6a87cf-5445-411d-a051-5bbd3087c3e0.png align="center")

### Immutable: cannot be changed

Some objects **cannot be changed** after they are created. These are **immutable**.

Immutable types in Python:

- `int` (numbers like 10)
- `float` (like 3.14)
- `str` (strings)
- `bool` (True / False)
- `tuple`

Try to change a string:

```python
>>> drink = "chai"
>>> drink[0] = "C"
TypeError: 'str' object does not support item assignment
```

Python refuses. The string object `"chai"` cannot be edited in place.

"But wait," Aman says, "I can do this:"

```python
>>> drink = "chai"
>>> drink = "coffee"
```

Yes! But that is **not changing the string**. That is **moving the label** to a new string object. The old `"chai"` is still `"chai"`. It is just not used anymore.

This is the key difference:

> **Reassignment** = move the label to a new object. **Mutation** = change the object itself.

Immutable objects allow reassignment but not mutation.

### Mutable: can be changed

Some objects **can** be changed in place. These are **mutable**.

Mutable types:

- `list`
- `dict`
- `set`

Example:

```python
>>> fruits = ["apple", "banana"]
>>> fruits[0] = "mango"
>>> fruits
['mango', 'banana']
```

No error. The *same* list object was modified. The label `fruits` did not move. The object changed.

### Why does this matter?

Aman asks, "Why should I care?"

Neha gives one example that will make sense fully in Part 7:

```python
>>> a = [1, 2, 3]
>>> b = a
>>> a[0] = 100
>>> b
[100, 2, 3]
```

`b` changed, even though Aman only touched `a`! This happens because lists are mutable and `a` and `b` point to the **same** object. We will explore this in detail in Part 7.

### Practice

1. Which of these are immutable? `int`, `list`, `str`, `dict`, `tuple`
2. What will happen here?

   ```python
   name = "python"
   name[0] = "P"
   ```
3. Is this *reassignment* or *mutation*?

   ```python
   x = 5
   x = 6
   ```
4. Is this *reassignment* or *mutation*?

   ```python
   nums = [1, 2]
   nums.append(3)
   ```

---

## Part 6: Python Data Types — The Big Picture

Before going deeper, Neha draws the full map of Python's built-in types on a whiteboard. "You don't need to master all of these today," she says. "Just know they exist."

### 1\. Numbers

```python
age = 25          # int
price = 99.5      # float
z = 3 + 4j        # complex
```

Python also has `Decimal` and `Fraction` for very precise maths (you import them when needed).

### 2\. Strings

```python
name = "chai aur code"
```

Text inside quotes. Single `'...'` or double `"..."` both work.

### 3\. Lists

```python
drinks = ["chai", "coffee", "lassi"]
```

An ordered collection. You can add, remove, and change items. **Mutable.**

### 4\. Dictionaries

```python
menu = {"chai": 10, "coffee": 20}
```

Key–value pairs. Like a real dictionary: word → meaning. **Mutable.**

### 5\. Tuples

```python
point = (3, 4)
```

Like a list, but **immutable**. Once created, cannot be changed.

### 6\. Sets

```python
unique_ids = {1, 2, 3}
```

A collection with **no duplicates** and no fixed order. **Mutable.**

### 7\. Booleans

```python
is_hot = True
```

Only two values: `True` and `False`.

### 8\. None

```python
result = None
```

A special value that means "nothing" or "no value yet".

### 9\. Files

```python
f = open("notes.txt")
```

Files are also objects in Python.

### 10\. Program unit types

Neha points at the last group: **functions, modules, and classes**. These are also objects. You can pass a function to another function. You can store a class in a variable. This idea becomes powerful later.

### 11\. Advanced types (for later)

Things like **decorators**, **generators**, **iterators**, and **metaclasses**. Ignore them for now. They come in future articles.

![](https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/be059800-b18a-4ffd-b5b8-ce4d1fa27b69.png align="center")

### Python is dynamically typed

One more big idea. In languages like C or Java, you must *declare* the type:

```c
int age = 25;
```

In Python, you don't:

```python
age = 25
```

Python looks at the value and decides the type itself. This is called **dynamic typing**. You can even check:

```python
>>> type(age)
<class 'int'>
>>> age = "twenty five"
>>> type(age)
<class 'str'>
```

The same name `age` first pointed to an int, then to a string. The *name* has no type. The *object* has the type.

### Quick table

| Type | Example | Mutable? |
| --- | --- | --- |
| int, float | `10`, `3.5` | No |
| str | `"chai"` | No |
| bool | `True` | No |
| tuple | `(1, 2)` | No |
| list | `[1, 2]` | Yes |
| dict | `{"a": 1}` | Yes |
| set | `{1, 2}` | Yes |
| None | `None` | No |

### Practice

1. What type is each of these? `42`, `"42"`, `42.0`, `[42]`, `(42,)`, `{"n": 42}`
2. What is the difference between a list and a tuple?
3. What will `type(True)` print?
4. Can a set contain the same value twice?

---

## Part 7: Internal Working of Python (References and Memory)

Now Neha brings everything together. "You have seen the pieces. Let's see how Python manages objects in memory."

### Shared references

Go back to the example that surprised Aman:

```python
>>> a = [1, 2, 3]
>>> b = a
```

What does `b = a` do? It does **not** copy the list. It makes `b` point to the **same** list object that `a` points to. Now there are two labels on one object. This is called a **shared reference**.

```plaintext
a ──┐
    ├──> [1, 2, 3]
b ──┘
```

Now:

```python
>>> a[0] = 100
>>> a
[100, 2, 3]
>>> b
[100, 2, 3]
```

Both show `100`, because there is **only one list**. You changed it through `a`, and `b` sees the same change.

![](https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/4223f7f7-0ce6-45ca-9d9b-8f2e9465b12c.png align="center")

### Now the same thing with an immutable type

```python
>>> x = 10
>>> y = x
>>> x = 20
>>> y
10
```

Here `y` is still `10`. Why? Because `x = 20` does **not** change the object `10`. It makes a new object `20` and moves the label `x`. The label `y` still points to `10`.

This is why Part 5 matters. **With immutable objects, shared references are safe. With mutable objects, you must be careful.**

### How to make a real copy

If Aman wants `b` to be a separate list, he must copy it:

```python
>>> a = [1, 2, 3]
>>> b = a[:]          # slice copy
>>> b = a.copy()      # or this
>>> b = list(a)       # or this

>>> a[0] = 100
>>> b
[1, 2, 3]
```

Now `a` and `b` are two different objects. Changing one does not change the other.

(For lists inside lists, you need `copy.deepcopy()` from the `copy` module. That is a topic for another day.)

### `==` vs `is`

Two questions you can ask about objects:

- `==` asks: **Do they have the same value?**
- `is` asks: **Are they the exact same object in memory?**

```python
>>> a = [1, 2, 3]
>>> b = a
>>> c = [1, 2, 3]

>>> a == b
True
>>> a is b
True        # same object

>>> a == c
True        # same value
>>> a is c
False       # different objects
```

Neha's tip: use `==` almost always. Use `is` only for `None` (`if x is None:`).

### The `id()` function

Every object has a unique identity number (its address in memory). You can see it:

```python
>>> a = [1, 2, 3]
>>> b = a
>>> id(a)
140234567891200
>>> id(b)
140234567891200    # same!
```

Same `id` means same object.

### Reference count and garbage collection

Remember that each object has a **reference count**: how many names point to it.

```python
>>> drink = "lassi"     # count = 1
>>> other = drink       # count = 2
>>> drink = "chai"      # "lassi" count = 1
>>> other = "coffee"    # "lassi" count = 0
```

When the count becomes **zero**, no one can reach that object anymore. Python's **garbage collector** removes it from memory automatically. You never have to free memory yourself.

You can even check a reference count (though the number includes a temporary reference from the function call itself, so it looks one higher):

```python
>>> import sys
>>> drink = "lassi"
>>> sys.getrefcount(drink)
```

### A small surprise: Python reuses small numbers

Try this:

```python
>>> a = 10
>>> b = 10
>>> a is b
True
```

`True`? Aman did not write `b = a`. He wrote `b = 10` separately. Why is it the same object?

Because Python **caches small integers** (roughly from -5 to 256) and short strings. When you write `10`, Python reuses the existing `10` object instead of making a new one. This saves memory.

This is safe only because integers are immutable. Nobody can change `10` into `11`, so sharing it causes no harm. **This is the reason immutability matters so much in Python's design.**

![](https://cdn.hashnode.com/uploads/covers/68822b6ad516e7a593530cf9/524a148b-a0b0-494c-990e-e25d076e38d5.png align="center")

### Putting the whole picture together

Here is what Aman now understands when he runs `python hello.py`:

1. Python compiles `hello.py` into **bytecode**.
2. The **PVM** runs the bytecode, one instruction at a time.
3. Each value in the program becomes an **object** in memory.
4. Variable names are **labels** that point to these objects.
5. **Immutable** objects are never changed; labels just move.
6. **Mutable** objects can be changed, and all labels pointing to them see the change.
7. When no label points to an object, the **garbage collector** removes it.

### Practice

1. What is printed?

   ```python
   a = [1, 2]
   b = a
   b.append(3)
   print(a)
   ```
2. What is printed?

   ```python
   a = "hello"
   b = a
   a = "world"
   print(b)
   ```
3. Fix the code so that `b` does **not** change when `a` changes:

   ```python
   a = [1, 2, 3]
   b = a
   a[0] = 99
   ```
4. What is the difference between `==` and `is`?
5. True or False: `a = 5; b = 5; a is b` gives `True` in CPython.

---

## Part 8: Final Quiz

Test yourself. Answers are at the bottom. Try first without looking!

**Q1.** Which website should a beginner use to install Python?

**Q2.** Python converts source code into \_\_\_\_\_\_ before running it.

**Q3.** What is the full form of PVM?

**Q4.** What folder stores compiled `.pyc` files?

**Q5.** Which symbol is the Python shell prompt?

**Q6.** Name three immutable types and three mutable types.

**Q7.** What does this print?

```python
x = (1, 2, 3)
x[0] = 10
```

**Q8.** What does this print?

```python
menu = {"chai": 10}
copy_menu = menu
copy_menu["coffee"] = 20
print(menu)
```

**Q9.** How does Python know when an object can be removed from memory?

**Q10.** Which of these is the standard Python implementation: Jython, CPython, PyPy, IronPython?

---

### Answers

**Part 2:**

1. Your own version (for example, `Python 3.12.x`).
2. So the terminal can find the `python` command from any folder.
3. False. Plain Python from [python.org](http://python.org) is better for learning.

**Part 3:**

1. bytecode, Python Virtual Machine (PVM).
2. No. Bytecode is platform-independent and needs the PVM to run.
3. Python version 3.12.
4. No. `.pyc` files are saved only for imported modules, not the main file you run directly.

**Part 4:**

1. Read, Evaluate, Print, Loop.
2. `100`.
3. The path of your current folder.
4. The shell automatically shows the value of any expression you type.

**Part 5:**

1. `int`, `str`, `tuple` are immutable. `list`, `dict` are mutable.
2. `TypeError` — strings cannot be changed in place.
3. Reassignment.
4. Mutation.

**Part 6:**

1. `int`, `str`, `float`, `list`, `tuple`, `dict`.
2. A list is mutable; a tuple is immutable.
3. `<class 'bool'>`.
4. No. Sets automatically remove duplicates.

**Part 7:**

1. `[1, 2, 3]` — `a` and `b` share the same list.
2. `hello` — strings are immutable; `a = "world"` only moves the label `a`.
3. Use `b = a[:]` or `b = a.copy()` instead of `b = a`.
4. `==` compares values; `is` checks if both names point to the same object.
5. True (because of small integer caching).

**Final Quiz:**

1. [python.org](http://python.org)
2. bytecode
3. Python Virtual Machine
4. `__pycache__`
5. `>>>`
6. Immutable: int, str, tuple (also float, bool). Mutable: list, dict, set.
7. `TypeError` — tuples are immutable.
8. `{'chai': 10, 'coffee': 20}` — both names point to the same dict.
9. When its reference count becomes zero, the garbage collector removes it.
10. CPython.

---

## Epilogue

A week later, Neha asks Aman the same question: *"What happens when you run* `python hello.py`*?"*

This time Aman draws it on paper. Source code becomes bytecode. The PVM runs it. Objects are created in memory. Names point to objects. Immutable objects never change; mutable ones do. When nothing points to an object, it is cleaned up.

Neha nods. "Now you don't just *use* Python. You *understand* it."
