Python Decorators: различия между версиями
Материал из noname.com.ua
Перейти к навигацииПерейти к поискуSirmax (обсуждение | вклад) (Новая: =Декораторы в питоне= Разбор только одного примера, что был сложен для меня.) |
Sirmax (обсуждение | вклад) |
||
| (не показано 7 промежуточных версий этого же участника) | |||
| Строка 1: | Строка 1: | ||
| + | [[Категория:Python]] |
||
=Декораторы в питоне= |
=Декораторы в питоне= |
||
Разбор только одного примера, что был сложен для меня. |
Разбор только одного примера, что был сложен для меня. |
||
| + | |||
| + | |||
| + | <PRE> |
||
| + | # coding=utf8 |
||
| + | from webob import Request |
||
| + | from wsgiref import simple_server |
||
| + | from webob.exc import HTTPNotFound |
||
| + | |||
| + | </PRE> |
||
| + | webob - работа с HTTP |
||
| + | wsgiref - веб сервер. можно использовать любой другой, и имя им легион. |
||
| + | |||
| + | Декоратор. Сама идея декоратора прекрасна - обернуть вызов ф-и в другую ф-ю и потом переопределить оригинальную. |
||
| + | вот хорошие ссылки: |
||
| + | * http://habrahabr.ru/post/141411/ |
||
| + | * http://habrahabr.ru/post/139866/ |
||
| + | |||
| + | Это декоратор: |
||
| + | <PRE> |
||
| + | def webob_wrap(func): |
||
| + | def wrapped(environ, start_response): |
||
| + | aaa=100 |
||
| + | req = Request(environ) |
||
| + | app = func(req, environ) |
||
| + | return app(environ, start_response) |
||
| + | return wrapped |
||
| + | </PRE> |
||
| + | |||
| + | |||
| + | Это собственно функции которые борабатывают URL. |
||
| + | <PRE> |
||
| + | def list_topics_app(environ, start_response): |
||
| + | start_response('200 OK', [('Content-type', 'text/plain')]) |
||
| + | return "\n".join(["%s=%s" % (k, v) for k, v in environ.items()]) |
||
| + | #return "123" |
||
| + | |||
| + | def view_topic_app(environ, start_response): |
||
| + | start_response('200 OK', [('Content-type', 'text/plain')]) |
||
| + | return "\n".join(["%s=%s" % (k, v) for k, v in environ.items()]) |
||
| + | #return "123" |
||
| + | |||
| + | def fff(environ, start_response): |
||
| + | start_response('200 OK', [('Content-type', 'text/plain')]) |
||
| + | return "\n".join(["%s=%s" % (k, v) for k, v in environ.items()]) |
||
| + | </PRE> |
||
| + | |||
| + | <PRE> |
||
| + | @webob_wrap |
||
| + | def forum_app(req, environ): |
||
| + | peek = req.path_info_peek() |
||
| + | if not peek: |
||
| + | return list_topics_app |
||
| + | elif peek == 'new_topic': |
||
| + | return new_topic_app |
||
| + | elif peek.isdigit(): |
||
| + | topic_id = int(req.path_info_pop()) |
||
| + | environ['forum_app.topic_id'] = topic_id |
||
| + | return view_topic_app |
||
| + | else: |
||
| + | return HTTPNotFound() |
||
| + | </PRE> |
||
| + | |||
| + | Запуск сервера |
||
| + | <PRE> |
||
| + | server = simple_server.WSGIServer( |
||
| + | ('127.0.0.1', 8080), |
||
| + | simple_server.WSGIRequestHandler, |
||
| + | ) |
||
| + | |||
| + | server.set_app(forum_app) |
||
| + | server.serve_forever() |
||
| + | </PRE> |
||
| + | |||
| + | Логика работы приложения такая |
||
| + | * при любом запросе исполниться forum_app |
||
| + | * т.к. ф-я обернута в декоратор, то на самом деле вызов будет выглядеть так |
||
| + | <PRE> |
||
| + | forum_app=webob_wrap(forum_app): |
||
| + | forum_app(environ, start_response) |
||
| + | </PRE> |
||
| + | Т.е. в декоратор будут передано окружение. |
||
| + | * forum_app вернет ту ф-ю которая потом будет вызвана внутри декоратора |
||
| + | **app = func(req, environ) - эта строчка в app запишет ф-ю (но не вызывая ее!) в зависимости от req. |
||
| + | **return app(environ, start_response) - а вернет на самом деле результат одной из ф-я обрабатывающих URL |
||
Текущая версия на 15:41, 28 сентября 2012
Декораторы в питоне
Разбор только одного примера, что был сложен для меня.
# coding=utf8 from webob import Request from wsgiref import simple_server from webob.exc import HTTPNotFound
webob - работа с HTTP wsgiref - веб сервер. можно использовать любой другой, и имя им легион.
Декоратор. Сама идея декоратора прекрасна - обернуть вызов ф-и в другую ф-ю и потом переопределить оригинальную. вот хорошие ссылки:
Это декоратор:
def webob_wrap(func):
def wrapped(environ, start_response):
aaa=100
req = Request(environ)
app = func(req, environ)
return app(environ, start_response)
return wrapped
Это собственно функции которые борабатывают URL.
def list_topics_app(environ, start_response):
start_response('200 OK', [('Content-type', 'text/plain')])
return "\n".join(["%s=%s" % (k, v) for k, v in environ.items()])
#return "123"
def view_topic_app(environ, start_response):
start_response('200 OK', [('Content-type', 'text/plain')])
return "\n".join(["%s=%s" % (k, v) for k, v in environ.items()])
#return "123"
def fff(environ, start_response):
start_response('200 OK', [('Content-type', 'text/plain')])
return "\n".join(["%s=%s" % (k, v) for k, v in environ.items()])
@webob_wrap
def forum_app(req, environ):
peek = req.path_info_peek()
if not peek:
return list_topics_app
elif peek == 'new_topic':
return new_topic_app
elif peek.isdigit():
topic_id = int(req.path_info_pop())
environ['forum_app.topic_id'] = topic_id
return view_topic_app
else:
return HTTPNotFound()
Запуск сервера
server = simple_server.WSGIServer(
('127.0.0.1', 8080),
simple_server.WSGIRequestHandler,
)
server.set_app(forum_app)
server.serve_forever()
Логика работы приложения такая
- при любом запросе исполниться forum_app
- т.к. ф-я обернута в декоратор, то на самом деле вызов будет выглядеть так
forum_app=webob_wrap(forum_app): forum_app(environ, start_response)
Т.е. в декоратор будут передано окружение.
- forum_app вернет ту ф-ю которая потом будет вызвана внутри декоратора
- app = func(req, environ) - эта строчка в app запишет ф-ю (но не вызывая ее!) в зависимости от req.
- return app(environ, start_response) - а вернет на самом деле результат одной из ф-я обрабатывающих URL