Объекты в Python

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

Введение

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

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

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

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

id()

Рассмотрим очень полезную для дальнейшего понимания объектом функцию id()

# id() print("# id():\n") a = 1961 print("a = 1961") print(f"id(a) = {id(a)}")

# id(): a = 1961 id(a) = 140042834389712

b = 1065 print("b = 1065") print(f"id(b) = {id(b)}")

b = 1065 id(b) = 140042834389648

b - это новый элемент со своим уникальным id

Если выполнить b = a, то b получит id и значение от a, то есть станет тем же объектом, просто у объекта a появится второе название.

b = a print("b = a") print(f"id(b) = {id(b)}") print(f"id(a) == id(b): {id(a) == id(b)}") print(f"a is b: {a is b}")

b = a id(b) = 140042834389712 id(a) == id(b): True a is b: True

В циклах при увеличении счётчика создаётся новый объект.

i = 0 print("i = 0") print(f"id(i) = {id(i)}") i += 2 print("i += 2") # Создаётся новый объект print(f"id(i) = {id(i)}")

i = 0 id(i) = 140042835400976 i += 2 id(i) = 140042835401008

dir()

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

Рассмотрим обычную строку

print("l =", l) print("m =", m)

['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

А теперь простой список

l = ["l", "m"] print(dir(l))

['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

Видно, что некоторые атрибуты совпадают, а некоторые нет. Например, у строк нет метода copy а у списков upper.

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

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

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

РЕКЛАМА от Яндекса. Может быть недоступна в вашем регионе

Конец рекламы от Яндекса. Если в блоке пусто считайте это рекламой моей телеги

Изменяемые и неизменяемые объекты

Объекты могут быть изменяемыми (mutable) и неизменяемыми (immutable)

Очень хорошей иллюстрацией разницы в их применении являются аргументы по умолчанию

Множество (set) , Словарь (dict) и Список (list) это изменяемые объекты.

Строка - это неизменяемый объект

# Пример 1. Строка a = "aaa" b = a print("a = ", a) print("b = ", b) print("id(a) == id(b):", id(a) == id(b)) # True так как a и b это один и тот же объект print("id(a): ", id(a)) b = "bbb" print("id(a) == id(b):", id(a) == id(b)) # False так как b теперь новый объект print("id(a): ", id(a)) print("id(b): ", id(b)) print("a =", a) print("b =", b)

a = aaa b = aaa id(a) == id(b): True id(a): 2037982796544 id(a) == id(b): False id(a): 2037982796544 id(b): 2037982798368 a = aaa b = bbb

Список - это изменяемый объект, но в этом примере поведение списка и строки пока что одинаковое потому что и
b = "bbb"
и
m = ["m", "m"]
создают новые объекты.

# Пример 1. Список lst = ["l", "l"] m = lst print("lst: ", lst) print("m: ", m) print("id(lst) == id(m): ", id(lst) == id(m)) # True m = ["m", "m"] print("lst = ", lst) print("m = ", m) print("id(lst) == id(m): ", id(lst) == id(m)) # False

lst: ['l', 'l'] m: ['l', 'l'] id(lst) == id(m): True lst = ['l', 'l'] m = ['m', 'm'] id(lst) == id(m): False

А в следующем примере уже видна разница. Изначальная строка a останется без изменений, а вот список l изменится из-за изменения m

# Пример 2. Строка a = "heihei" b = a print("a =", a) print("b =", b) print("id(a) == id(b): ", id(a) == id(b)) # True b += ".ru" print("a =", a) print("b =", b) print("id(a) == id(b): ", id(a) == id(b)) # False # Пример 2. Список lst = ["heihei.ru", "topbicycle.ru"] m = lst print("lst = ", lst) print("m = ", m) print("id(lst) == id(m)", id(lst) == id(m)) # True m.append("beget.com") print("lst =", lst) print("m =", m) print("id(lst) == id(m)", id(lst) == id(m)) # True здесь проявилась изменяемость списка.

a = heihei b = heihei id(a) == id(b): True a = heihei b = heihei.ru id(a) == id(b): False lst = ['heihei.ru', 'topbicycle.ru'] m = ['heihei.ru', 'topbicycle.ru'] id(lst) == id(m) True lst = ['heihei.ru', 'topbicycle.ru', 'beget.com'] m = ['heihei.ru', 'topbicycle.ru', 'beget.com'] id(lst) == id(m) True

С помощью функции id() можно убедиться в том, что строка b стала новым объектом после b += "b" а список m и список l остались одним и тем же объектом.

В следующем примере мы изменим список не с помощью append(), а напрямую, но результат будет таким же.

# Mutable Objects print("\n# Mutable Objects:\n") my_list = [0, 1, 2] print(f"my_list = {my_list}") s = my_list print("s = my_list") print(f"s = {s}") # Изменим элемент в s # и увидим, что и изначальный my_list изменится s[1] = 34 print("s[1] = 34") print(f"s = {s}") # Изменился не только s но и my_list print(f"my_list = {my_list}") print(f"s is my_list: {s is my_list}") # Python doesn't have variables in the sense of boxes # holding a value # Python has named references to objects

python objects_example.py

# Mutable Objects: my_list = [0, 1, 2] s = my_list s = [0, 1, 2] s[1] = 34 s = [0, 34, 2] my_list = [0, 34, 2] s is my_list: True

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

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

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

Похожие статьи
Размер объекта
Основы Python
configparser
docstring
#!: Shebang
Объекты
Итерация
os
pathlib

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

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

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

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

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

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

@aofeed

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

@aofeedchat

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