Различия между версиями 15 и 16
Версия 15 от 2016-09-02 15:57:27
Размер: 20789
Редактор: FrBrGeorge
Комментарий:
Версия 16 от 2016-09-02 18:19:25
Размер: 22009
Редактор: FrBrGeorge
Комментарий:
Удаления помечены так. Добавления помечены так.
Строка 180: Строка 180:
Что важно, состав объекта доступен в процессе работы программы:
{{{#!python
>>> a="STR"
>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__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', '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']
>>> hasattr(a,"zfill")
True
>>> hasattr(a,"yfill")
False
}}}

Функция `dir(<объект>)` возвращает список строк — имё

Особенности ЯП Python3

Базовые особенности

Python2 и Python3

Имеется два похожих языка программирования с разным синтаксисом — Pythoh2 и Python3. Python3 — более новый язык, из которого выброшено то, что показалось неудачным в Python2.

Интерпретатор

Python — интерпретируемый, а не компилируемый язык, поэтому многие механизмы контроля (и возникающие благодаря им ошибки) перенесены со стадии лексического/синтаксического анализа на стадию выполнения программы. Например, наличие или отсутствие имени в пространстве видимости проверяется в момент использования этого имени:

   1 Python 2.7.8 (default, Nov 20 2014, 14:29:22) 
   2 [GCC 4.9.2 20141101 (ALT Linux 4.9.2-alt1)] on linux2
   3 Type "help", "copyright", "credits" or "license" for more information.
   4 >>> a*2
   5 Traceback (most recent call last):
   6   File "<stdin>", line 1, in <module>
   7 NameError: name 'a' is not defined
   8 >>> a=2
   9 >>> a*2
  10 4

Вместо операторных скобок (составных операторов) используется одинаковый отступ записи всех операторов в блоке (это называется «блок с отступом», в грамматике — "suite").

   1 for i in range(10):
   2     n = 3*i**2 + 2*i + 7
   3     print (i,n)
   4 print "Done"

Достоинство: практически любую программу можно прочесть. Недостаток: надо избегать использования символов табуляции.

Связывание

Значение любого питоновского выражения — это объект. Объект можно связать с помощью имени или в качестве элемента составного объекта. Основная операция связывания — это «=». В примере создаётся два объекта: один с одной связью (именем), другой — с четырьмя (три имени и участие в списке).

   1 >>> a=b=[1,"QQ",2]
   2 >>> c=b
   3 >>> e=[234,678,b]
   4 >>> d=[1,"QQ",2]
   5 >>> id(a), id(b), id(c), id(d), id(e[2])
   6 (139945032097664, 139945032097664, 139945032097664, 139945032132440, 139945032097664)

Удалить объект в Питоне нельзя. Операция del удаляет одну связь. Если эта связь — последняя, объект становится недоступен. В удобный для Питона момент придёт сборщик мусора gc и очистит занимаемую объектом память (с предварительным вызовом у объекта определенного метода-"деструктора").

   1 >>> del a
   2 >>> a
   3 Traceback (most recent call last):
   4   File "<stdin>", line 1, in <module>
   5 NameError: name 'a' is not defined
   6 >>> c
   7 [1, 'QQ', 2]

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

   1 >>> c[1]="ZZZZZ"
   2 >>> e[2]
   3 [1, 'ZZZZZ', 2]
   4 >>> b
   5 [1, 'ZZZZZ', 2]

Групповое связывание

Связывание может быть групповым, когда слева и справа от «=» стоят последовательности (причём «слева» может быть не одно):

   1 >>> a=x,y=3,5
   2 >>> a
   3 (3, 5)
   4 >>> x
   5 3
   6 >>> y
   7 5

Более того, эти последовательности автоматически распаковываются:

   1 >>> c=["QQ",3,[12,34],(1,5,6)]
   2 >>> (s,t),n,(x,y),l=c
   3 >>> s
   4 'Q'
   5 >>> t
   6 'Q'
   7 >>> x
   8 12
   9 >>> y
  10 34
  11 >>> l
  12 (1, 5, 6)

«Математические» сравнения

