← Назад к вопросам

Какие переменные можно переопределять системой?

1.0 Junior🔥 161 комментариев
#DevOps и инфраструктура#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Переменные, которые переопределяются системой

В Python есть специальные переменные, которые интерпретатор создаёт и управляет автоматически. Их называют "dunder variables" (double underscore).

1. Встроенные переменные окружения

name — имя модуля при импорте:

# app.py
print(__name__)

if __name__ == "__main__":
    print("Script запущен напрямую")
else:
    print("Script импортирован")

file — путь к файлу модуля:

import os
import sys

script_dir = os.path.dirname(os.path.abspath(__file__))
print(f"Директория скрипта: {script_dir}")

# Добавить путь для импортов
sys.path.insert(0, script_dir)

doc — docstring модуля/класса/функции:

"""
Это docstring модуля.
Описывает назначение.
"""

def my_function(x):
    """Эта функция делает что-то."""
    return x * 2

print(__doc__)  # Docstring модуля
print(my_function.__doc__)  # Docstring функции

2. Переменные класса

class — класс объекта:

class User:
    pass

user = User()
print(user.__class__)  # <class User>
print(user.__class__.__name__)  # User

dict — словарь атрибутов:

class User:
    class_var = "shared"
    
    def __init__(self, name):
        self.name = name

user = User("Alice")
print(user.__dict__)  # {'name': 'Alice'}
print(User.__dict__)  # {'class_var': ..., '__init__': ...}

doc — docstring класса:

class User:
    """Класс пользователя."""
    pass

print(User.__doc__)  # Класс пользователя.

3. Дандер методы (Dunder Methods)

Интерпретатор вызывает их автоматически:

class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email
    
    def __str__(self):  # для print()
        return f"{self.name} ({self.email})"
    
    def __repr__(self):  # для debug
        return f"User(name={self.name!r}, email={self.email!r})"
    
    def __len__(self):  # для len()
        return len(self.name)
    
    def __getitem__(self, key):  # для user[0]
        if key == 0:
            return self.name
        raise IndexError()
    
    def __eq__(self, other):  # для ==
        if not isinstance(other, User):
            return False
        return self.email == other.email
    
    def __lt__(self, other):  # для <
        return self.name < other.name
    
    def __call__(self, msg):  # для user()
        return f"{self.name}: {msg}"
    
    def __del__(self):  # при удалении
        print(f"Удаляем {self.name}")

user = User("Alice", "alice@mail.com")
print(str(user))  # Alice (alice@mail.com) — вызвал __str__
print(repr(user))  # User(name='Alice', email='alice@mail.com')
print(len(user))  # 5 — вызвал __len__
print(user[0])  # Alice — вызвал __getitem__
print(user == User("Bob", "alice@mail.com"))  # True — вызвал __eq__
print(user("hello"))  # Alice: hello — вызвал __call__

4. Переменные функции

name — имя функции:

def process_data(x):
    return x * 2

print(process_data.__name__)  # process_data

doc — docstring функции:

def calculate(a, b):
    """Суммирует два числа."""
    return a + b

print(calculate.__doc__)  # Суммирует два числа.

code — код функции:

def greet(name):
    return f"Hello {name}"

code = greet.__code__
print(code.co_varnames)  # ('name', 'return_value')
print(code.co_argcount)  # 1

defaults — дефолтные значения параметров:

def greet(name, greeting="Hello"):
    return f"{greeting} {name}"

print(greet.__defaults__)  # ('Hello',)

5. Переменные модуля sys

sys.argv — аргументы командной строки:

import sys

print(sys.argv)  # ['script.py', 'arg1', 'arg2']

sys.path — пути поиска модулей:

import sys

print(sys.path)
sys.path.insert(0, '/custom/path')

sys.modules — загруженные модули:

import sys

print(sys.modules.keys())  # все импортированные модули

6. Exception переменные

traceback — стек вызовов при исключении:

import traceback

try:
    1 / 0
except ZeroDivisionError as e:
    print(e.__traceback__)  # stack trace
    traceback.print_exc()

7. Переменные в выполняемом контексте

annotations — типизация:

def add(a: int, b: int) -> int:
    return a + b

print(add.__annotations__)  # {'a': <class 'int'>, 'b': <class 'int'>, 'return': <class 'int'>}

globals — глобальные переменные функции:

GLOBAL_VAR = 42

def get_global():
    return GLOBAL_VAR

print(get_global.__globals__['GLOBAL_VAR'])  # 42

8. Переменные окружения OS

import os

print(os.environ['HOME'])  # Домашняя директория
print(os.environ.get('DATABASE_URL', 'default'))  # С дефолтом

# Установка переменной окружения
os.environ['MY_VAR'] = 'value'

9. Скрытые переменные (name mangling)

class User:
    def __init__(self, password):
        self.__password = password  # Скрыта от внешнего доступа
    
    def check_password(self, pwd):
        return self.__password == pwd

user = User("secret123")
print(user._User__password)  # secret123 — name mangling
print(hasattr(user, '__password'))  # False

10. Переменные контекста (contextvars)

from contextvars import ContextVar
import asyncio

user_id = ContextVar('user_id')

async def task1():
    user_id.set(1)
    print(f"Task 1: {user_id.get()}")

async def task2():
    user_id.set(2)
    print(f"Task 2: {user_id.get()}")

async def main():
    await asyncio.gather(task1(), task2())

asyncio.run(main())
# Task 1: 1
# Task 2: 2 (не пересекается с Task 1)

Best Practices

  1. Не переопределяй dunder переменные напрямую — система управляет ими
  2. Используй name == "main" для проверки, запущен ли скрипт
  3. Не полагайся на file для production — может быть None в некоторых окружениях
  4. Используй os.environ для конфигурации, не переопределяй переменные окружения
  5. Слоты + name mangling для скрытия деталей реализации
  6. Контекстные переменные для потокобезопасности в asyncio

Большинство этих переменных Python создаёт и управляет автоматически, полагаться стоит на документацию.

Какие переменные можно переопределять системой? | PrepBro