我正在创建一个Python脚本,它调用Instagram API并创建所有照片的数组。 API结果是分页的,因此它只显示25个结果。如果还有更多照片,则会为您提供next_url
,其中包含下一批照片。
我有用PHP编写的脚本,我在我的函数中做了类似的事情:
// loop through this current function again with the next batch of photos
if($data->pagination->next_url) :
$func = __FUNCTION__;
$next_url = json_decode(file_get_contents($data->pagination->next_url, true));
$func($next_url);
endif;
我怎样才能在Python中做这样的事情?
我的功能看起来像这样:
def add_images(url):
if url['pagination']['next_url']:
try:
next_file = urllib2.urlopen(url['pagination']['next_url'])
next_json = f.read()
finally:
# THIS DOES NOT WORK
next_url = json.loads(next_json)
add_images(next_url)
return
但显然我不能从内部调用add_images()。我有什么选择?
答案 0 :(得分:4)
您可以在add_images()
内致电add_images()
。上次我检查时,递归仍然适用于Python; - )。
但是,由于Python不支持尾调用消除,因此需要警惕堆栈溢出。 CPython的默认递归限制为1,000(可通过sys.getrecursionlimit()
获得),因此您可能不必担心。
然而,现在有了生成器和async
的出现,我认为这种JavaScript样式的递归回调调用 unpythonic 。您可以考虑使用生成器和/或协同程序:
def get_images(base_url):
url = base_url
while url:
with contextlib.closing(urllib2.urlopen(url)) as url_file:
json_data = url_file.read()
# get_image_urls() extracts the images from JSON and returns an iterable.
# python 3.3 and up have "yield from"
# (see https://www.python.org/dev/peps/pep-0380/)
for img_url in get_image_urls(json_data):
yield img_url
# dict.get() conveniently returns None or
# the provided default argument when the
# element is missing.
url = json_data.get('pagination', {}).get('next_url')
images = list(get_images(base_url));