Как получить уникальный идентификатор и имя объекта

Раздел: Основы Python -> Встроенные функции

Идентификация объектов: 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>

Обратите внимание: лямбды имеют одинаковое имя '', но разные id.

Пример 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__

Использование id() и name в Python - comments

En
Python id name (python)