Binding In python

  "Execution model" in python:


1. **Structure of a Program**:

   - A Python program is constructed from code blocks, such as modules, function bodies, and class definitions.

   - Each code block is executed in an execution frame.


```python

# A module is a code block

print("This is a module")


def function_block():

    # A function body is a code block

    print("This is a function block")


class MyClass:

    # A class definition is a code block

    print("This is a class block")

```


2. **Binding of Names**:

   - Names refer to objects and are introduced by name binding operations.

   - Names can be bound through formal parameters, class definitions, function definitions, assignments, and import statements, among others.


```python

# Function parameter binding

def greet(name):

    print(f"Hello, {name}!")


# Class definition binding

class Person:

    pass


# Assignment binding

x = 10


# Import binding

import math

```


3. **Resolution of Names**:

   - A scope defines the visibility of a name within a block.

   - Names are resolved using the nearest enclosing scope (LEGB rule: Local, Enclosing, Global, Built-in).

   - The `global` and `nonlocal` statements can modify name resolution.


```python

x = 10  # Global variable


def outer():

    x = 20  # Enclosing variable


    def inner():

        x = 30  # Local variable

        print(x)  # Output: 30


    inner()

    print(x)  # Output: 20


outer()

print(x)  # Output: 10

```


4. **Annotation Scopes**:

   - Annotation scopes are introduced by type parameter lists and type statements.

   - Annotation scopes behave mostly like function scopes but with some exceptions (e.g., access to enclosing class namespace).


```python

class MyClass:

    type Alias = int


    def func[T: Alias]() -> T:

        return T(42)


print(MyClass.func())  # Output: 42

```


5. **Lazy Evaluation**:

   - The values of type aliases and the bounds and constraints of type variables are lazily evaluated.

   - Evaluation happens when necessary to resolve an attribute access.


```python

from typing import Literal


type Alias = 1/0  # No exception yet

print(Alias.__value__)  # ZeroDivisionError is raised here


def func[T: 1/0](): pass

T = func.__type_params__[0]

print(T.__bound__)  # ZeroDivisionError is raised here

```


6. **Builtins and Restricted Execution**:

   - The `__builtins__` namespace is an implementation detail and should not be touched directly.

   - The builtins namespace is found by looking up `__builtins__` in the global namespace.


7. **Interaction with Dynamic Features**:

   - Name resolution of free variables occurs at runtime, not compile time.

   - The `eval()` and `exec()` functions have limited access to the environment for resolving names.


```python

i = 10

def f():

    print(i)  # Resolved at runtime

i = 42

f()  # Output: 42

```


These key points cover the execution model, name binding and resolution, annotation scopes, lazy evaluation, builtins, and interactions with dynamic features in Python. The provided code examples illustrate the concepts and their usage.

Post a Comment

Previous Post Next Post