Какого встроенного типа данных нет в python
Перейти к содержимому

Какого встроенного типа данных нет в python

  • автор:

Изменяемые и неизменяемые типы данных в Python

Python считается одним из самых удивительных языков программирования. Многие люди выбирают его в качестве первого языка из-за его элегантности и простоты. Благодаря широкому сообществу, избытку пакетов и согласованности синтаксиса, опытные профессионалы также используют Python. Тем не менее, существует одна вещь, которая раздражает как новичков, так и некоторых профессиональных разработчиков – объекты Python.

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

Как известно, объектом в Python является абсолютно все, а каждый объект относится к какому-либо типу данных. Типы данных бывают изменяемые и неизменяемые (англ. mutable и immutable). К неизменяемым относятся целые числа (int), числа с плавающей запятой (float), булевы значения (bool), строки (str), кортежи (tuple). К изменяемым — списки (list), множества (set), байтовые массивы (byte arrays) и словари (dict).

Функции id() и type()

Разобраться с изменяемостью типов данных нам помогут встроенные функции и операторы Python.

Встроенный метод id() возвращает идентификатор объекта в виде целого числа. Это целое число обычно относится к месту хранения объекта в памяти. Встроенная функция type() возвращает тип объекта.

Что касается операторов, для определения идентичности переменных мы можем использовать == , а is используется для определения того, указывают ли переменные на один и тот же объект. Почитать подробнее об отличиях этих операторов можно здесь.

Если сравнить две переменные, x и y , имеющие одинаковое значение, при помощи оператора равенства ( x == y ), он выдаст True. Но если мы при помощи того же оператора сравним идентификаторы объектов x и y (полученные с использованием функции id() ) – мы получим False. Дело в том, что во втором случае мы сравнивали адреса памяти переменных, а они разные – расположены в разных местах. Хотя значения, которые содержат эти переменные, одинаковы.

x = 'Привет!' y = 'Привет!' x == y # Получим True id(x) == id(y) # Получим False

Создадим переменную z путем присвоения ей в качестве значения переменной x . Используя оператор is , мы обнаружим, что обе переменные указывают на один и тот же объект и, соответственно, имеют одинаковые идентификаторы.

x = 'Привет!' z = x x is z # Получим True id(x) == id(z) # Получим True

Неизменяемые типы данных

Давайте рассмотрим некоторые неизменяемые типы.

Целые числа (int)

Давайте определим переменную x , имеющую значение 10. Встроенный метод id() используется для определения местоположения x в памяти, а type() используется для определения типа переменной. Когда мы пытаемся изменить значение x , оно успешно изменяется.

Стоит заметить, что адрес памяти тоже изменяется. Так происходит потому, что фактически мы не изменили значение x , а создали другой объект с тем же именем x и присвоили ему другое значение. Мы связали имя x с новым значением. Теперь, когда вы вызываете x , он будет выводить новое значение и ссылаться на новое местоположение.

x = 10 print(x, type(x), id(x)) # Получим (10, int, 140727505991744)
x = 12 print(x, type(x), id(x)) # Получим (12, int, 140727505991808)

Строки (str)

То же самое верно и для строкового типа данных. Мы не можем изменить существующую переменную, вместо этого мы должны создать новую с тем же именем.

В данном примере мы определили строковую переменную x , но допустили ошибку в слове и теперь хотим исправить «ю» на «и». Однако мы получаем TypeError. Это показывает, что строковые объекты не подлежат обновлению.

x = 'Прювет!' x[2] = 'и' # Получим TypeError: 'str' object does not support item assignment

Кортежи (tuple)

Давайте разберем кортежи. Мы определили кортеж с 4 значениями. Воспользуемся функцией id() для вывода его адреса. Если мы захотим изменить значение первого элемента, то получим ошибку TypeError. Это означает, что кортеж не поддерживает присвоение или обновление элементов.

tuple1 = (1, 2, 3, 4) print(tuple1, id(tuple1)) # Получим (1, 2, 3, 4) 3240603720336

С другой стороны, мы можем обновить весь кортеж, задав его с нуля. После этого мы увидим новые значения элементов кортежа и новый адрес.

tuple1 = (5, 6, 7, 8) print(tuple1, id(tuple1)) # Получим (5, 6, 7, 8) 3240603720256

Числа с плавающей запятой (float)

У нас есть переменная x типа float. Используя функцию id() , мы можем узнать ее адрес. Если мы попробуем заменить элемент с индексом 1, то получим TypeError. Как и в предыдущих примерах видим, что float не поддерживает модификацию элемента.

x = 3.456 x[1] = 4 # Получим TypeError: 'float' object does not support item assignment

Если же мы обновим float, переопределив его, то при вызове получим новое значение и новый адрес.

x = 3.654 type(x), id(x) # Получим (float, 3240603166960)

Изменяемые типы данных

Теперь давайте рассмотрим некоторые изменяемые типы.

Списки (list)

Определим список с именем x и добавим в него некоторые значения. После этого обновим список: присвоим новое значение элементу с индексом 1. Можем заметить, что операция успешно выполнилась.

x = ['Яблоко', 'Груша', 'Слива'] x[1] = 'Ананас' x # выведет ['Яблоко', 'Ананас', 'Слива']

Вышеописанные действия являются простым и базовым примером модификации. Чтобы проверить изменчивость на более глубоком уровне, давайте рассмотрим тот же пример с небольшими изменениями.

Создадим новое имя y и свяжем его с тем же объектом списка. А теперь проверим, совпадает ли x с y . Нам вернется True. Кроме того, x и y имеют одинаковые адреса памяти.

x = y = ['Яблоко', 'Груша', 'Слива'] x is y # True id(x), id(y), id(x) == id(y) # (3240602862208, 3240602862208, True)

