简体   繁体   English

python递归装饰器

[英]python recursive decorator

I have a function that returns a list of dictionaries from an API call. 我有一个函数返回API调用中的字典列表。 The API can return max 100 records per request. API可以为每个请求返回最多100条记录。 Records are stored in pages, each page containing 100 records. 记录存储在页面中,每页包含100条记录。

def call_api(page):
    return list_of_records

what I need is a decorator that can re-run this function every time it returns 100 records with the page argument =+ 1. 我需要的是一个装饰器,每次返回100个带有页面参数= + 1的记录时都可以重新运行该函数。

something like: 就像是:

if len(list_of_records) == 100:
   call_api(page +=1)

the final output should be one single list with all the records 最终输出应该是包含所有记录的单个列表

Defining a decorator that recursively calls a function is certainly possible. 定义一个递归调用函数的装饰器当然是可能的。

Here is how such a decorator might look in your case: 以下是这种装饰器在您的情况下的外观:

import functools

def with_pages(func):
    @functools.wraps(func)

    def wrapper(page):
        list_of_records = []
        partial_list = func(page)
        list_of_records.extend(partial_list)
        while len(partial_list) == 100:  # there is probably a better condition to check if you are at the last page (e.g. next_page URI in api reply)
            page += 1
            partial_list = func(page)
            list_of_records.extend(partial_list)
        return list_of_records
    return wrapper

@with_pages
def call_api(page):
    # api interaction creating list_of_records_on_a_page
    return list_of_records_on_a_page

Alternatively, you can adapt call_api such that you can call it recursively. 或者,您可以调整call_api ,以便可以递归调用它。

Something like: 就像是:

def call_api(page, list_of_records=[]):
    partial_list = ... # the records you get from the api
    list_of_records.extend(partial_list)
    # often api provide the url for the next page or some more reliable info
    # about whether or not you are on the last page, i.e. testing for the length
    # of the reply is probably not the best strategy
    if len(partial_list) == 100:
        # time.sleep(0.2)  # just to not end up with to many requests in a short period of time
        call_api(page + 1, list_of_records)
    return list_of_records

Simply calling call_api(1) will be enough to get all pages. 只需调用call_api(1)即可获取所有页面。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM