今天学brython
的时候发现了它的ajax
请求太繁琐了。比如:
from browser import document, ajax url = "http://api.open-notify.org/iss-now.json" msg = "Position of the International Space Station at {}: {}" def complete(request): import json import datetime data = json.loads(request.responseText) position = data["iss_position"] ts = data["timestamp"] now = datetime.datetime.fromtimestamp(ts) document["zone10"].text = msg.format(now, position) def click(event): # 就是这个函数的代码,感觉挺没用的,还要敲好几行……一点不符合python的优雅 req = ajax.ajax() req.open("GET", url, True) req.bind("complete", complete) document["zone10"].text = "waiting..." req.send() document["button10"].bind("click", click)
这是官方给出的代码,然后我在想怎么将这坨代码搞得精简点。于是我想到了装饰器。鉴于我装饰器基础不是很扎实,但是为了以后敲代码的方便,我打算手撕一个python
库来一行代码解决ajax
的发送问题。为了解决这个问题,我把装饰器学了一遍(都怪我以前偷懒,觉得搞懂原理也没啥用,然后遇到问题了被迫学一遍)。
写这篇博客先主要理解下装饰器。
代码如下:
def hello(func): def world(): pass return world @hello def a(): print("hello world!")
装饰器代码等效于:
hello(a)
再精简点,等效于:
world # 对,就是这个函数名
所以调用这个函数:
a() # 等效于调用:hello(a)() -> 再等效于调用 world()
这个应该没问题了。
这个就直接把我的那个ajax
的例子放出来吧:
from browser import ajax, bind, document from functools import wraps def send_ajax(url, method="GET", data=None, sync=True): def hello(func): @wraps(func) def world(*args, **kwargs): req = ajax.ajax() req.open(method, url, sync) req.bind("complete", func) if data is None: req.send() else: req.send(data) return world return hello
然后使用:
from browser import bind, document from litter_ajax import send_ajax # 导入自己写的包 url = "http://api.open-notify.org/iss-now.json" msg = "Position of the International Space Station at {}: {}" @bind(document['button10'], 'click') @send_ajax(url, method="GET", data=None, sync=True) # 只用多添加一行代码即可! def complete(request): import json import datetime data = json.loads(request.responseText) position = data["iss_position"] ts = data["timestamp"] now = datetime.datetime.fromtimestamp(ts) document["zone10"].text = msg.format(now, position)
不过要注意,ajax
要在服务器下才能跨文件执行,可以用brython
提供的服务器命令:
py -m http.server
这样就可以了!对了,还有关键的没说:
好了,可以继续了。
和函数没啥区别,就是多了个__call__
函数:
class Hello: def __init__(self): pass def __call__(self, func): def world(): pass return world
对,和函数没啥区别,知道__call__
是干啥的这坨代码就没了。
还是拿我的代码举例子,如下:
class send_ajax: def __init__(self, url, method="GET", data=None, sync=True): self.url = url self.method = method self.data = data self.sync = sync def __call__(self, func): @wraps(func) def world(*args, **kwargs): req = ajax.ajax() req.open(self.method, self.url, self.sync) req.bind("complete", func) if self.data is None: req.send() else: req.send(self.data) return world
看懂了函数的代码想必这个代码也好理解。
好了,结束了 ~