Теперь добавим новое значение к списку x и проверим обновленный вывод.

x.append('Персик') x # ['Яблоко', 'Груша', 'Слива', 'Персик']

Если мы теперь вызовем y , то получим тот же список, что и при вызове x . Хотя непосредственно в y мы ничего не добавляли. Это означает, что по сути мы обновляем один список объектов, у которого есть два разных имени: x и y . Оба они одинаковы и имеют один адрес в памяти даже после модификации.

y # ['Яблоко', 'Груша', 'Слива', 'Персик'] x is y, id(x) == id(y) # (True, True)

Словари (dict)

Словари — часто используемый тип данных в Python. Давайте посмотрим на их изменчивость.

Определим словарь под именем dict с тремя ключами и их значениями. Когда мы распечатаем его, отобразится все его содержимое. Можно распечатать каждое значение словаря отдельно, а также использовать ключи вместо индексов. Подробнее о добавлении элементов в словарь вы можете узнать тут.

dict = dict # Получим dict['Name'], dict['Age'], dict['Job'] # ('Алиса', 27, 'Senior Python Developer')

Давайте изменим какое-нибудь значение в нашем словаре. Например, обновим значение для ключа Name . Выведем обновленный словарь. Значение изменилось. При этом сами ключи словаря неизменяемы.

dict[‘Name’] = ‘Роберт’ dict #

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

Давайте по отдельности определим список и кортеж. Убедимся, что в кортеже есть значение типа список, а в списке есть значение типа кортеж.

tuple1 = ([1, 1], 2, 3) list1 = [(1, 1), 2, 3] tuple1, list1 # (([1, 1], 2, 3), [(1, 1), 2, 3])

Нулевой элемент кортежа – список. Давайте попробуем изменить какой-то из элементов списка, указав его индекс. Например, можно поменять в нулевом элементе кортежа (т.е. в списке) нулевой элемент. Нам успешно удается это сделать, потому что список – изменяемый объект, даже если он находится в кортеже.

tuple1[0][0] = 'Поменялся' tuple1 # (['Поменялся', 1], 2, 3)

Если же, наоборот, кортеж находится в списке, то вы не сможете поменять элемент этого кортежа, хотя он и находится в изменяемом списке. Ведь сам кортеж неизменяем. Поэтому такие преобразования невозможны.

list1[0][0] = 'Поменялся' list1 # Получим TypeError: 'tuple' object does not support item assignment

Заключение

Мы разобрали различия между изменяемым и неизменяемым объектами в Python. Стоит понимать, что всё в Python называется объектами. И главное различие между ними – являются они изменяемыми или неизменяемыми.

Типы данных в Python 3

В Python, как и в других языках программирования, все данные для удобства делятся на типы. Тип данных определяет значения, которые можно присваивать, и действия, которые можно выполнять.

Данное руководство ознакомит вас с основными встроенными типами данных python.

Основы работы с типами данных

Хорошим примером типов данных являются данные, которые используются в реальном мире: целые числа (0, 1, 2…), иррациональные числа (π), и т.п.

Как правило, в математических операциях можно комбинировать числа различных типов, например:

При этом можно оставить в качестве ответа полученное уравнение, а также можно округлить π до 3.14 и сложить числа:

5 + π = 5 + 3.14 = 8.14

Но если мы попытаемся решить уравнение, в котором кроме чисел будут присутствовать другие типы данных, например слова, мы не получим никакого вменяемого результата. К примеру, как бы вы решили следующее уравнение?

Компьютеры строго разграничивают все типы данных, потому нужно очень внимательно присваивать значения и использовать их в различных операциях.

Числа

Любая цифра воспринимается в python как число. При этом не обязательно объявлять, какой тип данных вы вводите. Python воспринимает любое число, записанное без десятичных знаков, как целое число (например, 133), а любое число, записанное с десятичными знаками, в качестве числа с плавающей точкой (например, 138.0).

Целые числа

Как и в математике, в компьютерном программировании целые числа – это натуральные числа, которые могут быть положительными, отрицательными, или равняться 0 (…,-1, 0, 1, …). Целое число можно отметить как int. Как и в других языках, в python не нужно использовать запятую при написании многозначных чисел (к примеру, тысяча записывается как 1000, а не как 1,000).

Чтобы вывести целое число, используйте такой синтаксис:

Также можно объявить переменную (в данном случае она является символом числа, которое нужно вывести):

my_int = -25
print(my_int)
-25

Также python умеет выполнять математические операции с целыми числами:

int_ans = 116 — 68
print(int_ans)
48

Целые числа широко используются в программах python.

Числа с плавающей точкой

Число с плавающей точкой (или float) – это действительное число (это означает, что оно может быть как рациональным, так и иррациональным числом). Числа с плавающей точкой могут содержать дробную часть (например, 9.0 или -116.42). Проще говоря, python воспринимает любое число с десятичной точкой как число с плавающей точкой.

Чтобы вывести число с плавающей точкой, используйте:

Также вы можете объявить переменную:

my_flt = 17.3
print(my_flt)
17.3

Как и с целыми числами, python умеет выполнять математические операции с числами с плавающей точкой:

flt_ans = 564.0 + 365.24
print(flt_ans)
929.24

При работе с целыми числами и числами с плавающей точкой важно помнить, что 3 и 3.0 – не одно и то же. 3 ≠ 3.0, поскольку 3 – целое число, а 3.0 – число с плавающей точкой.

Логический тип

Логический тип данных (или boolean) – это примитивный тип данных, который принимает одно из двух возможных значений: истину (true) или ложь (false). Этот тип присутствует во многих языках программирования и используется для построения алгоритмов.

