-->

calling function names with strings python

2019-09-17 10:09发布

问题:

I would like to be able to pass a call of either get, post, delete, etc, into my requests function. So instead of having all these different functions for each RESTFULness, I'd like to have a func like:

I have:

class BitbucketAPIHoss(object):

    API_URL_1 = 'https://api.bitbucket.org/1.0/'

    API_URL_2 = 'https://api.bitbucket.org/2.0/'

    HEADERS = {'Content-Type': 'application/json'}

    def __init__(self, username='codyc54321', password='trump_4_dictator_of_milky_way'):
        self.username = username
        self.password = password

    def get_bitbucket_project_names(self):
        repo_dicts = self.get_bitbucket_response_as_dict('user/repositories', "1")
        repo_names = extract_values(key='name', dictionaries=repo_dicts)
        return repo_names

    def create_repository(self, name=None):
        payload = {'scm': 'git',
                   'name': name,
                   'is_private': 'true',

        }
        json_payload = json.dumps(payload)
        url_ending = os.path.join('repositories', self.username, name)
        print(url_ending)
        response = self.post_to_bitbucket(url_ending=url_ending, payload=json_payload)
        print(response)

    def delete_repository(self, name=None):
        url_ending = os.path.join('repositories', self.username, name)
        print(url_ending)
        (url_ending=url_ending)


    def get_bitbucket_response_as_dict(self, url_ending, api_version="2"):
        if api_version == "2":
            api_url = self.API_URL_2
        elif api_version == "1":
            api_url = self.API_URL_1

        url = os.path.join(api_url, url_ending)
        r = requests.get(url, auth=(self.username, self.password), headers=self.HEADERS)
        content = r.text
        payload = demjson.decode(content)
        return payload

    def post_to_bitbucket(self, url_ending, payload=None, api_version="2"):
        if api_version == "2":
            api_url = self.API_URL_2
        elif api_version == "1":
            api_url = self.API_URL_1

        url = os.path.join(api_url, url_ending)
        if payload:
            r = requests.post(url, auth=(self.username, self.password), data=payload, headers=self.HEADERS)
        else:
            r = requests.post(url, auth=(self.username, self.password), headers=self.HEADERS)

try

def call_request(style):
    r = requests.style(url, auth=(username, pw), headers=headers)

call_request('get')

but no:

In [6]: def call(style):
    r = requests.style('https://api.bitbucket.org/1.0/', auth=('codyc54321', 'pw'), headers={'Content-Type': 'application/json'})
   ...:     

In [7]: call(get)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-7-72b682ad376c> in <module>()
----> 1 call(get)

NameError: name 'get' is not defined

In [8]: call('get')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-8-6a61a82da77f> in <module>()
----> 1 call('get')

<ipython-input-6-6ef72c4981c2> in call(style)
      1 def call(style):
----> 2     r = requests.style('https://api.bitbucket.org/1.0/', auth=('codyc54321', 'pw'), headers={'Content-Type': 'application/json'})
      3 

AttributeError: 'module' object has no attribute 'style'

Can I call any func I want w a string? I can't see how to use getattr here. Thank you

ANSWER:

    class BitbucketAPIHoss(object):

        API_URL_1 = 'https://api.bitbucket.org/1.0/'

        API_URL_2 = 'https://api.bitbucket.org/2.0/'

        HEADERS = {'Content-Type': 'application/json'}

        def __init__(self, username='codyc54321', password='why_so_broke_kanye?'):
            self.username = username
            self.password = password
            self.d = {'auth': (self.username, self.password), 'headers': self.HEADERS}

        def get_bitbucket_project_names(self):
            repo_dicts = self.call_api('get', 'user/repositories', api_version="1")
            repo_names = extract_values(key='name', dictionaries=repo_dicts)
            return repo_names

        def call_api(self, method, url_ending, api_version="2", **kwargs):
            if api_version == "2":
                api_url = self.API_URL_2
            elif api_version == "1":
                api_url = self.API_URL_1

            url = os.path.join(api_url, url_ending) # 'user/repositories'
            request_call_function = getattr(requests, method)
            kwargs.update(self.d)        
            r = request_call_function(url, **kwargs)
            payload = demjson.decode(r.content)
            return payload


In [1]: from my_scripting_library import *

In [2]: hoss = BitbucketAPIHoss()

In [3]: names = hoss.get
hoss.get_bitbucket_project_names     hoss.get_bitbucket_response_as_dict  

In [3]: names = hoss.get_bitbucket_project_names()

In [4]: names
Out[4]: 
[u'autohelper',
 u'bookwormbuddy',
 u'bytesized_python',
 u'fakething',
 u'foodpro',
 ...]

回答1:

I think you probably want getattr:

def call(method):
    f = getattr(requests, method)
    return f('https://api....', ...);