Какие переменные можно переопределять системой?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Переменные, которые переопределяются системой
В 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
- Не переопределяй dunder переменные напрямую — система управляет ими
- Используй name == "main" для проверки, запущен ли скрипт
- Не полагайся на file для production — может быть None в некоторых окружениях
- Используй os.environ для конфигурации, не переопределяй переменные окружения
- Слоты + name mangling для скрытия деталей реализации
- Контекстные переменные для потокобезопасности в asyncio
Большинство этих переменных Python создаёт и управляет автоматически, полагаться стоит на документацию.