ГлавнаяРегистрацияВход Приветствую Вас Гость | RSS
   
Меню сайта
Разделы новостей
mp3player
Главная » 2007 » Июль » 8 » Руководство по интроспекции на Python(Часть 1)
Руководство по интроспекции на Python(Часть 1)
14:44

Патрик О'Брайен

Перевод: Intersoft Lab

Как изучать объекты Python

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

Что такое интроспекция?

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

В случае программирования интроспекция означает возможность изучать что-либо, чтобы определить, что это такое, что оно умеет и что может делать. Интроспекция предоставляет программистам огромные гибкость и контроль. Если вы хоть раз работали с языками программирования, которые поддерживают интроспекцию, вы, возможно, испытываете схожие чувства: "непроанализированный объект не стоит воплощения".

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

Мы начнем наше изучение Питоновской интроспекции в самом общем виде, в каком только возможно, а затем окунемся в более сложные технологии. Возможно, кто-нибудь даже заявит, что характеристики, которые являются нашей отправной точкой, не заслуживают звания "интроспективных". Согласимся, что, попадают ли они или нет под определение интроспекции, остается спорным моментом. Цель этой статьи и наша единственная задача - найти ответы на интересующие вопросы.

Давайте приступим к нашему исследованию, используя Python интерактивно. При запуске Python из командной строки мы входим в оболочку Python, где можем вводить код Python и получать немедленный ответ от интерпретатора Python. (Команды, перечисленные в этой статье, выполнятся надлежащим образом для Python 2.2.2. Возможно, вы получите другие результаты и ошибки, если используете более раннюю версию. Последнюю версию Python можно скачать с Web-сайта Python (см. Ресурсы).)

Листинг 1. Запускаем интерпретатор Python в интерактивном режиме

$ python

