在自定义的类里对jqdatasdk的api进行批量二次封装的方法
简介
jqdatasdk是聚宽的一个模块,主要用于从本地获取聚宽的金融数据,方便在本地进行量化研究,或者对接本地使用的交易系统。
如果要便捷的使用jqdatasdk的话,你可能会希望定义一个自定义的类,然后对jqdatasdk的API进行二次封装,从而实现较高自由度的调用,或者实现一些比较复杂的功能。
这里介绍一下如何借鉴python装饰器的技术来实现批量二次封装jqdatasdk的API。其实这个方法同样也适用于二次封装其他的API。
阅读之前
在阅读本文之前,你可能需要具备如下知识:
- python基础
- python面向对象的编程
- python函数式编程:主要是装饰器、可变参数、关键字参数
- python魔法方法
注意:为了简化代码,下面演示的代码中有部分是伪代码。
为了区别自然语言”方法“和编程中面向对象的”方法“, 以免理解起来有混淆,我用中英文进行区分,编程的方法用英文method来表示。
开始
在批量操作之前,先介绍一下最简单的二次封装API的方法,方便进行理解。
最简单的方法,就是直接创建一个同名的method,然后指向jqdatasdk的method。
优点是灵活度高,比如可以增加调用前的判断条件,调用结束后运行其他method等。缺点是麻烦,机械劳动太多,而且代码重复量大。如果要二次封装的API数量很多的话,显然不适合。
import jqdatasdk
class JQData():
def __init__(self):
self._sdk = jqdatasdk
def get_price(self, *args, **kwargs):
if condition:
return self._sdk.get_price(*args, **kwargs)
else:
do_somthing()
如果不想做这么多重复工作的话,可以用__getattr__这个魔法method来实现代理调用。
简单来说,getattr__就是当调用一个没有定义的属性或者method时进行的操作。因此我们可以写一个__getattr,当调用jqdatasdk的method时,因为我们的类中没有这些method,所以直接借助getattr(),返回了jqdatasdk的method,从而实现代理访问(注意:__getattr__和getattr是有区别的,具体区别可以自己去搜索)。
但是,这里也有一个明显的缺点,就是它是直接调用API,不能像上面的方法一样,加入一些其他的操作。
import jqdatasdk
class JQData():
def __init__(self):
self._sdk = jqdatasdk
def __getattr__(self, name):
# 这里还可以自己定义哪些方法要进行代理访问。
methods = [i for i in self._skd.__dict__ if i.startswith('get_')]
if name in methods:
return getattr(self._sdk, name)
因此,我们需要一个方法,既可以省去机械劳动,减少代码重复量,又可以实现比较高的灵活度,方便加入一些其他操作。这里,我们借鉴一下python装饰器的思路。
在这里,我们让__getattr__不要直接返回jqdatasdk的method,而是运行了一个"中间"method,而运行这个"中间"method返回的一个是真正的调用API的函数(注意:返回的对象是一个函数)。这个函数可以定义一些自己的操作。
如果觉得不是很好的理解的话,可能需要先去看看装饰器方面的内容。
class JQData():
def __init__(self):
self._sdk = jqdatasdk
def __getattr__(self, name):
# 这里还可以自己定义哪些方法要进行代理访问。
methods = [i for i in self._skd.__dict__ if i.startswith('get_')]
if name in methods:
return self._run_func(name)
def _run_func(self, name):
def wrapper(*args, **kwargs):
if condition:
func = getattr(self._sdk, name)
df = func(*args, **kwargs)
self.do_something(df)
return df
else:
do_otherthing()
return wrapper