使用** kwargs时强制关键字的最佳方法是什么?

时间:2014-09-16 19:12:05

标签: python parameters args kwargs

我不确定我是否在问题中使用了正确的术语。

目前,我正在尝试围绕Google的Blogger API(博客服务)制作包装器/界面。 [我知道它已经完成,但我正在使用它作为学习OOP / python的项目。]

我制作了一个从博客中获取25个帖子的方法:

def get_posts(self, **kwargs):
    """ Makes an API request. Returns list of posts. """

    api_url = '/blogs/{id}/posts'.format(id=self.id)
    return self._send_request(api_url, kwargs)

def _send_request(self, url, parameters={}):
    """ Sends an HTTP GET request to the Blogger API.
        Returns JSON decoded response as a dict. """

    url = '{base}{url}?'.format(base=self.base, url=url)

# Requests formats the parameters into the URL for me
    try:
        r = requests.get(url, params=parameters)
    except:
        print "** Could not reach url:\n", url
        return
    api_response = r.text
    return self._jload(api_response)

问题是,每次调用get_posts函数时都必须指定API密钥:

someblog = BloggerClient(url='http://someblog.blogger.com', key='0123')
someblog.get_posts(key=self.key)

每次API调用都要求将密钥作为URL上的参数发送。 那么,最好的方法是什么?

我正在考虑一种可能的方式(但可能不是最好的方法?),就是在_send_request()中将键添加到kwargs字典中:

def _send_request(self, url, parameters={}):
    """ Sends an HTTP get request to Blogger API.
        Returns JSON decoded response. """
# Format the full API URL:
    url = '{base}{url}?'.format(base=self.base, url=url)

# The api key will be always be added:
    parameters['key']= self.key
    try:
        r = requests.get(url, params=parameters)
    except:
        print "** Could not reach url:\n", url
        return
    api_response = r.text
    return self._jload(api_response)

我无法真正理解这样做的最佳方式(或最多的方式)。

2 个答案:

答案 0 :(得分:1)

您可以将其存储在命名常量中。

如果此代码不需要安全,只需

API_KEY = '1ih3f2ihf2f'

如果它将在某个服务器上托管或需要更安全,您可以将该值存储在环境变量中

在您的终端中:

export API_KEY='1ih3f2ihf2f'

然后在你的python脚本中:

import os
API_KEY = os.environ.get('API_KEY')

答案 1 :(得分:0)

  

问题是,每次调用get_posts函数时都必须指定API密钥:

如果真的只是这一种方法,那么显而易见的想法就是写一个包装器:

def get_posts(blog, *args, **kwargs):
    returns blog.get_posts(*args, key=key, **kwargs)

或者,更好的是,结束课程为你做这件事:

class KeyRememberingBloggerClient(BloggerClient):
    def __init__(self, *args, **kwargs):
        self.key = kwargs.pop('key')
        super(KeyRememberingBloggerClient, self).__init__(*args, **kwargs)
    def get_posts(self, *args, **kwargs):
        return super(KeyRememberingBloggerClient, self).get_posts(
            *args, key=self.key, **kwargs)

现在:

someblog = KeyRememberingBloggerClient(url='http://someblog.blogger.com', key='0123')
someblog.get_posts()

是的,您可以覆盖或monkeypatch所有其他方法使用的_send_request方法,但如果只有1或2个方法需要修复,为什么要深入研究类的未记录的内部,以及分叉其中一种方法的主体只是为了让你能够以一种你没想到的方式改变它,而不是干净利落地进行改变?

当然,如果有分散在4个不同类中的90种不同方法,您可能需要考虑以编程方式构建这些包装器(和/或对类进行monkeypatching)......或者只是修补一个私有方法,就像您正在做的那样。这似乎是合理的。