Как получить уникальный идентификатор и имя объекта
Идентификация объектов: id() и атрибут __name__
В Python каждый объект имеет уникальный целочисленный идентификатор, который можно получить с помощью встроенной функции id(). Этот идентификатор остаётся постоянным в течение жизни объекта и может быть использован для сравнения объектов (оператор is). Для получения имени объекта (например, имени функции, класса или модуля) используется атрибут __name__. Эти два инструмента помогают отслеживать объекты и работать с их метаданными.
Пример получения id и имени:
def greet():
return 'Hello'
print(id(greet))
print(greet.__name__)
Python max (функция max в python)
140735670726656
greet
функция bin python (встроенная функция bin() в python)
Функция id возвращает целое число, которое в CPython обычно является адресом объекта в памяти. Атрибут __name__ для функции содержит строку с именем, заданным при определении.
Типичная ошибка: попытка получить __name__ у объекта, у которого его нет, например у числа или строки.
x = 42
print(x.__name__) # AttributeError
Python id name (использование id() и name в python)
AttributeError: 'int' object has no attribute '__name__'
команда open в python (команда open для открытия файлов в python)
Решение: проверять наличие атрибута с помощью hasattr(obj, '__name__').
Как сравнить объекты по id?
Оператор is сравнивает id объектов. Это полезно для проверки, ссылаются ли две переменные на один и тот же объект.
a = [1, 2, 3]
b = a
c = [1, 2, 3]
print(a is b) # True
print(a is c) # False
Enumerate python (функция enumerate в python)
True
False
функция sum в python (функция sum в python)
Ошибка: путаница между is и ==. is проверяет идентичность, == проверяет равенство значений.
Как получить имя переменной по её id?
Иногда требуется узнать, какая переменная ссылается на объект с заданным id. Это можно сделать, перебирая globals(), но такой подход ненадёжен, так как одна переменная может иметь несколько имён.
x = 'привет'
obj_id = id(x)
for name, value in globals().items():
if id(value) == obj_id:
print(name)
функция zip в python (функция zip в python)
x
минимальное целое число python (минимальное целое число)
Проблема: если объект присвоен нескольким переменным, будет найдено только одно имя (первое). Также не работает для объектов в локальных областях видимости или для элементов коллекций.
Как получить имя класса объекта?
Для получения имени класса используется obj.__class__.__name__.
class Car:
pass
c = Car()
print(c.__class__.__name__)
Car
Этот способ работает для любого объекта, так как у всех объектов есть класс.
Как использовать __name__ в модуле для проверки запуска?
Идиома if __name__ == '__main__' позволяет выполнять код только при прямом запуске скрипта, а не при импорте.
# файл example.py
def main():
print('Запущен напрямую')
if __name__ == '__main__':
main()
Ошибка: использование __name__ без понимания, что при импорте модуля оно равно имени модуля (например, 'example'), а не '__main__'.
Как получить имя функции во время выполнения внутри неё?
Атрибут __name__ доступен и внутри функции.
def calc():
print(f'Выполняется функция {calc.__name__}')
calc()
Выполняется функция calc
Расширенные примеры использования id() и __name__
Ниже приведены дополнительные примеры, демонстрирующие различные аспекты работы с id() и атрибутом __name__.
Пример 1: Кэширование малых целых чисел и интернирование строк
Python кэширует целые числа от -5 до 256, поэтому id одинаковых чисел из этого диапазона совпадает. Строки могут интернироваться (особенно короткие).
a = 100
b = 100
print(id(a), id(b)) # одинаковые
c = 257
d = 257
print(id(c), id(d)) # разные (обычно)
s1 = 'hello'
s2 = 'hello'
print(id(s1), id(s2)) # часто одинаковые (интернирование)
140735670726656 140735670726656 140735670726912 140735670727168 140735670727424 140735670727424
Важно: не следует полагаться на интернирование строк, оно может варьироваться.
Пример 2: id() изменяемого объекта не меняется при модификации содержимого
lst = [10, 20]
print(id(lst))
lst.append(30)
print(id(lst)) # тот же
140735670727168 140735670727168
Пример 3: id() для лямбда-функций
f1 = lambda x: x*2
f2 = lambda x: x*2
print(id(f1), id(f2))
print(f1.__name__, f2.__name__)
140735670727232 140735670727296 <lambda> <lambda>
Обратите внимание: лямбды имеют одинаковое имя '
Пример 4: Получение имени переменной через inspect (более продвинутый способ)
import inspect
def get_variable_name(var):
frame = inspect.currentframe().f_back
for name, value in frame.f_globals.items():
if value is var:
return name
return None
x = 42
print(get_variable_name(x))
x
Этот способ использует стек вызовов и может работать медленнее.
Пример 5: Использование id() для проверки, является ли объект тем же после присваивания
original = {'key': 'value'}
alias = original
copy = original.copy()
print(original is alias) # True
print(original is copy) # False
print(id(original) == id(alias)) # True
True False True
Пример 6: Атрибут __name__ у класса и его экземпляра
class MyClass:
pass
obj = MyClass()
print(MyClass.__name__) # 'MyClass'
print(obj.__class__.__name__) # 'MyClass'
# У экземпляра нет __name__
# print(obj.__name__) # AttributeError
MyClass MyClass
Пример 7: Проверка наличия __name__ с помощью hasattr
def test():
pass
objs = [test, 42, 'строка', [1,2], test.__class__]
for obj in objs:
if hasattr(obj, '__name__'):
print(f'{obj} имеет __name__: {obj.__name__}')
else:
print(f'{obj} не имеет __name__')
имеет __name__: test 42 не имеет __name__ строка не имеет __name__ [1, 2] не имеет __name__ не имеет __name__