Примечание: Название этого типа данных (Boolean) всегда пишется с заглавной буквы, поскольку этот тип назван в честь математика Джорджа Буля, который занимался вопросами математической логики. Значения True и False тоже пишутся с большой буквы, так как в Python они являются специальными значениями.

Многие математические операции можно расценивать как истинные или ложные:

500 > 100 True
1 > 5 False
200 < 400 True
4 < 2 False
5 = 5 True
500 = 400 False

Как и в случае с числами, значения Boolean можно определять переменными:

Теперь можно вывести значение переменной с помощью функцииprint():

Поскольку 5 меньше 8, на экране появится:

Строки

Строка представляет собой последовательность из одного или нескольких символов (букв, цифр и других символов), которые могут быть постоянными или переменными. В Python троки обозначаются одинарными (‘) или двойными кавычками (“). Чтобы создать строку, заключите последовательность символов в кавычки:

‘This is a string in single quotes.’
«This is a string in double quotes.»

Одинарные и двойные кавычки работают одинаково. Важно только использовать один и тот же тип кавычек в рамках одной программы.

Простая программа Hello, World демонстрирует применение строк в программировании (последовательность символов, из которых состоит фраза «Hello, World!», является строкой).

Строки можно хранить в переменных:

hw = «Hello, World!»

Чтобы вывести значение переменной, введите:

print(hw)
Hello, World!

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

Списки

Список – это изменяемая, упорядоченная последовательность элементов. Значения, которые находятся в списке, называются элементами. Подобно тому, как строки определяются кавычками, списки определяются квадратными скобками ([]).

Список целых чисел выглядит так:

Список чисел с плавающей точкой имеет такой вид:

[3.14, 9.23, 111.11, 312.12, 1.05]

[‘shark’, ‘cuttlefish’, ‘squid’, ‘mantis shrimp’]

Для примера можно определить список sea_creatures:

sea_creatures = [‘shark’, ‘cuttlefish’, ‘squid’, ‘mantis shrimp’]

Чтобы вывести этот список, введите:

print(sea_creatures)
[‘shark’, ‘cuttlefish’, ‘squid’, ‘mantis shrimp’]

Списки – очень гибкий тип данных, который позволяет быстро добавить, удалить или изменить данные. В Python существует тип данных, очень похожий на списки, но который нельзя изменять. Такой тип называется кортежем.

Кортежи

Кортеж (tuple) позволяет группировать данные. Кортеж – это неизменяемая упорядоченная последовательность элементов.

Кортежи очень похожи на списки, но вместо квадратных скобок они используют круглые скобки. Кроме того, как уже говорилось, данные этого типа нельзя изменять.

Кортеж имеет такой вид:

(‘blue coral’, ‘staghorn coral’, ‘pillar coral’)

Кортеж можно хранить в переменной и вывести на экран:

coral = (‘blue coral’, ‘staghorn coral’, ‘pillar coral’)
print(coral)
(‘blue coral’, ‘staghorn coral’, ‘pillar coral’)

Словари

Словарь – это неупорядоченный изменяемый массив данных, состоящий из пар «ключ-значение». Словари обозначаются фигурными скобками (<>).

Словари обычно хранят связанные данные. Словарь имеет такой вид:

Кроме фигурных скобок, в словарях используется двоеточие. Слева от двоеточия пишутся ключи, в данном случае это ‘name’, ‘animal’, ‘color’, ‘location’.

Справа от двоеточия находятся значения. Значения могут быть представлены любым типом данных. В приведённом примере значениями являются ‘Jake’, ‘dog’, ‘yellow’, ‘Tree Fort’.

Попробуйте создать переменную для словаря, а затем вывести её на экран.

Чтобы запросить только один из элементов словаря, используйте квадратные скобки. Например:

Заключение

Теперь вы знакомы с основными типами данных Python и можете применять их при разработке программ.

Введение в типы данных Python

Python :: Учебник для начинающих

  • Как данные представлены в Python?
  • Базовые типы данных в Python
  • Динамическая типизация в Python
  • О приведении типов в Python
  • Получение помощи по объектам в Python
  • Краткие итоги параграфа
  • Вопросы и задания для самоконтроля

Как данные представлены в Python?

Когда мы имеем дело со значениями в программе, например, присваивая их для хранения переменной или передавая в качестве аргументов функции, нам приходится манипулировать различными типами этих значений ( ) такими, например, как числа или строки. В Python , как и в других языках программирования, имеется как встроенный комплект стандартных типов данных, так и возможность определять собственные пользо­вательские типы данных. При этом следует помнить про одну важную особенность – все данные в Python представлены в виде объектов, которые представляют собой выделенные области памяти со значениями данного типа и определенными для этих значений наборами операций (см. пример №1 ).

Код Результат pythonCodes

# Импортируем модуль. import sys # Интерпретатор автоматически выделит под значения в памяти # место, определит тип значений и набор операций для их # обработки, т.е. создаст в памяти два объекта. str_1 = 'Большой ' str_2 = 'дом.' # Выведем на экран типы этих значений. Для этого используем # общедоступную встроенную функцию type(obj) print('Тип объекта str_1: ', type(str_1)) print('Тип объекта str_2: ', type(str_2), end='\n\n') # Выведем объемы занимаемой значениями памяти. Метод getsizeof(obj) # модуля sys стандартной библиотеки возвращает размер объекта в байтах. print('Объем str_1: ', sys.getsizeof(str_1), 'байт') print('Объем str_2: ', sys.getsizeof(str_2), 'байт', end='\n\n') # Объединим эти строки в одну и выведем на экран. print(str_1 + str_2, end='\n\n') # Узнаем, что еще можно делать, например, с первым объектом. print(dir(str_1))
Тип значения в переменной str_1: Тип значения в переменной str_2: Объем памяти, занимаемый str_1: 90 байт Объем памяти, занимаемый str_2: 82 байт Большой дом. ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__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', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill'] 

Пример №1. Определение типа и размера данных.

Как видим, Python предоставляет нам довольно обширный стандартный набор операций над строковыми объектами (надеюсь вы не забыли про кнопку «Результат» ). Тоже самое касается и других встроенных типов. Если же программисту вдруг станет тесно, он всегда может разработать собственный тип данных и определить для него необходимый набор операций.

Базовые типы данных Python

Давайте с целью первичного ознакомления перечислим некоторые основные типы данных встроенные в Python .

  • Числа – это целые ( -8 , 0 , 47 ), вещественные ( -0.54 или -.54 , 0.0 , 2.475 ) и комплексные числа ( -3+5j , 77+2j ). Все они относятся к неизменяемым типам данных.
  • Строки – это текст произвольной длины, взятый в одинарные, двойные или тройные кавычки. Например, ’25 яблок’ , «Ok, Python!» , »’Строка в тройных кавычках так»’ , «»»или так.»»» . Строки также являются неизменяемым типом данных, хотя получить доступ к символу строки можно по его индексу.
  • Списки – это упорядоченные неименованные изменяемые коллекции значений (объектов), например, [‘A’, ‘B’, ‘C’] или [2, [True, False], «house»] . Литерал списка задается квадратными скобками, внутри которых через запятую перечисляются значения любых типов данных включая и сами списки. Доступ к значениям списка осуществляется по индексам (об этом чуть позже).
  • Кортежи – это упорядоченные неименованные неизменяемые коллекции значений (объектов), например, (‘A’, ‘B’, ‘C’) или (2, «house», True) . Литерал кортежа задается круглыми скобками, внутри которых через запятую перечисляются значения неизменяемых типов данных. Доступ к значениям осуществляется по индексам. Но, т.к. кортежи являются неизменяемыми последовательностями, то добавлять или удалять элементы из них нельзя.
  • Словари – это именованные изменяемые неупорядоченные коллекции значений (объектов), например, . Литерал словаря задается фигурными скобками, внутри которых через запятую перечисляются пары ключ: значение . В качестве ключей в принципе можно использовать любые неизменяемые уникальные значения, например, числа или строки, а в качестве значений вообще любые типы объектов, включая другие словари. Доступ к значениям в словаре осуществляется по ключам.
  • Множества – это неименованные и неупорядоченные изменяемые коллекции уникальных и неизменяемых значений (объектов), например, . Литерал множества задается фигурными скобками, внутри которых через запятую перечисляются значения неизменяемых типов данных. Сами множества являются изменяемыми коллекциями значений, но вот значения в коллекции должны относиться к неизменяемым типам вроде чисел и строк.
  • Логические значения – этот тип данных содержит всего две булевых константы: True и False .
  • NoneType – специальное значение None , которое означает отсутствие значения.

Чтобы узнать тип объекта, используемого в программе, можно воспользоваться встроенной функцией type(obj) , которой в качестве аргумента нужно передать интересующий нас объект (см. пример №2 ). Функция является встроенной в интерпретатор Питона , поэтому ее не нужно импортировать и она общедоступна для использования из любой точки программы. Посмотреть весь список встроенных функций можно в справочнике стандартной библиотеки в разделе Built-in Functions.

Код Результат pythonCodes

# Не забываем про кнопку Результат! # Именованный аргумент end задает концовку вывода. # Здесь мы задали двойной перевод строки end='\n\n'. print('--- Числа ---', end='\n\n') # Выводим тип целого числа. print('5: ', type(5)) # Выводим тип числа с плавающей точкой. print('7.033: ', type(7.033)) # Выводим тип комплексного числа. print('-0.2+3j: ', type(-0.2+3j), end='\n\n') print('--- Строки ---', end='\n\n') # Строка в одинарных кавычках. print('\'Строка\': ', type('Строка')) # Строка в двойных кавычках. print('"Строка": ', type("Строка")) # Строка в тройных кавычках. print('"""Строка""": ', type("""Строка"""), end='\n\n') print('--- Списки ---', end='\n\n') # Проверим, является ли этот литерал списком. print('["one", [1,2], 0]: ', type(["one", [1,2], 0])) # Так можно задавать пустой список. print('[]: ', type([]), end='\n\n') print('--- Кортежи ---', end='\n\n') # Проверим, является ли этот литерал кортежем. print('("one", (1,2), 0): ', type(("one", (1,2), 0))) # Так можно задавать пустой кортеж. print('(): ', type(()), end='\n\n') print('--- Словари ---', end='\n\n') # Проверим, является ли этот литерал словарем. dict = print(": ", type(dict)) # Так можно задавать пустой словарь. print('<>: ', type(<>), end='\n\n') print('--- Множества ---', end='\n\n') # Проверим, является ли этот литерал множеством. print(": ", type()) # Так можно задавать пустое множество (литерала нет). print('set(): ', type(set()), end='\n\n') print('--- Булевы значения ---', end='\n\n') # Проверим, являются ли эти литералы булевыми значениями. print('True: ', type(True)) print('False: ', type(False), end='\n\n') print('--- Значение None ---', end='\n\n') # Проверим, является ли этот литерал NoneType. print('None: ', type(None), end='\n\n')
--- Числа --- 5: 7.033: -0.2+3j: --- Строки --- 'Строка': "Строка": """Строка""": --- Списки --- ["one", [1,2], 0]: []: --- Кортежи --- ("one", (1,2), 0): (): --- Словари --- : <>: --- Множества --- : set(): --- Булевы значения --- True: False: --- Значение None --- None:

Пример №2. Литералы встроенных типов данных в исходном коде.

