Объекты в Python

Содержание
Введение
Равенство по значению и по идентичности
Передача аргументов
Всё является объектом
Размер объекта
Встроенные типы данных
Похожие статьи

Введение

Основной объект в Python, от которого всё наследуется это PyObject python.org

У него есть два атрибута: счётчик ссылок Py_REFCNT и тип Py_TYPE .

Про типы данных в Python можно прочитать много интересного в официальной документации

Про итерацию, итераторы и итерируемые объекты вы можете прочитать в статье «Итерация в Python» , а про типы данных - в статье «Python collections»

Советую изучть встроенные функции dir() и id() , их применение вносит ясность в некоторые особенности питоноских объектов.

Изменяемые и неизменяемые объекты
Итераторы и итерируемые объекты
Python collections
dir()
id()

Равенство по значению и по идентичности

== сравнивает значения объектов.

is проверяет являются ли объекты одним и тем же объектом в памяти. То есть сравнивает ссылки на область в памяти.

# Value vs. Identity Equality print("\n# Value vs. Identity Equality:\n") p = [5, 6, 7] print(f"p = {p}") q = [5, 6, 7] print(f"q = {q}") print(f"p == q: {p == q}") print(f"p is q: {p is q}") print(f"p is p: {p is p}") # Value-equality and identity equality are fundamentally # different concepts. # Comparison by value can be controlled programatically # Identity comparison is unalterable defined # by the language # Value vs. Identity Equality:

p = [5, 6, 7] q = [5, 6, 7] p == q: True p is q: False p is p: True

Не советую злоупотреблять сложными логическими выражениями, поэтому следующий пример, скорее для прохождения специфических собеседований, чем для реального кодинга

Разберём что вернут следующие выражения, а главное, почему они это вернут.

0 == False # True 1 == True # True 2 == True # False 2 == False # False

В Python

0 интерпретируется как False
1 интерпретируется как True
2 не интерпретируется ни как False ни как True

это довольно логично и легко запомнить. Удлинним выражение

Не советую писать что-то похожее, если не хотите запутать тех кто будет читать ваш код.

1 == True is True

True

2 == True is True

False

Результат угадать несложно. Сложнее объяснить. Какие приходят на ум варианты:

# Изначальные выражение 0 == True is True # False 1 == True is True # True 2 == True is True # False # 1 (0 == True) is True # False (1 == True) is True # True (2 == True) is True # False # 2 0 == (True is True) # False 1 == (True is True) # True 2 == (True is True) # False

Оба варианта дают один и тот же результат. Чтобы разобраться есть ли среди них правильный заменим True is True на True is False

# Изначальные выражение 0 == True is False # False 1 == True is False # False 2 == True is False # False # 1 (0 == True) is False # True (1 == True) is False # False (2 == True) is False # True # 2 0 == (True is False) # True 1 == (True is False) # False 2 == (True is False) # False

Оба варианта установки скобок не равносильны изначальному выражению. А всё потому, что Python интерпретирует такое выражение как (0 == True) and (True == False)

# Изначальные выражение 0 == True is True # False 1 == True is True # True 2 == True is True # False 0 == True is False # False 1 == True is False # False 2 == True is False # False (0 == True) and (True is True) # False (1 == True) and (True is True) # True (2 == True) and (True is True) # False (0 == True) and (True is False) # False (1 == True) and (True is False) # False (2 == True) and (True is False) # False

Здесь совпадают значения возвращаемые для всех чисел 0, 1 и 2. Нужно ли знать о такой особенности Python? Возможно. Нужно ли избегать написания кода с такими особенности? Нужно.

Ещё одна причина быть осторожнее с неправильным использованием is кроется в разном поведении Python при запуске скриптов и при использовании интерактивного режима

a = 2 print(a is 2) a = 1234567 print(a is 1234567)

True True C:\demo.py:2: SyntaxWarning: "is" with 'int' literal. Did you mean "=="? print(a is 2) C:\demo.py:4: SyntaxWarning: "is" with 'int' literal. Did you mean "=="? print(a is 1234567)

Теперь в интерактивном режиме

