Найти в Дзене

В Python'е все является объектами. Приложение к видео 2

Оглавление

Доброго времени суток, читатели, зрители моего канала programmer's notes.

Приложение к уроку

Встроенные классы Python

Отойду несколько от порядка, который был задан видео-уроком. Начну с функций, которые не так часто используются в непосредственно в программировании (за исключением, пожалуй type()), но они бывают очень полезны для исследовательской работы программисты.

  • type() - получить тип переменной;
  • id() - получить идентификатор объекта.
  • dir() - получить список методов и свойств объекта;

Функция type()

Простой фрагмент

a = 10
b = 10.234
print(type(a))
print(type(b))

Результат выполнения фрагмента

<class 'int'>
<class 'float'>

Что это означает с точки зрения объектно-ориентированного программирования?

Что переменные a и b являются членами классов или объектами классов. a - объект класса int, класса целых чисел, b - объект класса float, класса чисел с плавающей точкой. Т.е. мы с самого начала нашего вводного курса работали с объектами. И когда мы пишем a = 33 это означает: создается объект - целое число равное 33, создается переменная a, которая указывает на объект.

Ещё один фрагмент

ls = [2, 1, 4]
st = {'qwerty', 2, 1}
print(type(ls))
print(type(st))

Результат выполнения

<class 'list'>
<class 'set'>

Т.е. нами было создано два объекта: класса список и класса множество.

А как программно проверять тип переменной с помощью функции type()? Да все просто

Проверка, что переменная указывает на множество
Проверка, что переменная указывает на множество

Соответственно можно использовать ключевые слова list, int, float, dict и т.д.

С помощью свойства __name__ можно получить строку-название класса и, соответственно писать

if type(ls).__name__ == 'list':

ну и подобным же образом для других типов.

Но есть и другая функция, весьма, кстати, удобная

isinstance() - возвращает True или False.

Вот фрагмент

Еще один вариант проверки
Еще один вариант проверки

Функция id()

Чем интересная данная функция? Она возвращает внутренний идентификатор объекта, на который указывает данная переменная.

Рассмотрим фрагмент

a = 10
b = a
# a и b указывают на один оюъект
print(id(a))
print(id(b))
a = a + 1 # новый объект
# a и b указывают на разные объекты
# b указывает на старый
print(id(a))
print(id(b))
b = 100
# теперь и b указывает на другой объект
# а объект равный 10 остался в памяти без указателя
# и будет автоматически удалён
print(id(a))
print(id(b))

Результат выполнения фрагмента

140380570077776
140380570077776
140380570077808
140380570077776
140380570077808
140380570269136

Соотнесите результат выполнения и текст фрагмента, и всё станет понятным

Числа в python называются статическими типами. Их изменения приводят к созданию нового типа. К статическим типам относятся также строки. Например. запись

s = s.upper()

Создает новый объект, в котором все буквы становятся заглавными по отношению к старому объекту, который будет удалён из памяти.

Другой тип данных динамический. С ним уже не всё так просто.

Следующий фрагмент

ls = [1, 2, 4, 2]
ll = ls
# переменные указывают на один и тот же объект
print(id(ls))
print(id(ll))
ls[3] = 5
# содержимое изменилось, а объект тот же
print(id(ls))
print(id(ll))
ls = ls + [30, 300, 3000]
# а вот теперь ls будет указывать на другой объект
print(id(ls))
print(id(ll))

Результат выполнения фрагмента

140235803221952
140235803221952
140235803221952
140235803221952
140235803167104
140235803221952

Т.е. в одном случае, если мы меняем элемент списка, объект остается тот же, а вот если мы складываем два списка, то создает новый объект, а на старый по-прежнему указывает переменная ll. Тут важно, что два списка складываются. Добавление же элементов, скажем с помощью append() также объект не меняет.

Функция dir()

Это совсем такая забавная функция. В программе ее нет смысла использовать. Это справка по тому, какие методы и свойства есть у объекта или класса. Я то вообще этим никогда не пользуюсь, смотрю документацию - это самый правильный путь, как я думаю. Но для исследования и более глубокого понимания Python, она хороша.

Но вот фрагмент

a = 23
print(dir(a))
print(dir(list))

Результат выполнения

['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__',
'__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__',
'__trunc__', '__xor__', 'as_integer_ratio', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__im
ul__', '__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']

Результат, как видим, выдаётся как список имен методов и свойств. Из примера ясно, что в качестве аргумента может быть и объект и класс. Конечно, некоторые элементы списков нам с вами знакомы. Это касается списка, конечно. С числовыми типами мы не использовали методов. Но при желании, конечно можно

a = 123
b = a.__add__(10)
print(b)
print(a)

Результат выполнения

133
123

Обратим внимание, что метод создает новый объект, в полном соответствии с тем, что числовые типы являются статическими. Обратим также внимание на свойство __doc__, которое по смыслу должно содержать объяснение по данному объекту.

Например

a = 123
print(a.__doc__)
print(a.__add__.__doc__)

Результат выполнения я приводить не буду, чтобы не загромождать изложение. Вы можете сделать это сами. В первом случае дает объяснение фактически класса int. Во втором - описание метода. Но в python всё является объектами, поэтому метод это тоже объект. И у него есть свои методы и свойства (sic!).

Функции тоже, являются объектами класса function. Это проверяется опять с помощью функции type().

Функция, это тоже объект
Функция, это тоже объект

Результат выполнения данного фрагмента

<class 'function'>
None

С классом понятно, но понятно и со свойством __doc__. Мы сами написали функцию и не указали для нее документации. А вот как это можно сделать

Функция с документацией
Функция с документацией

Результат выполнения

Это простая функция для
   демонстрации того, как писать  
   документацию для функции

Ну пока, всё!

Всего наилучшего. Оставляйте свои комментарии, не забывайте про лайки и подписывайтесь на мой канал programmer's notes.

Всюду классы. классы, классы, всюду классы, господа, а без классов жизнь плохая, а без классов никуда.
Всюду классы. классы, классы, всюду классы, господа, а без классов жизнь плохая, а без классов никуда.