Хотелось бы добавить, что встроенные типы данных можно классифицировать по нескольким признакам: изменяемые (списки, словари, множества) и неизменяемые (числа, строки, кортежи, логические значения, значение None ), а также упорядоченные (строки, списки, кортежи) и неупорядоченные (словари и множества). Эта классификация очень важна для понимания возможностей типов и области их применения. Однако здесь мы в подробности углубляться не будем, оставив более детальное рассмотрение перечисленных типов данных до последующих параграфов нашего учебника.

Динамическая типизация в Python

Как упоминалось ранее, Python относится к языкам программирования с динамической типизацией данных. Давайте рассмотрим это понятие подробнее.

– это прием, при котором переменная связывается с типом в момент присваивания значения, а не в момент объявления переменной.

Это значит, что в Python программисту не нужно объявлять тип переменной в исходном коде. Интерпретатор делает это автоматически во время присвоения переменной нового значения. При этом он самостоятельно контролирует объем памяти, распределяемый под вновь создаваемый объект (см. пример №3 ).

Объем памяти, занимаемой любым объектом, можно узнать при помощи метода sys.getsizeof(obj) модуля sys стандартной библиотеки, который возвращает размер объекта в байтах. В качестве аргумента методу необходимо передать интересующий нас объект.

Проверить объект на принадлежность к типу можно при помощи встроенной функции isinstance(obj, type) , которой в качестве аргументов нужно передать проверяемый объект, а также имя типа. Если имя типа объекта совпадает с типом объекта, то функция вернет True , иначе – False .

Код Результат pythonCodes

# Импортируем модуль sys стандартной библиотеки. import sys # Присвоим переменной целое число. d = 33 # Проверим тип переменной. print('Тип переменной d: ', type(d)) # Узнаем ее размер в байтах. print('Размер d в байтах: ', sys.getsizeof(d), end='\n\n') # Теперь присвоим той же переменной словарь. d = # Тип по-прежнему int? print("Тип d все еще int?: ", isinstance(d, int)) # А какой тогда? print("Новый тип переменной d: ", type(d)) # А размер изменился? print('Новый размер d в байтах: ', sys.getsizeof(d))
Тип переменной d: Размер d в байтах: 28 Тип d все еще int?: False Новый тип d: Новый размер переменной d в байтах: 232 

Пример №3. Динамическая типизация в действии.

Как видим, интерпретатор все сделал за нас. Однако при этом не стоит забывать, что мы сами должны следить за тем, чтобы в выражениях использовались значения допустимых типов (см. пример №4 ). Например, если в текущем фрагменте кода мы делим переменные, следует самим следить за тем, чтобы в обоих на момент выполнения операции хранились числа, иначе может возникнуть ошибка.

Код Результат pythonCodes

# Присвоим переменной число с плавающей точкой. d = 33.47 # Присвоим переменной строку. s = '33.47' # Попробуем сложить res = d + s # и затем вывести результат на экран. print(res) # Получили вполне ожидаемую ошибку.
unsupported operand type(s) for +: 'float' and 'str' 

Пример №4. Неправильное использование значений различных типов.

Хорошо, а где интерпретатор хранит тип значения? Все очень просто. Как мы уже говорили, в Python все состоит из объектов. Переменные как таковые типа не имеют. Когда в коде программы мы присваиваем переменной значение, интерпретатор создает для значения объект, в котором хранятся как тип значения, так и набор допустимых для данного типа операций. Самой же переменной присваивается только ссылка на этот объект. Таким образом в Python переменные не хранят сами значения, а только ссылаются на объекты присваиваемых им значений. Когда же мы присваиваем переменной другое значение, ей присваивается новая ссылка, указывающая на объект нового значения. А прежний объект, если он больше не используется в программе, просто удаляется, т.е. задействуется механизм автоматической сборки мусора .

О приведении типов в Python

Довольно часто в программе требуется преобразовать значение одного типа данных в другой. Например, когда пользователь вводит данные для вычислений в строковом виде, перед вычислениями возникает необходимость преобразования строки в число (см. пример №5 ). Если этого не сделать, то мы получим либо ошибку (как в предыдущем примере), либо совсем неожиданный результат.

Для передачи в программу данных, вводимых пользователем с клавиатуры, используется встроенная функция input() , которая останавливает текущий поток программы до тех пор, пока пользователь не введет все данные и не нажмет Enter . При этом функции можно передавать в качестве аргумента строку с сообщением, которое будет выведено пользователю на экран. Таким сообщением обычно бывает подсказка о типе вводимых данных или призыв к какому-то действию.

Код Результат pythonCodes

# Просим ввести 1-е число с плавающей точкой. d = input('Введите 1-е вещественное число: ') # Просим ввести 2-е число с плавающей точкой. s = input('Введите 2-е вещественное число: ') # Я ввел 2.44 и 3.27 (см. Результат). # Преобразуем строки в вещественые числа. d = float(d) s = float(s) # А вот теперь сложим res = d + s # и выведем результат на экран. print('d + s =', res) 
Введите 1-е вещественное число: 2.44 Введите 2-е вещественное число: 3.27 d + s = 5.71 

Пример №5. Приведение типов в Python (часть 1).

В примере выше для преобразования строки в число мы использовали встроенную функцию float() . Кроме того, для преобразования различных типов данных между собой всегда доступны и другие встроенные функции (конструкторы типов): bool() , int() , complex() , str() , tuple() , list() , dict() или set() (см. пример №6 ). О каждой из них мы поговорим подробнее, когда будем рассматривать вопрос приведения типов в конце этой главы.

Код Результат pythonCodes

