Автостопом по Python | страница 56
>>>> def foo():
>… ····print("I am inside foo.")
>…
>…
>…
>>>> import logging
>>>> logging.basicConfig()
>>>>
>>>> def logged(func, *args, **kwargs):
>… ····logger = logging.getLogger()
>… ····def new_func(*args, **kwargs):
>… ········logger.debug("calling {} with args {} and kwargs {}".format(
>… ···················· func.__name__, args, kwargs))
>… ········return func(*args, **kwargs)
>… ····return new_func
>…
>>>>
>>>>
>… @logged
>… def bar():
>… ····print("I am inside bar.")
>…
>>>> logging.getLogger(). setLevel(logging.DEBUG)
>>>> bar()
>DEBUG: root: calling bar with args () and kwargs {}
>I am inside bar.
>>>> foo()
>I am inside foo.
Этот механизм подойдет, чтобы изолировать основную логику функции или метода. Примером задачи, для которой нужно использовать декорирование, можно назвать запоминание или кэширование: вы хотите сохранить результат дорогой функции в таблице и использовать его вместо того, чтобы выполнять повторные вычисления. Очевидно, это не является частью логики функции. В PEP 3129 (https://www.python.org/dev/peps/pep-3129/), начиная с Python 3, декораторы также можно применять к классам.
Динамическая типизация
Python — динамически типизированный язык (в противоположность статически типизированным). Это означает, что переменные не имеют фиксированного типа. Переменные реализуются как указатели на объект, что дает возможность задать сначала значение 42, затем значение thanks for all the fish, а потом установить в качестве значения функцию.
Динамическая типизация, используемая в Python, зачастую считается недостатком, поскольку может привести к сложностям и появлению кода, для которого сложно выполнять отладку: если именованный объект может иметь в качестве значения множество разных вещей, разработчик поддерживающий код, должен отслеживать это имя в коде, чтобы убедиться, что оно не получило неуместное значение. В табл. 4.2 перечислены правила хорошего и плохого тона при именовании.
Совет | Плохой код | Хороший код |
---|---|---|
Используйте короткие функции или методы, чтобы снизить риск указания одного имени для двух несвязанных объектов | >a = 1 | >def get_answer(a): |
>a = 'answer is {}'.format(a) | >····return 'answer is | |
>····{}'.format(a) | ||
>a = get_answer(1) | ||
Используйте разные имена для связанных элементов, если они имеют разные типы | ># Строка… | >items_string = 'a b c d' |
>items = 'a b c d' | >items_list = items.split(' ') | |
># А теперь список | >items = set(items_list) | |
>items = items.split(' ') |