Python生成自定义类并添加自定义方法

来源:互联网 发布:千牛和淘宝卖家 编辑:程序博客网 时间:2024/06/05 16:00

  最近准备做个简单的web服务器,通过配置url method header 等属性实现自定义的API,框架考虑的是Tornado和PyRestful。然后就遇到了问题,API的数量是动态生成的,每个API的请求方式也不一样。如果单纯的PyRestful是满足不了的。

import pyrestful.restimport tornado.ioloopfrom pyrestful import mediatypesfrom pyrestful.rest import get, postclass Book(object):    isbn = int    title = strclass BookResource(pyrestful.rest.RestHandler):    @get(_path="/books/json/{isbn}", _types=[int], _produces=mediatypes.APPLICATION_JSON)    def getBookJSON(self, isbn):        book = Book()        book.isbn = isbn        book.title = "My book for isbn " + str(isbn)        return book
  

  因此需要动态生成class及claas的method,还好Python是有对应的语法的:Metaclass

  通过继承type,重写__new__(cls, name, bases, attrs)方法

 class RestHandleMetaclass(type):        def __new__(cls, name, bases, attrs):    # do something ,such as redefinition attrs     # ps: attr is a tuple        return type.__new__(cls, name, (RestHandler,), attrs)

 

  接着遇到了第二个问题,@get(_path="/books/json/{isbn}", _types=[int], _produces=mediatypes.APPLICATION_JSON) 如何添加到方法上面。一开始我以为@符号是注解,走了不少弯路,后来才知道@在Python中是用来处理Decorator(装饰器)的。(参考资料:AB)。 由于attrs中的元素是方法,如何生成方法,同时已经被装饰器处理过,同时能修改@get()中的参数,并最终返回一个方法 成了第三个问题。还好pyrestful.rest.get启发了我

def get(*params, **kwparams):""" Decorator for config a python function like a Rest GET verb"""def method(f):return config(f,'GET',**kwparams)return method

  Python中的Method内部是可以定义Method,并返回Method的。同时尝试后发现内部定义的Method是可以加上@get,最终返回装饰器进行处理后的Method

class RestHandleMetaclass(type):    @staticmethod    def dynamicDecorator(data):        _path = "/books/json/" + str(data) + "/{isbn}"        _types = [int]        _produces = mediatypes.APPLICATION_JSON        @get(_path=_path, _types=_types, _produces=_produces)        def getBookJSON(self, isbn):            book = Book()            book.isbn = isbn            book.title = "My book for isbn " + str(isbn)            return book        return getBookJSON    def __new__(cls, name, bases, attrs):        for x in range(5):            attrs["getBookIsbn_" + str(x)] = RestHandleMetaclass.dynamicDecorator(x)        return type.__new__(cls, name, (RestHandler,), attrs)

  最后补上相关的代码。

class TestA(object, metaclass=RestHandleMetaclass):    pass
if __name__ == '__main__':    try:        print("Start the service")        app = pyrestful.rest.RestService([TestA])        app.listen(8080)        tornado.ioloop.IOLoop.instance().start()    except KeyboardInterrupt:        print("\nStop the service")


    

  


阅读全文
0 0