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

  • Предопределённые действия по подчистке

  • Пара слов о терминологии

  • Учебник Python 3.1

  • Пример по областям видимости и пространствам имён

  • Первый взгляд на классы В описании классов представлено немного нового синтаксиса, три новых типа объектов[54] и некоторое количество новой семантики.Синтаксис определения класса

  • Учебник Python 3.1. Учебник Python 3. Учебник Python 1 Материал из Викиучебника. Оглавление


    Скачать 1.85 Mb.
    НазваниеУчебник Python 1 Материал из Викиучебника. Оглавление
    АнкорУчебник Python 3.1.pdf
    Дата05.04.2017
    Размер1.85 Mb.
    Формат файлаpdf
    Имя файлаУчебник Python 3.1.pdf
    ТипУчебник
    #4516
    страница9 из 13
    1   ...   5   6   7   8   9   10   11   12   13
    else
    :
    print
    (
    "результат: "
    ,
    result)
    finally
    :
    print
    (
    "выполнение блока finally"
    )
    >>>
    divide(
    2
    ,
    1
    )
    результат:
    2
    выполнение блока
    finally
    >>>
    divide(
    2
    ,
    0
    )
    деление на ноль
    !
    выполнение блока
    finally
    >>>
    divide(
    "2"
    ,
    "1"
    )
    выполнение блока
    finally
    Traceback (most recent call last):
    File
    ""
    ,
    line
    1
    ,
    in
    ?
    File
    ""
    ,
    line
    3
    ,
    in
    divide
    TypeError
    : unsupported operand type
    (s)
    for
    /:
    'str'
    and
    'str'
    Как видите, блок finally выполняется при любом событии.
    Ошибка
    TypeError порождается при делении двух строк и не перехватывается блоком except
    , и поэтому порождается заново сразу после выполнения блока finally
    В приложениях реального мира, блок finally применяется для освобождения внешних ресурсов (таких как файлы или сетевые соединения), независимо от того, было ли их использование удачным.
    Предопределённые действия по подчистке
    Некоторые объекты определяют стандартные действия при подчистке, применяемые если объект больше не нужен, независимо от того, удачна была операция использования объекта или нет. Посмотрите на следующий пример, в которым мы пытаемся открыть файл и вывести его содержимое на экран.
    for
    line
    in
    open
    (
    "myfile.txt"
    ):
    print
    (line)
    Проблема этого кода в том, что он оставляет файл открытым на неопределённое количество времени после выполнения данной части кода. В простых сценариях это не является проблемой, но может стать ей в больших приложениях. Оператор with позволяет использовать объекты (такие как, например, файлы) таким образом, чтобы вы всегда могли быть уверены в том, что ресурсы будут сразу и корректно очищены.
    with
    open
    (
    "myfile.txt"
    )
    as
    f:
    for
    line
    in
    f:
    print
    (line)
    После выполнения оператора, файл
    f
    всегда закрывается, даже если при прочтении строк обнаружилась проблема. В документации к объектам, которые поддерживают
    62

    Учебник Python 3.1: Материал из Викиучебника.
    предопределённые действия по подчистке, таким как файлы, эта их способность будет явно указана.
    Классы
    За счёт механизма классов Python в язык с минимальным использованием нового синтаксиса и семантики добавляется возможность создания классов. Это смесь классовых механизмов, заимствованных из C++ и Modula-3. Как и в случае модулей, классы в Python не устанавливают абсолютного барьера между определением и программистом, рассчитывая больше на аккуратность и вежливость последнего — чтобы он не «врывался в определения». Наиболее важные возможности классов, тем не менее, содержат в себе всю возможную мощь: механизм наследования классов поддерживает несколько предков для класса, производный класс может перегружать любые методы своего предка или предков, а любой его метод может вызвать метод предка с таким же именем. Объекты могут содержать произвольное количество закрытых (private) данных.
    В терминологии C++, члены класса (включая данные-члены), обычно, открыты (public)
    (исключая
    Приватные переменные
    , описанные ниже), а все функции-члены — виртуальны.
    Нет специальных конструкторов и деструкторов. Как в Modula-3, нет краткой ссылки на члены объекта из его методов: функция-метод определяется с явным первым аргументом, описывающем объект, который неявно передаётся при вызове. Как в Smalltalk, классы сами по себе являются объектами, хотя и в более широком смысле: в Python все типы данных — объекты. Таким образом обеспечивается семантика для импортирования и переименования. В отличие от C++ и Modula-3 встроенные типы могут использоваться в качестве предков для расширения возможностей пользователем. Кроме того, как в C++, но не как в Modula-3, большинство встроенных операторов со специальным синтаксисом
    (арифметические операторы, индексирование и т.д.) могут быть переопределены для экземпляров классов.
    Пара слов о терминологии
    Обходя стороной поддерживаемую всем миром терминологию, применимую к разговорам о классах, в нашем случае я буду говорить в терминах C++ и Smalltalk. (Предпочёл бы использовать термины языка Modula-3, поскольку Python ближе к ней по объектно- ориентированной семантике, чем к C++, но предполагаю, что немногие читатели слышали о нём.)
    Объекты обладают индивидуальностью, и с одним объектом может быть связано несколько имён (в нескольких областях видимости). Такая практика в других языках известна каксовмещение имён (aliasing). На первый взгляд, совмещение малозаметно в
    Python, и его можно без последствий игнорировать при работе с основными неизменяемыми типами (числами, строками, кортежами). Тем не менее, совмещение имён влияет на семантику программного кода Python, работающего с изменяемыми объектами: списками, словарями и большинством типов, описывающих сущности вне программы
    (файлы, окна и т.п.). Обычно такая практика считается полезной, поскольку псевдонимы работают подобно указателям и вероятно даже превосходят их возможности. Например, передача объекта - дешевая операция, поскольку по реализации передаётся только указатель. Если функция изменяет переданный в качестве аргумента объект, это будет заметно и в месте вызова. За счёт этого пропадает необходимость в двух различных механизмах передачи аргументов.
    63

    Учебник Python 3.1: Материал из Викиучебника.
    Области видимости и пространства имён в Python
    Прежде чем заняться классами необходимо получить представление о правилах областей видимости в Python. Определения классов проделывают над пространствами имён некоторые ловкие трюки. Чтобы полностью понимать происходящее, нужно знать о принципах работы областей видимости и пространств имён. Эти знания не помешают любому профессиональному программисту на Python.
    Давайте начнём с нескольких определений.
    Пространство имён (namespace) — это набор связей имён с объектами
    [50]
    . В настоящий момент большинство пространств имён реализованы в виде словарей Python, но не стоит заострять на этом внимание (если только по поводу производительности): возможно, в будущем реализация изменится. Примеры пространств имён: набор встроенных имён
    (функции вроде abs()
    и имён встроенных исключений); глобальные имена в модуле; локальные имена при вызове функции. Важная вещь, которую необходимо знать о пространствах имён — это то, что нет абсолютно никакой связи между именами в разных пространствах имён: например, два разных модуля могут без проблем определять функцию «
    maximize
    », так как пользователи модулей будут использовать имена модулей в качестве префиксов.
    Кстати, слово атрибут (attribute) я применяю к любому имени, следующему за точкой.
    Например, в выражении z.real
    , real
    — это атрибут объекта z
    . Строго говоря, ссылки на имена в модуле являются ссылками на атрибуты: в выражении
    имя_модуля.имя_функции
    под имя_модуля скрывается объект модуля, а под имя_функции — его атрибут. В таком случае обнаруживается прямая связь между атрибутами модуля и глобальными именами, определёнными в модуле: они разделяют между собой одно и тоже пространство имён
    [51]
    Запись в атрибуты может быть запрещена (атрибут только для чтения, read-only attribute) или разрешена (перезаписываемый атрибут, writable attribute). В последнем случае присваивание атрибуту является возможным. Атрибуты модуля перезаписываемы: вы можете написать "
    modname.the_answer = 42
    "
    [52]
    . Перезаписываемые атрибуты могут также быть удалены оператором del
    . Например, код "
    del modname.the_answer
    " удалит атрибут the_answer из объекта с именем modname
    Пространства имён создаются в различные моменты и имеют разное время жизни.
    Пространство имён, содержащее встроенные имена создаётся при запуске интерпретатора и не удаляется никогда. Глобальное пространство имён модуля создаётся при вычитке определения модуля. Обычно, пространства имён модулей также «живут» до выхода из интерпретатора. Выражения, выполняемые верхне-уровневым порождением интерпретатора, прочитанные из файла сценария или интерактивно, рассматриваются как часть модуля под названием
    __main__
    , поэтому у них есть своё собственное глобальное пространство имён. (Встроенные имена по факту также живут в модуле, он называется builtins
    ).
    Локальное пространство имён функции создаётся при её вызове и удаляется когда функция возвращает значение либо порождает исключение, внутри неё не перехваченное.
    (На самом деле, лучшим способом объяснить, что происходит на самом деле, было бы
    «забывание»). Конечно же, рекурсивные порождения имеют свои пространства имён каждое.
    64

    Учебник Python 3.1: Материал из Викиучебника.
    Область видимости (scope) — это текстовая область в программе на Python, из которой прямым образом доступно пространство имён. «Прямым образом доступно» подразумевает, что явная ссылка на имя вынуждает интерпретатор искать это имя в пространстве имён.
    Несмотря на то, что области видимости определяются статически, используются они динамически. В любой момент во время выполнения существует как минимум три вложенных области видимости, чьи пространства имён доступны прямым образом: самая внутренняя
    [53]
    область видимости (по ней поиск осуществляется в первую очередь) содержит локальные имена; пространства имён всех объемлющих [данный код] функций, поиск по которым начинается с ближайшей объемлющей [код] области видимости; область видимости среднего уровня, по ней следующей проходит поиск и она содержит глобальные имена текущего модуля; и самая внешняя область видимости
    (заключительный поиск) — это пространство имён, содержащее встроенные имена.
    Если имя определено глобально, тогда все ссылки и присваивания уходят прямо в область видимости среднего уровня, содержащую глобальные имена модуля. Чтобы сменить привязку у всех переменных, найденных вне самой внутренней области видимости, можно использовать оператор nonlocal
    ; если такая переменная не объявлена как nonlocal
    , то она используется только для чтения (попытка записать значение в такую переменную создаст новую локальную переменную в самой внутренней области видимости, оставляя идентично названную вовне переменную без изменений).
    Обычно локальная область видимости ссылается на локальные имена текущей (на уровне текста) функции. Вне функций локальная область видимости ссылается на то же пространство имён, что и глобальная область видимости: пространство имён модуля.
    Определения классов помещают в локальную область видимости ещё одно пространство имён.
    Важно осознавать, что области видимости ограничиваются на текстовом уровне: глобальная область видимости функции, определённая в модуле, является пространством имён этого модуля, независимо от того, откуда или по какому псевдониму была эта функция вызвана. С другой стороны, фактический поиск имён осуществляется динамически, во время выполнения. Как бы то ни было, язык развивается в сторону статического разрешения имён (во время компиляции), так что не стоит полагаться на динамическое разрешение имён. (Фактически, локальные переменные уже определены статично.)
    Особая хитрость в Python состоит в том, что — при условии, что в данной области не включены операторы global или nonlocal
    — присваивания именам всегда уходят в самую внутреннюю область видимости. Присваивания не копируют данных, а лишь связывают имена с объектами. Тоже самое верно и для удалений: оператор "
    del x
    " удаляет связь x
    из пространства имён, на которое ссылается локальная область видимости. В действительности, все операции, вводящие новые имена, используют локальную область видимости: в частности, операторы импорта и описаний функций связывают имя модуля или функции в локальной области видимости соответственно. (Для того, чтобы указать определённой переменной, что она должна быть расположена в глобальной области видимости, может использоваться оператор global
    .)
    65

    Учебник Python 3.1: Материал из Викиучебника.
    Оператор global можно использовать для того, чтобы объявить определённые переменные как привязанные к глобальной области видимости и указывает, что их переназначения должны происходить в ней; оператор nonlocal помечает переменные как привязанные к окружающей их области видимости и указывает, что их переназначения должны происходить в ней.
    Пример по областям видимости и пространствам имён
    Приведём пример, показывающий, каким образом можно ссылаться на разные области видимости и пространства имён и как global и nonlocal влияют на привязку переменной.
    def
    scope_test():
    def
    do_local():
    spam
    =
    "локальный спам"
    def
    do_nonlocal():
    nonlocal
    spam spam
    =
    "нелокальный спам"
    def
    do_global():
    global
    spam spam
    =
    "глобальный спам"
    spam
    =
    "тестовый спам"
    do_local()
    print
    (
    "После локального присваивания:"
    ,
    spam)
    do_nonlocal()
    print
    (
    "После нелокального присваивания:"
    ,
    spam)
    do_global()
    print
    (
    "После глобального присваивания:"
    ,
    spam)
    scope_test()
    print
    (
    "В глобальной области видимости:"
    ,
    spam)
    Вывод кода из примера таков:
    После локального присваивания: тестовый спам
    После нелокального присваивания: нелокальный спам
    После глобального присваивания: нелокальный спам
    В глобальной области видимости: глобальный спам
    Заметьте, что локальное присваивание (работающее по умолчанию) не заменяет глобальную привязку на связывание из scope_test
    . Нелокальное присваивание заменило глобальную привязку на связывание из scope_test
    , а глобальное присваивание заменило привязку на связывание на уровне модуля.
    Можно увидеть, что до глобального присваивания у переменной spam не было предшествующих связываний.
    Первый взгляд на классы
    В описании классов представлено немного нового синтаксиса, три новых типа объектов
    [54]
    и некоторое количество новой семантики.
    Синтаксис определения класса
    Простейшая форма определения класса выглядит так:
    class
    ИмяКласса:
    <
    оператор-
    1
    >
    66

    Учебник Python 3.1: Материал из Викиучебника.
    <
    оператор-N
    >
    Определения классов, как и определения функций (операторы def
    ), должны быть исполнены для того, чтобы определить действие. (Вы можете, предположим, поместить определение класса в ветку оператора if или внутрь функции.)
    На практике, внутри определения класса обычно помещаются определения функций, но позволено использовать и другие операторы — и иногда с пользой — как мы увидим позже. Определения функций внутри класса имеют особенную форму списка аргументов, в связи с соглашениями по вызову методов — опять же, это будет рассмотрено ниже.
    При вводе определения класса создаётся новое пространство имён, которое и используется в качестве локальной области видимости. Таким образом, все присваивания локальным переменным происходят в этом новом пространстве имён. В частности, определения функций связываются здесь с именами новых функций.
    При успешном окончании парсинга определения класса (по достижении конца определения), создаётся объект-класс (class object). По существу, это обёртка вокруг содержимого пространства имён, созданного во время определения класса; подробнее объекты классов мы изучим в следующем разделе. Оригинальная локальная область видимости (та, которая действовала в последний момент перед вводом определения класса) восстанавливается, а объект-класс тут же связывается в ней с именем класса, указанном в заголовке определения класса (в примере —
    ИмяКласса
    ).
    Объекты-классы
    Объекты-классы поддерживают два вида операций: ссылки на атрибуты и создание экземпляра.
    Ссылки на атрибуты (Attribute references) используют стандартный синтаксис, использующийся для всех ссылок на атрибуты в Python:
    объект.имя
    . Корректными именами атрибутов являются все имена, которые находились в пространстве имён класса при создании объекта-класса. Таким образом, если определение класса выглядело так:
    class
    MyClass:
    """Простой пример класса"""
    i
    =
    12345
    def
    f(
    self
    ):
    return
    'привет мир'
    то
    MyClass.i и
    MyClass.f являются корректными ссылками на атрибуты, возвращающими целое и объект-функцию (function object) соответственно. Атрибутам класса можно присваивать значение, так что вы можете изменить значение
    MyClass.i через присваивание.
    __doc__
    также является корректным атрибутом, возвращающим строку документации, принадлежащей классу:
    "Простой пример класса"
    Создание экземпляра класса использует синтаксис вызова функции. Просто представьте, что объект-класс — это непараметризированная функция, которая возвращает новый экземпляр класса. Например (предполагая класс, приведённый выше):
    x
    =
    MyClass()
    создаёт новый экземпляр класса и присваивает этот объект локальной переменной x
    Операция создания экземпляра (instantiation) создаёт объект данного класса. Большая часть классов предпочитает создавать экземпляры, имеющие определённое начальное
    67

    Учебник Python 3.1: Материал из Викиучебника.
    состояние. Для этого класс может определять специальный метод под именем
    __init__()
    , например так:
    def
    __init__
    (
    self
    ):
    self
    .data
    =
    []
    Когда в классе определён метод
    __init__()
    , при создании экземпляра автоматически вызывается
    __init__()
    нового, только что созданного объекта. Так, в этом примере, новый инициализированный экземпляр может быть получен за счёт выполнения кода:
    x
    =
    MyClass()
    Конечно же, для большей гибкости, метод
    __init__()
    может иметь параметры. В этом случае аргументы, переданные оператору создания экземпляра класса, передаются методу
    __init__()
    . Например,
    >>>
    1   ...   5   6   7   8   9   10   11   12   13


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