# 191. Python’s F-strings Internals

**1**

**Basic f-string Syntax**

* The simplest way to use an f-string.

```python
name = "Alice"
age = 25
print(f"My name is {name} and I am {age} years old.")
```

🔍 **Under the hood:**

* At runtime, Python replaces `{name}` and `{age}` with their values and evaluates them dynamically.

***

**2**

**f-strings Use `str.format()` Internally**

* f-strings are syntactic sugar for `str.format()`.

```python
name = "Bob"
age = 30

# Equivalent f-string and str.format()
f_string = f"My name is {name} and I am {age} years old."
format_string = "My name is {} and I am {} years old.".format(name, age)

print(f_string)  
print(format_string)
```

🔍 **Under the hood:**

* `f"My name is {name} and I am {age} years old."` is roughly compiled to:

  ```python
  "My name is " + str(name) + " and I am " + str(age) + " years old."
  ```

***

**3. f-strings Evaluate Expressions**

* f-strings can evaluate any expression inside `{}`.

```python
x = 10
y = 5

print(f"The sum of {x} and {y} is {x + y}")
print(f"Half of {x} is {x / 2:.2f}")  # Formatting with 2 decimal places
```

🔍 **Under the hood:**

* The expressions `{x + y}` and `{x / 2:.2f}` are evaluated before string formatting.

***

**4. f-strings Use `__format__()` Internally**

* Python calls the `__format__()` method on objects inside f-strings.

```python
class Person:
    def __init__(self, name):
        self.name = name

    def __format__(self, format_spec):
        return self.name.upper() if format_spec == "upper" else self.name

p = Person("Charlie")

print(f"Hello, {p:upper}!")  # Uses custom __format__() method
```

🔍 **Under the hood:**

* `f"Hello, {p:upper}!"` calls `p.__format__("upper")`, which customizes the output.

***

**5. f-strings are Faster than `str.format()`**

* Since f-strings are evaluated at compile-time, they are faster than `format()`.

```python
import timeit

name = "Daniel"
age = 40

f_time = timeit.timeit(lambda: f"My name is {name} and I am {age} years old.", number=1000000)
format_time = timeit.timeit(lambda: "My name is {} and I am {} years old.".format(name, age), number=1000000)

print(f"f-string time: {f_time}")
print(f"format() time: {format_time}")
```

🔍 **Under the hood:**

* f-strings are compiled to efficient bytecode, avoiding extra function calls like `format()`.

***
