Его, упомянутый в других ответах о получении того же кода, работающего за обоими def get(self)
и def post(self)
для любого данного запроса. Я задавался вопросом, что используют люди методов, я думал:
class ListSubs(webapp.RequestHandler):
def get(self):
self._run()
def post(self):
self._run()
def _run(self):
self.response.out.write("This works nicely!")
Я бы предложил как теоретические, так и практические причины того, почему используемый вами подход (рефакторинг общего кода в отдельный метод и вызов его из методов post и get) превосходит очевидный - более простая альтернатива, когда один из этих двух методов вызывает другой.
С теоретической точки зрения, «метод A полностью делегирует методу B» подразумевает понятие «первичности» или «асимметрии» - проектное решение, которое, в дальнейшем, любое изменение, которое может быть применено к B, неизбежно, внутренне применимо и к A; что в будущем A может быть немного настроен по отношению к B (добавление некоторого дополнительного кода до и / или после вызова A для B), но никогда не наоборот. Когда нет причин ожидать такого превосходства, внедрять это понятие в свой код - плохое решение. Если и A, и B вызывают общий частный метод C, вы избегаете нарушения симметрии.
Некоторых не устраивают теоретические аргументы и они предпочитают прагматические аргументы: к счастью, в этом случае теоретические аргументы напрямую переходят в прагматические. Опять же, это проблема будущей эволюции кода: наличие как A, так и B вызова C оставляет вам все необходимые степени свободы для выполнения небольших настроек (добавление кода до и / или после вызова C) для любого, обоих или ни для одного из них. из A и B. Поскольку вы не знаете, какие части этой гибкости вам понадобятся, а цена простоты минимальна, выбор простого и гибкого пути весьма прагматичен и целесообразен.
Последний прагматический момент (применимый к любому варианту): всякий раз, когда у вас есть шаблон вроде:
def amethod(self):
return cmethod(self)
, вам обычно (скромно) лучше перефразировать это как
amethod = cmethod
Это позволяет избежать ненужного уровня вложенности вызовов (плоский лучше, чем вложенные). Итак, ваш класс можно было бы с пользой закодировать:
class ListSubs(webapp.RequestHandler):
def _run(self):
self.response.out.write("This works even better!")
get = post = _run
Ничего страшного, и вам придется выполнить рефакторинг обратно к исходному «вложенному» способу, если и когда вам действительно нужно применить настройки до или после вложенного вызова (из get
to _run
и т. д.) или нужны другие настройки в отладке (например, установите точку останова в отладчике на post
, но без триггера точки останова на get
и т. Д.), Но небольшое приятное упрощение для тех случаев, когда это возможно.
Рефакторинг кода, выполняющего работу, в его собственную функцию / метод - правильный метод.
Я использовал это:
class ListSubs(webapp.RequestHandler):
def post(self):
self.response.out.write("This works nicely!")
def get(self):
self.post()
Одна вещь, которую я не увидел в ответах и которые я добавлю, - это то, почему вам не следует этого делать. Довольно распространенный принцип, что изменение данных на сервере HTTP GET
- плохая идея. Изменение состояния сервера обычно должно происходить с помощью POST
. В результате каждый URL-адрес, который используется как для GET
, так и для POST
, должен иметь определенные действия, которые различаются в зависимости от типа запроса. В w3c есть хороший обзор того, когда использовать GET
по сравнению с POST
.
Я склонен думать о GET
и POST
как о геттере и сеттере. POST
изменяет данные, а GET
получает данные. В результате простой поиск может использовать GET
в течение всего дня, но когда вы сохраняете настройку обратно на сервер, POST
в порядке.
Например, у вас есть URL-адрес сообщения в вашем блоге ( example.com/blog/post-vs-get/
).Затем вы можете использовать get ()
, чтобы получить сообщение в блоге и отобразить его на экране с красивой формой комментариев. В этом примере моя форма комментария будет POST
обратно на тот же URL, вызывая метод post ()
, который может обработать форму и затем вернуть ту же обработанную страницу.
class ListSubs(webapp.RequestHandler):
def post(self):
comment = cgi.escape(self.request.get('comment'))
## Do magic with our comment.
self.get() ## Go off and return the rendered page.
def get(self):
## Get the blog post out of the data store and render a page.
self.response.out.write("""<html>
<body>
<p>My awesome blog post!</p>
<form method="post">
<h1>Comment</h1>
<textarea name="comment" rows="3" cols="60"></textarea>
<input type="submit" value="Comment">
</form>
</body>
</html>""")
Это дает четкое разделение труда между визуализацией страницы и обработкой данных POST. Это также предохраняет ваш код от ненужной проверки формы и / или обработки запроса без данных. На мой взгляд, такое разделение обязанностей также упрощает отладку и сопровождение кода.