# Преобразуем строку в список. li = list('abc') # Посмотрим, что получилось. print('Строка -> список: ', li, end='\n\n') # Вещественное число преобразуем в целое. int_num = int(11.24) print('float -> int: ', int_num) # Строковое представление числа в число. float_num = float("11.24") print('"11.24" -> float: ', float_num, end='\n\n') # Преобразуем что-то в логический тип. bool_1 = bool(1) print('1 -> bool: ', bool_1) bool_2 = bool(0) print('0 -> bool: ', bool_2) # Строку с буквами в bool. bool_3 = bool('яблоко') print('str -> bool: ', bool_3) # Пустой объект в bool ('', [], <> и т.д.). bool_4 = bool([]) print('[] -> bool: ', bool_4, end='\n\n') # А вот здесь получим ошибки преобразования. # Число не является итерируемым объектом. li_1 = list(5) # Буквы не получится преобразовать, нужно число. int_num = int('яблоко') 
Строка -> список: ['a', 'b', 'c'] float -> int: 11 "11.24" -> float: 11.24 1 -> bool: True 0 -> bool: False str -> bool: True [] -> bool: False 'int' object is not iterable 

Пример №6. Приведение типов в Python (часть 2).

Как можно было убедиться на примере, во избежание ошибок в процессе преобразования типов нужно следить за возможностью такого преобразования. В общем случае, например, один тип числа легко преобразуется в другие числа, итерируемые объекты – в другие итерируемые объекты, а в логический тип можно преобразовать вообще все что угодно.

Получение помощи по объектам Python

Ранее мы уже отмечали, что в языке Python повсюду присутствуют объекты, которые представляют собой данные и наборы операций (методы) для обработки этих данных. Методы и данные, кстати, называют атрибутами объекта. Доступ к атрибутам любого объекта осуществляется через точку и имя атрибута. А чтобы узнать, какие атрибуты имеет данный объект, можно воспользоваться очередной встроенной функцией dir() , которой в качестве аргумента следует передать требуемый объект. Результатом будет словарь со всеми атрибутами объекта (см. пример №7 ).

Если необходимо узнать количество элементов какой-нибудь последовательности или коллекции, например, строки или словаря, проще всего воспользоваться встроенной функцией len() , которой нужно передать требуемый объект в качестве аргумента.

Код Результат pythonCodes

# Давайте создадим строковый объект. str_1 = 'Конь в пальто!' # Выведем все атрибуты на экран и поэкспериментируем с ними. print(dir(str_1), end='\n\n') # Поищем подстроку па (выведет нам 7, т.е. индекс первого # вхождения подстроки в строке начиная с нуля). print(str_1.find('па')) # Переведем все символы строки в верхний регистр. print(str_1.upper(), end='\n\n') # Узнаем возможности типа int, используя его имя. # Ведь даже сами типы – это тоже объекты! d = dir(int) # А сколько вообще атрибутов у целочисленного типа? print('Количество атрибутов типа int:', len(d), end='\n\n') # Выведем их все на экран (см. Результат). print(d) 
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__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', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill'] 7 КОНЬ В ПАЛЬТО! Количество атрибутов типа int: 71 ['__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']

Пример №7. Получение атрибутов объектов.

Таким образом, если в процессе создания программы мы забудем, например, какие методы имеются в Python для обработки строк, всегда можно воспользоваться функцией dir() . Это касается объектов не только встроенных типов данных, но и созданных пользователем.

Но и это еще не все! Интерпретатор Python реально поставляется под ключ. Поэтому в комплекте имеется собственный встроенный справочник, что очень даже удобно (см. пример №8 ). Ведь типов данных довольно много и для каждого из них имеются не только общие, но и свои индивидуальные методы обработки этих данных. Так что, если информации предоставляемой функцией dir() становится недостаточно и хочется получить более подробную справку, следует обращаться за помощью к встроенной функции help() , передав ей в качестве аргумента интересующий нас объект.

Обратите внимание, что запись в коде, например, my_func означает имя функции и сам объект функции. А выражение my_func() означает вызов этой функции. Так вот, когда в качестве аргумента нужно передать объект функции, следует передавать только ее имя и не использовать скобки.

Код Результат pythonCodes

# Давайте создадим строковый объект. str_1 = 'Конь одел кеды!' # А теперь получим подробную справку по методу find. help(str_1.find) # Просто отделим блоки информации. print('\n\n') # А давайте запросим подробную справку по всему типу. help(str) 
Help on built-in function find: find(. ) method of builtins.str instance S.find(sub[, start[, end]]) -> int Return the lowest index in S where substring sub is found, such that sub is contained within S[start:end]. Optional arguments start and end are interpreted as in slice notation. Return -1 on failure. Help on class str in module builtins: class str(object) | str(object='') -> str | str(bytes_or_buffer[, encoding[, errors]]) -> str | | Create a new string object from the given object. If encoding or | errors is specified, then the object must expose a data buffer | that will be decoded using the given encoding and error handler. | Otherwise, returns the result of object.__str__() (if defined) | or repr(object). | encoding defaults to sys.getdefaultencoding(). | errors defaults to 'strict'. | | Methods defined here: | | __add__(self, value, /) | Return self+value. | | __contains__(self, key, /) | Return key in self. | | __eq__(self, value, /) | Return self==value. -- Далее --

Пример №8. Получение справки по объектам.

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

Следует иметь в виду, что на экран информация выводится частями. Поэтому желательно максимально уточнять запрос (как в примере выше), чтобы не приходилось многократно нажимать Enter для вывода очередного блока информации.