Python 2.2.2 (#1, Oct 28 2002, 17:22:19)

[GCC 3.2 (Mandrake Linux 9.0 3.2-1mdk)] on linux2

Type "help", "copyright", "credits" or "license" for more information.[1]

>>>

Запустив Python и посмотрев на его приглашение (>>>), вы, возможно, зададитесь вопросом, какие слова распознает Python. В большинстве языков программирования существуют зарезервированные, или ключевые слова, которые имеют специальное назначение в данном языке, и Python не является исключением. Возможно, вы также обратили внимание, что Python предлагает напечатать help для получения более подробной информации. Наверное, мы можем запросить у Python какую-нибудь справку о ключевых словах.

Интерактивная справочная утилита Python

Как предлагалось выше, давайте напечатаем help и посмотрим, получим ли мы какую-нибудь информацию о ключевых словах:

Листинг 2. Запрашиваем у Python справочную информацию

>>> help

Type help() for interactive help, or help(object) for help about object.[2]

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

Листинг 3. Запускаем справочную утилиту

>>> help()

Welcome to Python 2.2! This is the online help utility.

If this is your first time using Python, you should definitely check out

the tutorial on the Internet at http://www.python.org/doc/tut/.

Enter the name of any module, keyword, or topic to get help on writing

Python programs and using Python modules. To quit this help utility and

return to the interpreter, just type "quit".

To get a list of available modules, keywords, or topics, type "modules",

"keywords", or "topics". Each module also comes with a one-line summary

of what it does; to list the modules whose summaries contain a given word

such as "spam", type "modules spam".[3]

help>

Похоже, что мы немного продвинулись. Давайте введем keywords в приглашении справки:

Листинг 4. Запрашиваем справку о keywords

help> keywords

Here is a list of the Python keywords. Enter any keyword to get more help.[4a]

and elif global or

assert else if pass

break except import print

class exec in raise

continue finally is return

def for lambda try

del from not while

help> quit

You are now leaving help and returning to the Python interpreter.

If you want to ask for help on a particular object directly from the

interpreter, you can type "help(object)". Executing "help('string')"

has the same effect as typing a particular string at the help> prompt.[4b]

>>>

Когда мы напечатали help(), мы увидели приветствие и некоторые указания, а затем приглашение справки. В приглашении мы ввели keywords и получили список ключевых слов Python. Получив ответ на свой вопрос, мы вышли из справочной утилиты, увидев короткое прощальное сообщение, и вернулись к приглашению Python.

Как видно из этого примера, интерактивная справочная утилита Python отображает информацию на различные темы или об отдельном объекте. Эта справочная утилита довольно удобна и действительно использует интроспективные возможности Python. Однако буквальное использование справки не показывает, как она получает информацию. А поскольку задача этой статьи - раскрытие всех интроспективных секретов Python, нам необходимо незамедлительно выйти за рамки справочной утилиты.

Прежде чем выйти из справки, давайте воспользуемся ею, чтобы получить список доступных модулей. Модули - это просто текстовые файлы, которые содержат код Python и имена которых заканчиваются на .py. Если мы напечатаем в приглашении Python help('modules') или введем modules в приглашении справки, мы получим длинный список доступных модулей, который похож на неполный список, приведенный ниже. Попытайтесь сами установить, какие модули доступны на вашей системе, и понять, почему считается, что Python поставляется "вместе с батарейками".

Листинг 5. Получаем неполный список доступных модулей

>>> help('modules')

Please wait a moment while I gather a list of all available modules...[5a]

BaseHTTPServer cgitb marshal sndhdr

Bastion chunk math socket

CDROM cmath md5 sre

CGIHTTPServer cmd mhlib sre_compile

Canvas code mimetools sre_constants

<...>

bisect macpath signal xreadlines

cPickle macurl2path site xxsubtype

cStringIO mailbox slgc (package) zipfile

calendar mailcap smtpd

cgi markupbase smtplib

Enter any module name to get more help. Or, type "modules spam" to search

for modules whose descriptions contain the word "spam".[5b]

>>>

Модуль sys

Один из модулей, предоставляющих внутреннюю информацию о самом Python, - это модуль sys. Вы используете модуль, импортируя его и ссылаясь на его содержимое (как, например, переменные, функции и классы) с помощью нотации точка (.). Модуль sys содержит множество переменных и функций, которые предоставляют интересную и подробную информацию о текущем интерпретаторе Python. Давайте рассмотрим некоторые из них. И снова мы собираемся, запустив Python интерактивно, вводить команды в приглашении Python. Первое, что мы сделаем - это импортируем модуль sys. Затем введем переменную sys.executable, которая содержит путь к интерпретатору Python:

Листинг 6. Импортируем модуль sys

$ python

Python 2.2.2 (#1, Oct 28 2002, 17:22:19)

[GCC 3.2 (Mandrake Linux 9.0 3.2-1mdk)] on linux2

Type "help", "copyright", "credits" or "license" for more information.

>>> import sys

>>> sys.executable

'/usr/local/bin/python'

Если мы введем строку кода, который не содержит ничего кроме имени объекта, Python ответит, показывая представление этого объекта, которое - для простых объектов - как правило, есть значение этого объекта. В этом случае, поскольку выведенное значение заключено в кавычки, мы можем предположить, что sys.executable, вероятно, строковый объект. Позже мы изучим другие, более точные, способы определения типа объекта, однако просто ввод имени объекта в приглашении Python - это быстрый и легкий вид интроспекции.

Давайте рассмотрим некоторые другие полезные атрибуты модуля sys.

Переменная platform сообщает, в какой операционной системе мы работаем:

Атрибут sys.platform

>>> sys.platform

'linux2'

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

Листинг 8. Атрибуты sys.version и sys.version_info

>>> sys.version

'2.2.2 (#1, Oct 28 2002, 17:22:19) \n[GCC 3.2 (Mandrake Linux 9.0 3.2-1mdk)]'

>>> sys.version_info

(2, 2, 2, 'final', 0)

Переменная maxint показывает наибольшее допустимое целое значение:

Атрибут sys.maxint

>>> sys.maxint

2147483647

Переменная argv - это список, содержащий параметры командной строки, если она была задана. Первый элемент, argv[0], это путь к скрипту, который был запущен. Когда мы работаем с Python интерактивно, его значением является пустая строка:

Листинг 10. Атрибут sys.argv

>>> sys.argv

['']

Если мы запустим другую оболочку Python, как, например, PyCrust (за более подробной информацией о PyCrust см. ссылку, приведенную в Ресурсах), то увидим что-нибудь вроде этого:

Листинг 11. Атрибут sys.argv при использовании PyCrust

>>> sys.argv[0]

'/home/pobrien/Code/PyCrust/PyCrustApp.py'

Переменная path - это путь поиска модуля, список каталогов, в которых Python будет искать модули во время импорта. Пустая строка, ' ', в первой позиции относится к текущему каталогу:

Листинг 12. Атрибут path

>>> sys.path

['', '/home/pobrien/Code',

'/usr/local/lib/python2.2',

'/usr/local/lib/python2.2/plat-linux2',

'/usr/local/lib/python2.2/lib-tk',

'/usr/local/lib/python2.2/lib-dynload',

'/usr/local/lib/python2.2/site-packages']

Переменная modules - это словарь, который отображает имена модулей в объекты модулей для всех загруженных в текущий момент модулей. Как можно видеть, Python загружает определенные модули по умолчанию:

Листинг 13. Атрибут sys.modules

>>> sys.modules

{'stat': <module 'stat' from '/usr/local/lib/python2.2/stat.pyc'>,

'__future__': <module '__future__' from '/usr/local/lib/python2.2/__future__.pyc'>,

'copy_reg': <module 'copy_reg' from '/usr/local/lib/python2.2/copy_reg.pyc'>,

'posixpath': <module 'posixpath' from '/usr/local/lib/python2.2/posixpath.pyc'>,

'UserDict': <module 'UserDict' from '/usr/local/lib/python2.2/UserDict.pyc'>,

'signal': <module 'signal' (built-in)>,

'site': <module 'site' from '/usr/local/lib/python2.2/site.pyc'>,

'__builtin__': <module '__builtin__' (built-in)>,

'sys': <module 'sys' (built-in)>,

'posix': <module 'posix' (built-in)>,

'types': <module 'types' from '/usr/local/lib/python2.2/types.pyc'>,

'__main__': <module '__main__' (built-in)>,

'exceptions': <module 'exceptions' (built-in)>,

'os': <module 'os' from '/usr/local/lib/python2.2/os.pyc'>,

'os.path': <module 'posixpath' from '/usr/local/lib/python2.2/posixpath.pyc'>}

Модуль keyword

Давайте вернемся к нашему вопросу о ключевых словах Python. Даже несмотря на то, что справка предоставила нам список ключевых слов, оказывается, что часть информации справки жестко закодирована. Список ключевых слов, получается, жестко закодирован, что в конце концов не слишком интроспективно. Давайте посмотрим, сможем ли мы получить такую информацию непосредственно из одного из модулей в стандартной библиотеке Python. Если мы напечатаем help('modules keywords') в приглашении Python, то увидим следующее:

Листинг 14. Запрашиваем справку о модулях с ключевыми словами

>>> help('modules keywords')

Here is a list of matching modules. Enter any module name to get more help.[14]

keyword - Keywords (from "graminit.c")

Похоже, что модуль keyword содержит ключевые слова. Открыв файл keyword.py в текстовом редакторе, можно увидеть, что Python действительно создает список ключевых слов, явно доступных в виде атрибута kwlist модуля keyword. В модуле keyword также приводятся комментарии о том, что этот модуль генерируется автоматически на основе исходного кода самого Python, гарантируя точность и полноту списка ключевых слов:

Листинг 15. Список ключевых слов модуля keyword

>>> import keyword

>>> keyword.kwlist

['and', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else',

'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is',

'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'yield']

Функция dir()

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

Функция dir(), вероятно, наиболее известная из всех интроспективных механизмов Python. Она возвращает отсортированный список имен атрибутов для любого переданного в нее объекта. Если ни один объект не указан, dir() возвращает имена в текущей области видимости. Давайте применим dir() к нашему модулю keyword и посмотрим, что она покажет:

Листинг 16. Атрибуты модуля keyword

>>> dir(keyword)

['__all__', '__builtins__', '__doc__', '__file__', '__name__',

'iskeyword', 'keyword', 'kwdict', 'kwlist', 'main']

А как насчет модуля sys, который мы рассматривали выше?

Листинг 17. Атрибуты модуля sys

>>> dir(sys)

['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__',

'__stdin__', '__stdout__', '_getframe', 'argv', 'builtin_module_names',

'byteorder', 'copyright', 'displayhook', 'exc_info', 'exc_type', 'excepthook',

'exec_prefix', 'executable', 'exit', 'getdefaultencoding', 'getdlopenflags',

'getrecursionlimit', 'getrefcount', 'hexversion', 'last_traceback',

'last_type', 'last_value', 'maxint', 'maxunicode', 'modules', 'path',

'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags',

'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout',

'version', 'version_info', 'warnoptions']

Без указания аргумента dir() возвращает имена в текущей области видимости. Заметьте, что keyword и sys присутствуют в этом списке, поскольку мы импортировали их ранее. Импортирование модуля добавляет имя этого модуля в текущую область видимости:

Листинг 18. Имена в текущей области

>>> dir()

['__builtins__', '__doc__', '__name__', 'keyword', 'sys']

Мы упоминали, что функция dir() является встроенной функцией, что означает, что нам не нужно импортировать модуль, чтобы использовать эту функцию. Python распознает встроенные функции без нашего участия. И теперь мы видим это имя, __builtins__, возращенное обращением к dir(). Возможно, здесь имеется какая-то связь. Давайте введем имя __builtins__ в приглашение Python и посмотрим, скажет ли нам Python о нем что-нибудь интересное:

Листинг 19. Что такое __builtins__?

>>> __builtins__

<module '__builtin__' (built-in)>

Итак, __builtins__, похоже, является в текущей области именем, связанным с объектом модуля по имени __builtins__. (Поскольку модули - это не простые объекты с одиночными значениями, Python показывает информацию об этом модуле внутри угловых скобок.) Заметьте, что, если вы будете искать файл __builtin__.py на диске, то вы ничего не найдете. Этот особый объект модуля создается интерпретатором Python из ниоткуда, так как он содержит элементы, которые всегда доступны интерпретатору. И, несмотря на то, что физически файла не существует, мы все же можем применить нашу функцию dir() к этому объекту, чтобы увидеть все встроенные функции, объекты ошибок и несколько различных атрибутов, которые он содержит:

Листинг 20. Атрибуты модуля __builtins__

>>> dir(__builtins__)

['ArithmeticError', 'AssertionError', 'AttributeError', 'DeprecationWarning',

'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',

'FloatingPointError', 'IOError', 'ImportError', 'IndentationError',

'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError',

'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError',

'OverflowError', 'OverflowWarning', 'ReferenceError', 'RuntimeError',

'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError',

'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError',

'UnboundLocalError', 'UnicodeError', 'UserWarning', 'ValueError', 'Warning',

'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__', '__name__',

'abs', 'apply', 'bool', 'buffer', 'callable', 'chr', 'classmethod', 'cmp',

'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict',

'dir', 'divmod', 'eval', 'execfile', 'exit', 'file', 'filter', 'float',

'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int',

'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list',

'locals', 'long', 'map', 'max', 'min', 'object', 'oct', 'open', 'ord', 'pow',

'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'round',

'setattr', 'slice', 'staticmethod', 'str', 'super', 'tuple', 'type', 'unichr',

'unicode', 'vars', 'xrange', 'zip']

Функция dir() работает со всеми типами объектов, включая строки, целые числа, списки, кортежи, словари, функции, экземпляры и методы классов и классы, определенные пользователем. Давайте применим dir() к строковому объекту и посмотрим, что возвратит Python. Как вы можете видеть, даже простая строка Python имеет ряд атрибутов:

Листинг 21. Атрибуты строки

>>> dir('this is a string')

['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__',

'__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__',

'__hash__', '__init__', '__le__', '__len__', '__lt__', '__mul__', '__ne__',

'__new__', '__reduce__', '__repr__', '__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']

Поэкспериментируйте со следующими примерами, чтобы выяснить, что они возвратят. Заметьте, что символ # обозначает начало комментария. Все от начала комментария и до конца строки игнорируется Python:

Листинг 22. Применяем dir() к другим объектам

dir(42) # Integer (and the meaning of life)

dir([]) # List (an empty list, actually)

dir(()) # Tuple (also empty)

dir({}) # Dictionary (ditto)

dir(dir) # Function (functions are also objects)[22]

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

Листинг 23. Применяем dir() к классам, определенным пользователем, экземплярам класса и атрибутам

>>> class Person(object):

... """Person class."""

... def __init__(self, name, age):

... self.name = name

... self.age = age

... def intro(self):

... """Return an introduction."""

... return "Hello, my name is %s and I'm %s." % (self.name, self.age)

...

>>> bob = Person("Robert", 35) # Создать экземпляр Person

>>> joe = Person("Joseph", 17) # Создать еще один экземпляр

>>> joe.sport = "football" # Присвоить одному экземпляру новый атрибут

>>> dir(Person) # Атрибуты класса Person

['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',

'__hash__', '__init__', '__module__', '__new__', '__reduce__', '__repr__',

'__setattr__', '__str__', '__weakref__', 'intro']

>>> dir(bob) # Атрибуты bob

['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',

'__hash__', '__init__', '__module__', '__new__', '__reduce__', '__repr__',

'__setattr__', '__str__', '__weakref__', 'age', 'intro', 'name']

>>> dir(joe) # Заметьте, что joe имеет дополнительный атрибут

['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',

'__hash__', '__init__', '__module__', '__new__', '__reduce__', '__repr__',

'__setattr__', '__str__', '__weakref__', 'age', 'intro', 'name', 'sport']

>>> bob.intro() # Вызов метода intro экземпляра bob

"Hello, my name is Robert and I'm 35."

>>> dir(bob.intro) # Атрибуты метода intro

['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__get__',

'__getattribute__', '__hash__', '__init__', '__new__', '__reduce__',

'__repr__', '__setattr__', '__str__', 'im_class', 'im_func', 'im_self']

Часть вторая http://vvs.clan.su/news/2007-07-08-88

Категория: Работа с Python | Просмотров: 1722 | Добавил: VVS | Рейтинг: 0.0/0 |
Всего комментариев: 1
1 breedyOresee  
0
anabolic pharmacy http://sundrugstore.net/catalogue/r.htm rhode island hospital pharmacy list

Имя *:
Email *:
Код *:
Поиск
Форма входа
Наш опрос
Чего Вам не хватает на сайте?
Всего ответов: 21
Друзья сайта
Статистика
Возраст