Конструкции вида «a < b < c» в Питоне могут быть произвольной длины и обозначают многоместные сравнения в «математическом стиле» (в большинстве языков указанный пример читался бы как сравнение результата a<b с c.

«Списки»

Тип данных «list» в питоне — это динамический массив связей. Тип объекта может быть любым, но поскольку любая связь имеет одинаковое внутреннее представление, сложность индексации в объекте типа listO(1), зато сложность вставки/удаления зависит от расстояния до конца списка, наибольшая для начала (O(n), где n — длина списка), наименьшая — O(1) — для конца. Именно поэтому стек имитировать естественно с помощью list, а вот очередь — лучше с помощью collections.deque. Динамическая реогранизация массива при его значительном увеличении/уменьшении происходит прозрачно для программиста.

Словари

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

Множество внутренних структур самого Питона (например, пространства имён), реализованы с помощью словарей.

Цикл с итерируемым объектом

Цикл for переменная in последовательность в Питоне — не просто цикл по последовательности, и тем более — не просто цикл со счётчиком. Роль последовательности может играть любой итерируемый объект (т. е. имеющий метод .__iter__()). Помимо списков итерируемыми являются, например, словарь и файл:

   1 >>> d={1:"QQ", 222:"abc", (1,"TTT"): 2}
   2 >>> for k in d:
   3 ...   print(k)
   4 ... 
   5 1
   6 222
   7 (1, 'TTT')

В примере с файлом обратите внимание на удвоение переводов строк: итерация по файлу эквивалентна последовательному вызову метода .readline() (прочесть строку), который возвращает очередную строку целиком, вместе с концевым символом перевода строк, а функция print() при печати добавляет ещё один.

   1 >>> for line in open("file.txt"):
   2 ...   print(line)
   3 ... 
   4 First line
   5 
   6 Second line
   7 
   8 Third line

Выражения как суперпозиция методов

Все выражения с объектами можно воспринимать как «синтаксический сахар», удобную форму записи вызова соответствующий методов (они называются «специальными»). Например, a+b превращается в a.__add__(b), причём если при вычислении возникает исключение, то попытка продолжается с помощью b.__radd__(a).

Неявная динамическая типизация (duck typing)

Тип объекта в Питоне всегда строго определён — это класс, экземпляром которого объект является (этот класс возвращает, например, type(объект)). Но в пространстве имён нет никаких привязок к типам

Это означает, например, что при вызове функции или метода (и при вычислении выражения, так как операции — это вызовы методов) никакой проверки типов не производится. Ошибка возникнет только если у объекта не окажется соответствующего операции метода или какая-то из функций/методов всё-таки проверит тип параметра.

   1 >>> def su(a,b):
   2 ...     return a+b
   3 ... 
   4 >>> def di(a,b):
   5 ...     return a-b
   6 ... 
   7 >>> su(1,2)
   8 3
   9 >>> su([5,6],["QQ",9.0])
  10 [5, 6, 'QQ', 9.0]
  11 >>> di(1,2)
  12 -1
  13 >>> di([5,6],["QQ",9.0])
  14 Traceback (most recent call last):
  15   File "<stdin>", line 1, in <module>
  16   File "<stdin>", line 2, in di
  17 TypeError: unsupported operand type(s) for -: 'list' and 'list'

Универсальные логические выражения

В Питоне любой объект может быть параметром операторов if и while, а также булевских операций and, or и not. Обычно одно значение объекта любого класса может считаться «ложью» (такой объект называется нулевым), остальные — «истиной».

Нулевыми являются численные нули, пустые последовательности и словари и т. п., а также все объекты, имеющие метод .__bool__(), у которых он возвращает False.

Частичное вычисление. Операция not объект возвращает True или False, в зависимости от того, является ли объект нулевым, или нет. Операции оббъект1 and объкет2 и объект1 or объект2 возвращают объект1 или объект2 по следующим правилам:

A or B

B нулевой

B ненулевой

А нулевой

B

B

А ненулевой

A

A

То есть «если A ненулевой, результат A, иначе B»

A and B

B нулевой

B ненулевой

А нулевой

A

A

А ненулевой

B

B

То есть «если A нулевой, результат A, иначе B»

В обоих случаях есть ситуация, при которой B не вычисляется.

Интроспекция

Исполняющая система Python3 с точки зрения программиста выглядит как множество вложенных пространств имён. Каждое пространство имён — это объект. Свойства объекта определяются набором методов и полей (неявная динамическая типизация).

Что важно, состав объекта доступен в процессе работы программы:

   1 >>> a="STR"
   2 >>> dir(a)
   3 ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__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', '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']
   4 >>> hasattr(a,"zfill")
   5 True
   6 >>> hasattr(a,"yfill")
   7 False

Функция dir(<объект>) возвращает список строк — имё /!\

Строки документации

Все объекты Python3 самодокументированы /!\

Циклические конструкторы

/!\

Наличие современных программных конструкций

  • /!\ Исключения как средство управления вычислениями

  • /!\ Повторно-входимые функции

  • /!\ Декораторы

  • /!\ Контексты

  • /!\ Элементы функционального программирования

Динамическая объектная модель

  • /!\

Сравнение с другими языками

Паскаль и Си

  • (Паскаль) Питон различает большие и маленькие буквы.
  • У имён объектов нет типов, потому что они — не переменные, а просто именованные связи. Считается плохим тоном программирования использовать одно и то же имя для объектов разного типа.
  • Действительное отличие подхода «имя == связь» от подхода «имя == переменная» заметно только на изменяемых объектах, для константных же (чисел, строк) именованные связи ведут себя совершенно так же, как переменные без типа.
  • (Паскаль) Нет разделения на функции и процедуры, функция без return возвращает None, возвращаемое значение любой функции можно не использовать.

  • (Паскаль) Как и в Си, в Питоне «==» — это сравнение, а «=» — присваивание

  • (Си) Хотя в Питоне есть конструкция вида «a=b=c», операция «=» не является, как в Си, арифметической, и её нельзя использовать в выражениях.

  • (Паскаль) Операции and, or и not имеют более низкий приоритет, чем арифметические и операции сравнения, поэтому выражение вида a>0 and b+c<0 не требует скобок. Побитовые операции в Питоне обозначаются так же, как в Си: «&», «|» и «~».

  • (Си) В питоне, как в Си, есть операции изменения объекта (например, «+=» — прибавление). Разумеется, изменяться может только неконстантный объект (например, список), для константного объекта (число, строка) результат такой операции — новый объект, результат вычисления выражения. В приведённом примере в результате прибавления списочный объект остаётся тем же, а целочисленный меняется на другой.

       1 >>> a=[1,2,"QQ"]
       2 >>> id(a)
       3 140178647658648
       4 >>> a+=["NN",1.234]
       5 >>> a
       6 [1, 2, 'QQ', 'NN', 1.234]
       7 >>> id(a)
       8 140178647658648
       9 >>> b=3
      10 >>> id(b)
      11 6398248
      12 >>> b+=7
      13 >>> b
      14 10
      15 >>> id(b)
      16 6398080
    
  • (Си) В Питоне есть тернарная операция вида «результат_истина if условие else результат_ложь», соответствующая «У ? Р_И : Р_Л» в Си. Сверх того имеются и другие операции, замещающие операторы (лямбда-функции, циклические конструкторы)

  • Передача параметров в функции происходит строго по соиспользованию. Это значит, что фактическими параметрами функции являются объекты (возможно, только что вычисленные), для них создаются имена в локальном пространстве имён функции, а при выходе из функции эти имена уничтожаются. Копирования данных не происходит. В Си передача данных строго по значению (передача данных по ссылке имитируется передачей указателя на объект). В паскале передача данных либо по значению, либо по ссылке (указывается явно).
  • Частичное вычисление AND и OR (см. выше) как в Си, но значение — не булевское

  • Структуры (записи) как отдельные конструкции в Питоне не выделены. Логически — это просто объекты, у которых нет методов.
  • Структуры (записи) как последовательности байтов, в которые упакованы объекты разного типа, в синтаксис не встроены, поддерживаются модулем strcut

  • Массивы как последовательности байтов, представляющие собой последовательности данных одного типа, встречаются и используются в Питоне редко. Есть встроенные типы bytearray/bytes, выделенный модуль array. Самые мощные массивы реализованы в стороннем пакете NumPy.

  • В Питоне больше, чем с Си и Паскале, конструкций языка и встроенных типов, некоторые из них нужны не сразу (например, assert или with)

Подробности реализации

Некоторые свойства Питона, поясняющие его структуру, но без знания которых можно спокойно жить

Именование как «синтаксический сахар»

То, что мы видим как «именование», — это просто заполнение соответствующего пространства имён парами «имя → объект». Чем, собственно, и обеспечивается референция объекта. Кстати, все пространства имён доступны из самого Питона и имеют стандартный питоновский тип «словарь» (dict). Так что вообще никакой новой сущности не вводится, только «синтаксический сахар».

Пример: функция locals() возвращает словарь имён, локальных в текущем контексте:

   1 >>> locals()
   2 {'__name__': '__main__', '__builtins__': …}
   3 >>> A=123
   4 >>> locals()
   5 {'A': 123, '__name__': '__main__', '__builtins__': …}
   6 >>> locals()["A"]='OK'
   7 >>> locals()
   8 {'A': 'OK', '__name__': '__main__', '__builtins__': …}
   9 >>> QQ
  10 Traceback (most recent call last):
  11   File "<stdin>", line 1, in <module>
  12 NameError: name 'QQ' is not defined
  13 >>> locals()["QQ"]='Yes, QQ!'
  14 >>> QQ
  15 'Yes, QQ!'
  16 >>> locals()
  17 {'A': 'OK', '__name__': '__main__', 'QQ': 'Yes, QQ!', '__builtins__': …}

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

Python/Features (последним исправлял пользователь FrBrGeorge 2016-11-02 22:28:07)