Краткие итоги параграфа

  • Все данные в Python представлены в виде объектов, которые представляют собой выделенные области памяти со значениями данного типа и определенными для этих значений наборами операций.
  • К базовым типам данных Пайтона относятся числа ( int , float , complex ), строки ( str ), списки ( list ), кортежи ( tuple ), словари ( dict ), множества ( set ), булевы значения ( bool ) и специальное значение None ( NoneType ).
  • Python относится к языкам программирования с динамической типизацией данных, поэтому программисту не нужно объявлять тип переменной в исходном коде. Интерпретатор делает это автоматически во время присвоения переменной нового значения. При этом он самостоятельно контролирует объем памяти, распределяемый под вновь создаваемый объект.
  • Переменные в Python хранят не само значение, а ссылки на объект этого значения.
  • Для преобразования одного встроенного типа данных в другой можно пользоваться соответствующими функциями (конструкторами типов): bool() , int() , float() , complex() , str() , tuple() , list() , dict() или set() . Однако нужно быть внимательным и во избежание ошибок проверять возможность такого преобразования.
  • Для получения списка атрибутов объекта предназначена встроенная функция dir() , которой в качестве аргумента должен передаваться требуемый объект. Результатом будет словарь со всеми атрибутами объекта.
  • Для получения более подробной справки по объектам следует использовать встроенную функцию help() , которой в качестве аргумента также нужно передавать требуемый объект.

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

Вопросы и задания для самоконтроля

1. Определите устно типы следующих значений: ‘123’ , [1,2,3] , , 123 , , (1,2,3) . Показать решение.

Ответ. ‘123’ – строка (т.е. тип str ), [1,2,3] – список (т.е. тип list ), – множество (т.е. тип set ), 123 – целое число (т.е. тип int ), – словарь (т.е. тип dict ), (1,2,3) – кортеж (т.е. тип tuple ).

2. Выполните предыдущее задание, организовав вывод типов на экран при помощи скрипта. Показать решение.

Решение Результат pythonCodes

# Присвоим значения переменным. v_1 = '123' v_2 = [1,2,3] v_3 = v_4 = 123 v_5 = v_6 = (1,2,3) # Для определения типа значений используем функцию type(obj). print("Тип ", v_1, ": ", type(v_1), sep='') print("Тип ", v_2, ": ", type(v_2), sep='') print("Тип ", v_3, ": ", type(v_3), sep='') print("Тип ", v_4, ": ", type(v_4), sep='') print("Тип ", v_5, ": ", type(v_5), sep='') print("Тип ", v_6, ": ", type(v_6), sep='') 

Тип 123: Тип [1, 2, 3]: Тип : Тип 123: Тип : Тип (1, 2, 3):

3. Переменной li присвоили список [1, 2, 3] . В ходе выполения программы в список были добавлены еще два значения и он принял вид [1, 2, 3, 4, 5] . На сколько изменился объем памяти, занимаемый переменной? Показать решение.

Решение Результат pythonCodes

# Импортируем модуль sys стандартной библиотеки. import sys # Узнаем исходный размер, занимаемый переменной. li = [1, 2, 3] vol_1 = sys.getsizeof(li) # Узнаем конечный размер, занимаемый переменной. li = [1, 2, 3, 4, 5] vol_2 = sys.getsizeof(li) # Вычисляем изменение объема. v = vol_2 - vol_1 # Выводим результат на экран. print('Объем изменился на ', v, ' байт.', sep='')
Объем изменился на 16 байт.

4. Что такое динамическая типизация? Показать решение.

Ответ. – это прием, при котором переменная связывается с типом в момент присваивания значения, а не в момент объявления переменной.

5. Напишите код программы, которая будет запрашивать у пользователя два целых числа, а затем выводить на экран их произведение. Показать решение.

Решение pythonCodes

# Просим ввести 1-е целое число. d = input('Введите 1-е целое число: ') # Просим ввести 2-е целое число. s = input('Введите 2-е целое число: ') # Преобразуем строки в целые числа. d = int(d) s = int(s) # Перемножим их. res = d*s # И выведем результат на экран. print('Произведение чисел равно ', res)

6. У какого типа больше атрибутов: tuple или list ? Сперва попытайтесь догадаться устно, а затем вычислите программно и выведите их атрибуты на экран. Показать решение.

Ответ. Поскольку кортежи относятся к неизменяемым последовательностям, то скорее всего у них будет меньше методов для обработки своих данных, чем у списков. Ведь списки могут изменяться, а значит для них должны быть доступны дополнительные методы, например, для удаления или добавления новых элементов. Это конечно все несколько субъективно, но тем не менее давайте проверим.

Решение Результат pythonCodes

# Получаем словарь атрибутов типа tuple. t = dir(tuple) # Выводим их количество на экран. print('Количество атрибутов типа tuple:', len(t), end='\n\n') # Выведем все атрибуты на экран. print(t, end='\n\n') # Получаем словарь атрибутов типа list. li = dir(list) # Выводим их количество на экран. print('Количество атрибутов типа list:', len(li), end='\n\n') # Выведем все атрибуты на экран. print(li)
Количество атрибутов типа tuple: 33 ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index'] Количество атрибутов типа list: 46 ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__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']

7. Получите описание функции len , использовав встроенную справку. Показать решение.

Решение Результат pythonCodes

# Используем функцию help(). help(len) 
Help on built-in function len in module builtins: len(obj, /) Return the number of items in a container.

8. Какая из рассмотренных нами функций len() , type() , print() , isinstance() , dir() , help() или input() содержится в модуле sys ? Как мы можем получить доступ к ней? Показать решение.

Ответ. Все перечисленные функции являются встроенными и не требуют импорта модуля стандартной библиотеки sys . Но с одной такой функцией мы уже познакомились – это функция getsizeof() . Чтобы ее использовать, сперва нужно импортировать указанный модуль при помощи инструкции import sys .

Быстрый переход к другим страницам

  • Синтаксис Python
  • Введение в типы данных Python
  • Числа в Python
  • Вернуться к оглавлению учебника

Ok, Python!

okpython.net Copyright © 2022-2024.