Python 3.12.2 (tags/v3.12.2:6abddd9, Feb 6 2024, 21:26:36) [MSC v.1937 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> a = 2 >>> a is 2 :1: SyntaxWarning: "is" with 'int' literal. Did you mean "=="? True >>> a = 1234567 >>> a is 1234567 :1: SyntaxWarning: "is" with 'int' literal. Did you mean "=="? False

РЕКЛАМА хостинга Beget, которым я пользуюсь более десяти лет

Изображение баннера

Конец рекламы хостинга Beget, который я всем рекомендую.

Передача аргументов

m = [0, 1, 2] print(f"m = {m}") def modify(k): k.append(3) print("k =", k) print("\nmodify(m)\n") modify(m) print(f"m = {m}") print("\nNo copy of m is made\n") print("\nmodify(m)\n") modify(m) print(f"m = {m}")

m = [0, 1, 2] modify(m) k = [0, 1, 2, 3] m = [0, 1, 2, 3] No copy of m is made modify(m) k = [0, 1, 2, 3, 3] m = [0, 1, 2, 3, 3]

Функция modify() работает с тем же объектом, поэтому его значения изменяются. Обойти эту особенность можно с помощью функции copy()

Рассмотрим функцию replace() в которой создается новый объект

f = [4, 5, 6] print("f = ", f) def replace(g): g = [7, 8, 9] print("g =", g) print("\nreplace(f)\n") replace(f) print("f = ", f)

python replace.py

f = [4, 5, 6] replace(f) g = [7, 8, 9] f = [4, 5, 6]

Благодаря тому, что ссылка на старый объект не используется (вместо это переменная g указывает на новый объект) значение переменной f не изменилось.

Можно переписать функцию replace() так, чтобы она заменяла исходный объект.

Назовём новую функцию replace_contents()

def replace_contents(g): g[0] = 20 g[1] = 21 g[2] = 22 print("g = ", g) f = [10, 11, 12] print("f = ", f) print("\nreplace_contents(f)\n") replace_contents(f) print("f = ", f) # Function arguments are transferred using # pass-by-object-reference # References to objects are copied, # not the objects themselves.

python replace_contents.py

f = [10, 11, 12] replace_contents(f) g = [20, 21, 22] f = [20, 21, 22]

Убедиться в том, что если не произведено специальных действий, функция вернёт тот же самый объект довольно просто

def f(d): return d c = [0, 1, 2] print("c = ", c) e = f(c) print("e = f(c)") print(f"c is e: {c is e}")

python return_semantics.py

c = [0, 1, 2] e = f(c) c is e: True

Всё является объектом

Рассмотрим скрипт words.py со следюущим содержанием.

"""Retrieve and print words from a URL. Usage: python3 words.py <URL> """ import sys from urllib.request import urlopen def fetch_words(url): """Fetch a list of words from a URL. Args: url: The URL of a UTF-8 text document. Returns: A list of strings containing the words from the document """ # PEP 257 # story = urlopen("http://sixty-north.com/c/t.txt") story = urlopen(url) story_words = [] for line in story: line_words = line.decode("utf8").split() for word in line_words: story_words.append(word) story.close() return story_words def print_items(story_words): """Print items one per line. Args: An iterable series of printable items. """ for word in story_words: print(word) def main(url): words = fetch_words(url) print_items(words) if __name__ == "__main__": main(sys.argv[1])

python

Python 3.9.5 (default, Jun 15 2021, 15:30:04) [GCC 9.3.0] on linux Type "help", "copyright", "credits" or "license" for more information.

>>> import words
>>> type(words)

<class 'module'>

Получить все атрибуты объекта можно с помощью функции dir()

>>> dir(words)

['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'fetch_words', 'main', 'print_items', 'sys', 'urlopen']

>>> type(words.fetch_words)

<class 'function'>

>>> dir(words.fetch_words)

['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

>>> words.fetch_words.__name__

'fetch_words'

>>> words.fetch_words.__doc__

'Fetch a list of words from a URL.\n \n Args:\n url: The URL of a UTF-8 text document.\n\n Returns:\n A list of strings containing the words from\n the document\n '

Размер объекта в памяти

Стандартным средством определения размера объекта является getsizeof() из sys

Этот метод подходит не всем объектам, подробнее здесь

Встроенные типы данных
None
Built-in Collections
Строки
f-string
format string
Списки []
list comprehension: Абстракция списка
Словари {:}
dict comprehension: Абстракция словаря
Множества {}
set comprehension: Абстракция множества
Кортежи ()
Протоколы
Итерация

Автор статьи: Андрей Олегович

Похожие статьи
Размер объекта
weakref
Основы Python
Встроенные типы данных
Изменяемые и неизменяемые
Итерация
os
dir()
id()

РЕКЛАМА хостинга Beget, которым я пользуюсь более десяти лет

Изображение баннера

Конец рекламы хостинга Beget, который я всем рекомендую.

Поиск по сайту

Подпишитесь на Telegram канал @aofeed чтобы следить за выходом новых статей и обновлением старых

Перейти на канал

@aofeed

Задать вопрос в Телеграм-группе

@aofeedchat

Контакты и сотрудничество:
Рекомендую наш хостинг beget.ru
Пишите на info@urn.su если Вы:
1. Хотите написать статью для нашего сайта или перевести статью на свой родной язык.
2. Хотите разместить на сайте рекламу, подходящую по тематике.
3. Реклама на моём сайте имеет максимальный уровень цензуры. Если Вы увидели рекламный блок недопустимый для просмотра детьми школьного возраста, вызывающий шок или вводящий в заблуждение - пожалуйста свяжитесь с нами по электронной почте
4. Нашли на сайте ошибку, неточности, баг и т.д. ... .......
5. Статьи можно расшарить в соцсетях, нажав на иконку сети: