Python网络开发中的装饰器与类

10 投票
2 回答
1960 浏览
提问于 2025-04-15 23:37

我注意到,Python的网页框架处理请求主要有三种方式:一种是使用装饰器,另一种是用控制器类来处理每个请求,还有一种是用请求类来处理GET和POST请求。

我对这三种方法的优缺点很感兴趣。它们之间有没有什么明显的优点或缺点呢?为了更好理解,下面有三个例子。

Bottle使用装饰器:

@route('/')
def index():
    return 'Hello World!'

Pylons使用控制器类:

class HelloController(BaseController):
    def index(self):
        return 'Hello World'

Tornado使用请求处理类,里面有不同类型的方法:

 class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

哪种风格是最佳实践呢?

2 个回答

1

各种框架都在努力通过最好的代码来实现最佳性能,这里的“最好”指的是写代码和读代码都要简单易懂。它们各自采用不同的策略,通常是围绕MVC(模型-视图-控制器)或MVT(模型-视图-模板)来进行的。

你关注的内容可能更多是个人喜好问题,我的回答也是如此。我尽量避免争论,因为可能有我不知道的有效技术理由。

但我个人更喜欢把路由(也就是处理请求的部分)和控制器(在Django中叫视图)分开,把模板(显示内容的部分)也分开。这样做让重用控制器变得非常简单。没错,我是Django的用户。

所以,我其实不太喜欢Bottle框架中的装饰器或者把东西放在很大的类里面。我以前是做ASP.NET开发的时候喜欢这样,但Django让我摆脱了这些。

10

其实你提到的这三种方法,每种都有它的原因,都是针对不同项目的需求。

  • Bottle的目标是让程序员的工作尽可能简单明了。使用装饰器来定义路由,这样开发者就不需要担心面向对象编程(OOP)的问题了。
  • Pylons的开发目标是让代码可以重复使用,并且能很容易地与WSGI风格的HTTP处理流程结合。因此,他们选择了一种非常面向对象的方式来组织路由。举个例子,你可以把HelloController复制粘贴到任何Pylons应用中,它就能神奇地工作。即使这个应用是通过某种复杂的方式在WSGI上运行的。
  • Tornado则有它自己的理由来这样做:Tornado的基于epoll的IOLoop(结合tornado.web.Application)会在请求到来时实例化每个请求处理器(RequestHandler)。通过将每个请求处理器限制为特定的GET或POST请求,这样IOLoop就能快速实例化这个类,处理请求,然后让它被垃圾回收。这样做可以保持快速和高效,同时占用的内存也很小,无论你的应用有多少个请求处理器。这也是Tornado能处理比其他基于Python的web服务器更多同时请求的原因(每个请求都有自己的实例)。

说了这么多,你应该知道其实你总是可以覆盖默认的框架行为。例如,我为Tornado写了一个MethodDispatcher,让它的工作方式更像Pylons(其实我写的时候是想着CherryPy)。这样做会让Tornado稍微慢一点(并且内存占用稍微增加),因为它有一个大的请求处理器,而不是很多小的,但这样可以减少你应用中的代码量,让代码更容易阅读(当然,这是我个人的看法=)。

撰写回答