Выбрать главу

badcode.py:1: Imported module (string) not used

badcode.py:2: Imported module (re) not used

badcode.py:2: Module (re) re–imported

badcode.py:5: Parameter (y) not used

badcode.py:6: Using import and from ... import for (string)

badcode.py:7: Local variable (a) shadows global defined on line 3

badcode.py:8: Local variable (a) shadows global defined on line 3

В первой строке импортирован модуль, который далее не применяется, то же самое с модулем re. Кроме того, модуль re импортирован повторно. Другие проблемы с кодом: параметр y не использован; модуль string применен как в операторе import, так и во from–import; локальная переменная a затеняет глобальную, которая определена в третьей строке.

Можно переписать этот пример так, чтобы Pychecker выдавал меньше предупреждений:

import string

a = "a b c"

def test(x, y):

 a1 = "x y z"

 print string.split(a1) + x

test(['d'], 'e')

Теперь имеется лишь одно предупреждение:

goodcode.py:4: Parameter (y) not used

Такое тоже бывает. Программист должен лишь убедиться, что он не сделал ошибки.

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

Даже самые примитивные объекты в языке программирования 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 может дать информацию об определенной пользователем функции: