Главная страница
Навигация по странице:

  • Закрепление пройденного Контрольные вопросы

  • Отсутствие инструкций объявления

  • Переменные, объекты и ссылки

  • Имена

  • Информация о типе хранится в объекте

  • Объекты уничтожаются автоматически

  • Математический анализ. 3е издание


    Скачать 4.86 Mb.
    Название3е издание
    АнкорМатематический анализ
    Дата04.02.2022
    Размер4.86 Mb.
    Формат файлаpdf
    Имя файлаpython_01.pdf
    ТипДокументы
    #351981
    страница22 из 98
    1   ...   18   19   20   21   22   23   24   25   ...   98
    164
    Глава 5. Числа
    Расширения сторонних разработчиков
    Помимо встроенных числовых типов собственно языка Python вы мо
    жете встретить различные свободно распространяемые расширения сторонних разработчиков, реализующие еще более экзотические чи
    словые типы. К таким типам можно отнести рациональные числа, век
    торы и матрицы. Модули, реализующие эти типы, можно загрузить из
    Сети, там же вы найдете более подробную информацию о них.
    В заключение
    В этой главе были рассмотрены типы числовых объектов языка Python и операции, применяемые к ним. Здесь мы познакомились со стан
    дартными целочисленными типами и с числами с плавающей точкой,
    а также с некоторыми экзотическими, нечасто используемыми типа
    ми, такими как комплексные числа и числа с фиксированной точно
    стью. Мы также исследовали синтаксис выражений в языке Python,
    порядок преобразования типов, битовые операции и различные лите
    ральные формы представления чисел в сценариях.
    Далее, в этой же части книги, мы рассмотрим следующий тип объек
    тов – строки. Однако в следующей главе мы потратим некоторое время на более подробное ознакомление с механизмом операции присваива
    ния значений переменным. Это, пожалуй, самая фундаментальная идея в языке Python, поэтому вам обязательно нужно прочитать следую
    щую главу. Но перед этим ответьте на контрольные вопросы главы.
    Закрепление пройденного
    Контрольные вопросы
    1. Каким будет значение выражения 2 * (3 + 4) в языке Python?
    2. Каким будет значение выражения 2 * 3 + 4 в языке Python?
    3. Каким будет значение выражения 2 + 3 * 4 в языке Python?
    4. Какие функции можно использовать для вычисления квадратного корня числа и квадрата?
    5. Какой тип будет иметь результат следующего выражения: 1 + 2.0 +3?
    6. Каким образом можно выполнить усечение и округление числа с плавающей точкой?
    7. Как им образом можно преобразовать целое число в число с плаваю
    щей точкой?
    8. Каким образом можно вывести целое число в восьмеричном и шест
    надцатеричном представлениях?
    9. Каким образом можно преобразовать строковое представление вось
    меричного или шестнадцатеричного числа в простое целое число?

    Закрепление пройденного
    165
    Ответы
    1. Результатом выражения будет число 14, то есть результат произве
    дения 2 * 7, потому что круглые скобки предписывают выполнить операцию сложения до операции умножения.
    2. В данном случае результат будет равен 10, то есть результат выра
    жения 6 + 4. При отсутствии круглых скобок в языке Python ис
    пользуются правила старшинства операторов, согласно которым оператор умножения имеет более высокий приоритет, чем оператор сложения (стоящий левее).
    3. Данное выражение даст в результате число 14, то есть результат вы
    ражения 2 + 12, согласно тем же правилам старшинства, что и в пре
    дыдущем вопросе.
    4. Функции вычисления квадратного корня, а также числа пи, тан
    генса и многие другие доступны в импортируемом модуле math. Что
    бы найти квадратный корень числа, необходимо импортировать мо
    дуль math и вызвать функцию math.sqrt(N). Чтобы найти квадрат числа, можно воспользоваться либо оператором возведения в сте
    пень X ** 2, либо встроенной функцией pow(X, 2).
    5. Результатом будет число с плавающей точкой: целые числа будут преобразованы в числа с плавающей точкой, как к наиболее слож
    ному числовому типу в выражении, и для вычисления результата будет использоваться математика вещественных чисел.
    6. Функция int(N) выполняет отсечение дробной части, а функция round(N,
    digits?) выполняет округление.
    7. Функция float(N) выполняет преобразование целых чисел в числа с плавающей точкой. Смешивание целых чисел и чисел с плаваю
    щей точкой в одном выражении также приводит к выполнению преобразования.
    8. Встроенные функции oct(I) и hex(I) возвращают строковые пред
    ставления целых чисел в восьмеричном и в шестнадцатеричном фор
    матах. Для этих же целей может использоваться строка формата %.
    9. Для преобразования строковых представлений восьмеричных и ше
    стнадцатеричных чисел в обычные целые числа может использо
    ваться функция int(S, base?). Для этих целей может также исполь
    зоваться функция eval(S), но она более медленная и может стать ис
    точником проблем, связанных с безопасностью. Обратите внима
    ние: целые числа в памяти компьютера всегда хранятся в двоичном формате, для вывода которых просто используются разные форма
    ты представления.

    6
    Интерлюдия о динамической типизации
    В предыдущей главе мы приступили к детальному исследованию базо
    вых типов объектов в языке Python, начав с чисел. Мы продолжим на
    ши исследования типов в следующей главе, но прежде чем продол
    жить, вам необходимо разобраться в самой фундаментальной, на мой взгляд, идее программирования на языке Python, которая составляет основу гибкости языка – динамической типизации и полиморфизме.
    Как будет показано в этой главе и далее в книге, в сценариях на языке
    Python не производится объявление объектов определенных типов.
    В действительности нам даже не приходится беспокоиться о конкрет
    ных типах; более того, они могут применяться в более широком диапа
    зоне ситуаций, чем можно было предусмотреть заранее. Поскольку ди
    намическая типизация составляет основу этой гибкости, давайте ко
    ротко ознакомимся с этой моделью.
    Отсутствие инструкций объявления
    Если у вас имеется опыт работы с компилирующими языками или с языками, обладающими статической типизацией, такими как C,
    C++ или Java, вероятно, эта тема в книге вызывает у вас недоумение.
    Мы все время использовали переменные, не объявляя ни их самих, ни их типы, и все както работало. Например, когда вводится инструкция a
    = 3 в интерактивной оболочке интерпретатора или в файле сценария,
    как интерпретатор Python узнает, что речь идет о целом числе? И вооб
    ще, как Python узнает, что есть что?
    Как только вы начинаете задавать такие вопросы, вы попадаете в сфе
    ру действия модели динамической типизации, используемой в языке
    Python. В языке Python типы определяются автоматически, во время выполнения, а не в результате объявлений в программном коде. Это

    Отсутствие инструкций объявления
    167
    означает, что вам не требуется заранее объявлять переменные (эту кон
    цепцию проще понять, если иметь в виду, что все сводится к перемен
    ным, объектам и ссылкам между ними).
    Переменные, объекты и ссылки
    Как было видно из примеров, приводившихся до сих пор в книге, ко
    гда запускается операция присваивания, такая как a = 3, интерпрета
    тор выполняет ее, хотя перед этим ему нигде не сообщалось, что a – это имя переменной, или что она представляет объект целочисленного ти
    па. В языке Python все это решается весьма естественным способом,
    как описано ниже:
    Создание переменной
    Переменная (то есть имя), такая как a, создается автоматически,
    когда в программном коде ей впервые присваивается некоторое значение. Все последующие операции присваивания просто изме
    няют значение, ассоциированное с уже созданным именем. Строго говоря, интерпретатор Python определяет некоторые имена до за
    пуска программного кода, но вполне допустимо думать, что пере
    менные создаются первой операцией присваивания.
    Типы переменных
    Переменные не имеют никакой информации о типе или ограниче
    ниях, связанных с ним. Понятие типа присуще объектам, а не име
    нам. Переменные универсальны по своей природе – они всегда яв
    ляются всего лишь ссылками на конкретные объекты в конкретные моменты времени.
    Использование переменной
    Когда переменная участвует в выражении, ее имя замещается объек
    том, на который она в настоящий момент ссылается, независимо от того, что это за объект. Кроме того, прежде чем переменную можно будет использовать, ей должно быть присвоено значение – исполь
    зование неинициализированной переменной приведет к ошибке.
    Эта модель существенно отличается от традиционных языков програм
    мирования. Динамическая типизация обычно проще поддается пони
    манию начинающих, особенно если они четко осознают разницу между именами и объектами. Например, если ввести такую инструкцию:
    >>> a = 3
    интерпретатор Python выполнит эту инструкцию в три этапа, по край
    ней мере, концептуально. Следующие этапы отражают все операции присваивания в языке Python:
    1. Создается объект, представляющий число 3.
    2. Создается переменная a, если она еще отсутствует.
    3. Переменная связывается с новым объектом, представляющим чис
    ло 3.

    168
    Глава 6. Интерлюдия о динамической типизации
    Результатом выполнения этих этапов будет структура, которая пока
    зана на рис. 6.1. Как показано на схеме, переменные и объекты хра
    нятся в разных частях памяти и связаны между собой ссылкой (ссыл
    ка на рисунке показана в виде стрелки). Переменные всегда ссылают
    ся на объекты и никогда на другие переменные, но крупные объекты могут ссылаться на другие объекты (например, объект списка содер
    жит ссылки на объекты, которые включены в список).
    Эти ссылки на объекты в языке Python так и называются ссылки, то есть ссылки – это своего рода ассоциативная связь, реализованная в виде указателя на область памяти.
    1
    Когда бы ни использовалась пе
    ременная (то есть ссылка), интерпретатор Python автоматически пере
    ходит по ссылке от переменной на объект. Все на самом деле гораздо проще, чем кажется. В конкретных терминах:

    Переменные
    – это записи в системной таблице, где предусмотрено место для хранения ссылок на объекты.

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

    Ссылки
    – это автоматически разыменовываемые указатели на объ
    екты.
    Всякий раз, по крайней мере концептуально, когда в сценарии в ре
    зультате выполнения выражения создается новое значение, интерпре
    татор Python создает новый объект (то есть выделяет область памяти),
    1
    Читатели, знакомые с языком C, сочтут, что между ссылками в языке Py
    thon и указателями в языке C много общего (адреса в памяти). И действи
    тельно, ссылки реализованы как указатели и они часто играют ту же роль,
    особенно когда объект относится к категории изменяемых (подробнее об этом будет говориться ниже). Однако, так как ссылки при использовании всегда автоматически разыменовываются, вы никак не сможете использо
    вать саму ссылку – эта особенность ликвидирует огромный пласт ошибок,
    которые можно допустить в языке C. Вы можете считать ссылки указате
    лями типа «void» в языке C, которые автоматически разыменовываются при любом использовании.
    Имена
    Ссылки
    Объекты
    a
    3
    Рис. 6.1. Имена и переменные после выполнения операции присваивания a = 3.
    Переменная превращается в ссылку на объект 3. Во внутреннем
    представлении переменная в действительности является
    указателем на пространство памяти с объектом, созданным
    в результате интерпретации литерального выражения 3

    Отсутствие инструкций объявления
    169
    представляющий это значение. Внутренняя реализация интерпретато
    ра, с целью оптимизации, кэширует и повторно использует некоторые типы неизменяемых объектов, такие как малые целые числа и строки
    (каждый 0 в действительности не является новой областью в памяти,
    но подробнее о механизме кэширования мы поговорим позже). Но с ло
    гической точки зрения все выглядит так, как если бы результат каж
    дого выражения был представлен отдельным объектом и каждый объ
    ект занимал отдельную область памяти.
    С технической точки зрения объекты имеют более сложную структу
    ру, чем просто пространство в памяти, необходимое для хранения зна
    чения. Каждый объект имеет два стандартных поля: указатель типа,
    используемый для хранения информации о типе объекта, и счетчик
    ссылок
    , используемый для определения момента, когда память, зани
    маемая объектом, может быть освобождена. Чтобы понять, какую роль играют эти два поля в модели динамической типизации, нам не
    обходимо двинуться дальше.
    Информация о типе хранится в объекте,
    но не в переменной
    Чтобы увидеть, как используется информация о типах объектов, по
    смотрим, что произойдет, если выполнить несколько операций при
    сваивания одной и той же переменной:
    >>> a = 3 # Это целое число
    >>> a = 'spam' # Теперь это строка
    >>> a = 1.23 # Теперь это число с плавающей точкой
    Это не совсем типичный программный код на языке Python, но он ра
    ботает – сначала создается целое число, потом строка и, наконец, чис
    ло с плавающей точкой. Этот пример особенно странно выглядит для программистов, использовавших язык C, поскольку он выглядит так,
    как если бы при выполнении инструкции a = 'spam' производилось из
    менение типа переменной с целочисленного на строковый.
    Однако в действительности этого не происходит. В языке Python все реа
    лизовано намного проще: имена не имеют типов, как уже указывалось ранее, тип – это свойство объекта, а не имени. В предыдущем листинге просто изменяется ссылка на объект. Так как переменные не имеют ти
    пов, мы в действительности не изменяем типы переменных – мы просто записываем в переменные ссылки на объекты других типов. На самом деле все, что можно сказать о переменных в языке Python, – это то, что они ссылаются на конкретные объекты в конкретные моменты времени.
    С другой стороны, объекты знают, к какому типу они относятся, – ка
    ждый объект содержит поле, в котором хранится информация о его ти
    пе. Целочисленный объект 3, например, будет содержать значение 3
    плюс информацию, которая сообщит интерпретатору Python, что объ
    ект является целым числом (строго говоря – это указатель на объект

    170
    Глава 6. Интерлюдия о динамической типизации с названием int, которое играет роль имени целочисленного типа). Ука
    затель типа для строки 'spam' указывает на строковый тип (с именем str
    ). Поскольку информация о типе хранится в объектах, ее не нужно хранить в переменных.
    Итак, типы в языке Python – это свойства объектов, а не переменных.
    В типичном программном коде переменная обычно ссылается на объ
    екты только одного типа. Так как для языка Python это не является обязательным требованием, программный код на языке Python обла
    дает более высокой гибкостью, чем вам может показаться, – при уме
    лом использовании особенностей языка программный код смог бы ра
    ботать со многими типами автоматически.
    Я уже упоминал, что каждый объект имеет два поля – указатель типа и счетчик ссылок. Чтобы разобраться с последним из них, нам нужно пойти еще дальше и взглянуть, что происходит в конце жизненного цикла объекта.
    Объекты уничтожаются автоматически
    В листинге из предыдущего раздела мы присваивали одной и той же переменной объекты различных типов. Но что происходит с прежним значением, когда выполняется новое присваивание? Например, что произойдет с объектом 3 после выполнения следующих инструкций:
    >>> a = 3
    >>> a = 'spam'
    Дело в том, что всякий раз, когда имя ассоциируется с новым объек
    том, интерпретатор Python освобождает память, занимаемую преды
    дущим объектом (если на него не ссылается какоелибо другое имя или объект). Такое автоматическое освобождение памяти, занимаемой объектами, называется сборкой мусора (garbage collection).
    Чтобы проиллюстрировать сказанное, рассмотрим следующий при
    мер, где с имя x ассоциируется с разными объектами при выполнении каждой операции присваивания:
    >>> x = 42
    >>> x = 'shrubbery' # Освобождается объект 42 (если нет других ссылок)
    >>> x = 3.1415 # Теперь освобождается объект 'shrubbery'
    >>> x = [1,2,3] # Теперь освобождается объект 3.1415
    Первое, что следует отметить, – каждый раз с именем x связывается объ
    ект другого типа. Снова, хотя в действительности это не так, возникает ощущение изменения типа переменной x с течением времени. Напом
    ню, что в языке Python типы связаны с объектами, а не с именами. Так как имена – это всего лишь ссылки на объекты, данный код работает.
    Вовторых, следует помнить, что попутно уничтожаются ссылки на объекты. Каждый раз, когда имя x ассоциируется с новым объектом,
    интерпретатор Python освобождает пространство, занятое прежним объектом. Например, когда с именем x связывается строка 'shrubbery',

    Разделяемые ссылки
    171
    объект 42 немедленно уничтожается (при условии, что на него не ссы
    лается никакое другое имя), а пространство памяти, занимаемое объ
    ектом, возвращается в пул свободной памяти для повторного использо
    вания в будущем.
    Достигается это за счет того, что в каждом объекте имеется счетчик ссылок, с помощью которого интерпретатор следит за количеством ссы
    лок, указывающих на объект в настоящий момент времени. Как только
    (и именно в этот момент) значение счетчика достигает нуля, память, за
    нимаемая объектом, автоматически освобождается. В предыдущем лис
    тинге мы исходили из предположения, что всякий раз, когда имя x ас
    социируется с новым объектом, счетчик предыдущего объекта умень
    шается до нуля, заставляя интерпретатор освобождать память.
    Основная выгода от сборки мусора состоит в том, что программист мо
    жет свободно распоряжаться объектами, не будучи обязан освобож
    дать память в своем сценарии. Интерпретатор сам будет выполнять очистку неиспользуемой памяти в ходе выполнения программы. На практике эта особенность позволяет существенно уменьшить объем программного кода по сравнению с низкоуровневыми языками про
    граммирования, такими как C и C++.
    Разделяемые ссылки
    До сих пор мы рассматривали вариант, когда ссылка на объект при
    сваивается единственной переменной. Теперь введем в действие еще одну переменную и посмотрим, что происходит с именами и объекта
    ми в этом случае:
    >>>
    1   ...   18   19   20   21   22   23   24   25   ...   98


    написать администратору сайта