Краткий обзор раздела: Основные встроенные типы Python

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

Утиная типизация ‘Duck Typing’ в Python.

Утиная типизация заключается в том, что вместо проверки типа чего-либо в Python мы склонны проверять, какое поведение оно поддерживает (часто пытаясь использовать это поведение и перехватывая исключение, если оно не работает.

Что такое вызываемый объект callable в Python?.

Вызываемый объект callable — это все, что можно вызвать, используя круглые скобки. Вызываемые объекты часто принимают аргументы (которые заключаются в круглые скобки). В этом материале объясняется, почему происходит такая путаница между классами и функциями в Python.

Как проверить тип переменной/объекта в Python.

Для проверки типов лучше всего подходит функция isinstance, так как она поддерживает наследование (экземпляр производного класса также является экземпляром базового класса), а проверка на равенство типов — нет (требуется идентичность типов и отклоняет экземпляры подтипов, также называемых подкласса

Логический тип данных bool в Python.

Логический тип представлен двумя постоянными значениями False и True. Значения используются для представления истинности.

Целые числа int в Python.

Целые числа int имеют неограниченную точность и являются неизменяемыми объектами, поэтому, выполняя операцию над целыми числами, вы получаете новый числовой объект.

Ограничение длины преобразования целочисленной строки в Python.

CPython имеет глобальное ограничение на преобразование между int и str для смягчения атак типа «отказ в обслуживании». Это ограничение применяется только к десятичным или другим системам счисления, не равным степени двойки. Лимит можно настроить.

Вещественные числа float в Python.

Числа с плавающей запятой float, их еще называют вещественными числами — это последовательность десятичных цифр, которая включает десятичную точку .

Комплексные числа complex в Python.

Комплексное число complex состоит из двух чисел с плавающей точкой, представляющих соответственно его действительную и мнимую части. Доступ к обеим частям комплексного объекта x обеспечивают атрибуты x. real и x. imag, доступные только дл

Типы последовательностей в Python.

Существуют Изменяемые и НЕизменяемые типы последовательностей. Доступ к неизменяемым последовательностям быстрее, чем к изменяемым. Неизменяемые последовательности очень «дороги» для изменения, потому что для этого необходимо создать копию, а менять

Список list в Python.

Списки представляют собой изменяемые последовательности, обычно используемые для хранения коллекций однородных элементов. В Python списки представлены встроенным классом list().

Кортеж tuple в Python.

В Python кортежи представлены классом tuple(). Это неизменяемые последовательности, обычно используемые для хранения коллекций разнородных данных. Кортежи используются в тех случаях, когда требуется неизменяемая последовательность однородных данных

Диапазон range в Python.

Тип range — диапазон, представляет собой неизменяемую последовательность чисел и обычно используется для выполнения определенного количества раз циклов for. Диапазоны range представлены в языке Python классом range().

Текстовые строки str в Python.

Текстовые данные в Python обрабатываются с помощью встроенного класса str() или по другому тип str. Строки представляют собой неизменяемые последовательности Юникода.

Словарь dict в Python.

В языке Python тип данных словарь dict представлен встроенным классом dict(). Ключи словаря — это произвольные, неизменяемые (хэшируемые) значения. Словари можно создать, поместив разделенный запятыми список пар ключ: значение в фигур

Множество set и frozenset в Python.

Множество в Python3 — это неупорядоченный набор различных хешированных hashable объектов. Обычно множества используются в тестировании вхождения элемента, удаление дубликатов из последовательности и вычисление математических операций.

Итератор Iterator, протокол итератора в Python.

Python поддерживает концепцию итерации над контейнерами. Это реализовано с использованием двух разных методов (iterator.__iter__( ) и iterator.__next__( )), они используются для того, чтобы пользовательские классы могли поддерживать итерации.

Генератор generator в Python и выражение yield.

Тип generator (генератор) похож на тип iterator (итератор), но тип generator не хранит значения последовательности в памяти, а генерирует/вычисляет результат на лету — в ходе каждого вызова, тем самым экономит память и вычислительные ресурсы.

Контекстный менеджер with в Python.

Оператор with в Python поддерживает концепцию контекста среды выполнения, определенного контекстным менеджером. Протокол контекстных менеджеров реализован с помощью пары методов, которые позволяют определяемым пользователем классам определять конте

Байтовые строки bytes в Python.

Тип данных bytes это неизменяемые последовательности отдельных байтов. Двоичные протоколы основаны на кодировании текста ASCII. Объекты bytes могут быть созданы с помощью встроенного класса bytes().

Байтовый массив bytearray в Python.

Объекты bytearray являются **изменяемым** аналогом bytes объектов. Выделенного литерального синтаксиса для объектов bytearray нет, вместо этого они всегда создаются путем вызова конструктора встроенного класса bytearray().

Тип memoryview в Python, буфер обмена.

Объекты `memoryview` позволяют коду Python получать доступ к внутренним данным объекта, который поддерживает протокол буфера обмена, без копирования. `Memoryview` имеет понятие элемента, который является атомарной единицей памяти.

Файловый объект file object в Python.

Файловый объект file object, это объект, предоставляющий файлово-ориентированный API с такими методами, как file.read() или file.write() базовому ресурсу.

Универсальный псевдоним GenericAlias в Python.

Объекты GenericAlias создаются путем подписки на класс (обычно контейнер), например list[int]. Они предназначены для аннотаций типов. Объект GenericAlias ​​реализует параметризованные универсальные шаблоны — конкретный универсальный экземпляр, который предоставляет типы для элементов контейнера.

Объект объединения Union в Python.

Объект объединения Union содержит значение операции | (побитовая или) над объектами нескольких типов. Этот тип в первую очередь предназначен для аннотаций типов.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *