【转载】在自定义的类里对 jqdatasdk 的 api 进行批量二次封装的方法

转自 https://zhuanlan.zhihu.com/p/50916846

简介

jqdatasdk 是聚宽的一个模块,主要用于从本地获取聚宽的金融数据,方便在本地进行量化研究,或者对接本地使用的交易系统。

如果要便捷的使用 jqdatasdk 的话,你可能会希望定义一个自定义的类,然后对 jqdatasdk 的 API 进行二次封装,从而实现较高自由度的调用,或者实现一些比较复杂的功能。

这里介绍一下如何借鉴 python 装饰器的技术来实现批量二次封装 jqdatasdk 的 API。其实这个方法同样也适用于二次封装其他的 API。

阅读之前

在阅读本文之前,你可能需要具备如下知识:

  1. python 基础
  2. python 面向对象的编程
  3. python 函数式编程:主要是装饰器、可变参数、关键字参数
  4. 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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值