Опубликован: 22.12.2005 | Доступ: свободный | Студентов: 24084 / 1831 | Оценка: 4.18 / 3.71 | Длительность: 16:10:00
ISBN: 978-5-9556-0109-0
Лекция 14:

Устройство интерпретатора языка Python

< Лекция 13 || Лекция 14: 12345678

Исследование объекта

Даже самые примитивные объекты в языке программирования Python имеют возможности, общие для всех объектов: можно получить их уникальный идентификатор (с помощью функции id() ), представление в виде строки - даже в двух вариантах (функции str() и repr() ); можно узнать атрибуты объекта с помощью встроенной функции dir() и во многих случаях пользоваться атрибутом __dict__ для доступа к словарю имен объекта. Также можно узнать, сколько других объектов ссылается на данный с помощью функции sys.getrefcount(). Есть еще сборка мусора, которая применяется для освобождения памяти от объектов, которые более не используются, но имеют ссылки друг на друга (циклические ссылки). Сборкой мусора (garbage collection) можно управлять из модуля gc.

Все это подчеркивает тот факт, что объекты в Python существуют не сами по себе, а являются частью системы: они и их отношения строго учитываются интерпретатором.

Сразу же следует оговориться, что Python имеет две стороны интроспекции: "официальную", которую поддерживает описание языка и многие его реализации, и "неофициальную", которая использует особенности той или иной реализации. С помощью "официальных" средств интроспекции можно получить информацию о принадлежности объекта тому или иному классу (функция type() ), проверить принадлежность экземпляра классу ( isinstance() ), отношение наследования между классами ( issubclass() ), а также получить информацию, о которой говорилось чуть выше. Это как бы приборная доска машины. С помощью "неофициальной" интроспекции (это то, что под капотом) можно получить доступ к чему угодно: к текущему фрейму исполнения и стеку, к байт-коду функции, к некоторым механизмам интерпретатора (от загрузки модулей до полного контроля над внутренней средой исполнения). Сразу же стоит сказать, что этот механизм следует рассматривать (и тем более вносить изменения) очень деликатно: разработчики языка не гарантируют постоянство этих механизмов от версии к версии, а некоторые полезные модули используют эти механизмы для своих целей. Например, упомянутый ранее ускоритель выполнения Python-кода psyco очень серьезно вмешивается во фреймы исполнения, заменяя их своими объектами. Кроме того, разные реализации Python могут иметь совсем другие внутренние механизмы.

Сказанное стоит подкрепить примерами.

В первом примере исследуется объект с помощью "официальных" средств. В качестве объекта выбрана обычная строка:

>>> s = "abcd"
            >>> dir(s)
            ['__add__', '__class__', '__contains__', '__delattr__', '__doc__',
            '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__',
            '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__',
            '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__',
            '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__',
            '__str__', 'capitalize', 'center', 'count', 'decode',
            'encode', 'endswith', 'expandtabs', 'find', 'index', 'isalnum', 'isalpha',
            'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust',
            'lower', 'lstrip', 'replace', 'rfind', 'rindex', 'rjust', 'rstrip',
            'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title',
            'translate', 'upper', 'zfill']
            >>> id(s)
            1075718400
            >>> print str(s)
            abcd
            >>> print repr(s)
            'abcd'
            >>> type(s)
            <type 'str'>
            >>> isinstance(s, basestring)
            True
            >>> isinstance(s, int)
            False
            >>> issubclass(str, basestring)
            True

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

>>> def f(x, y=0):
            ...   """Function f(x, y)"""
            ...   global s
            ...   return t + x + y
            ...
            >>> f.secure = 1     # присваивается  дополнительный атрибут
            >>> f.func_name      # имя
            'f'
            >>> f.func_doc       # строка документации
            'Function f(x, y)'
            >>> f.func_defaults  # значения по умолчанию
            (0,)
            >>> f.func_dict      # словарь атрибутов функции
            {'secure': 1}
            >>> co = f.func_code # кодовый объект
            >>> co
            <code object f at 0x401ec7e0, file "<stdin>", line 1>

Кодовые объекты имеют свои атрибуты:

>>> co.co_code       # байт-код
            't\x00\x00|\x00\x00\x17|\x01\x00\x17Sd\x01\x00S'
            >>> co.co_argcount   # число аргументов
            2
            >>> co.co_varnames   # имена переменных
            ('x', 'y')
            >>> co.co_consts     # константы
            (None,)
            >>> co.co_names      # локальные имена
            ('t', 'x', 'y')
            >>> co.co_name       # имя блока кода (в нашем случае - имя функции)
            'f'

и так далее. Более правильно использовать для получения всех этих сведений модуль inspect.

< Лекция 13 || Лекция 14: 12345678
Сергей Крупко
Сергей Крупко

Добрый день.

Я сейчас прохожу курс  повышения квалификации  - "Профессиональное веб-программирование". Мне нужно получить диплом по этому курсу. Я так полагаю нужно его оплатить чтобы получить диплом о повышении квалификации. Как мне оплатить этот курс?

 

Павел Ялганов
Павел Ялганов

Скажите экзамен тоже будет ввиде теста? или там будет какое то практическое интересное задание?