我有一系列函数都通过了dict,但是在每种情况下dict应该以{{1}}开头。但是我发现,在对不同视图的顺序请求中,dict会记住数据,导致后来出现问题。
以下是相关代码:
{}
所以问题出现了,我有一个调用def picasa_sync_friend(user_profile, friend_id, force_update=False):
logger.warn('picasa_sync_friend')
data, error = picasa_query_by_profile('albums', user_profile, replace=(friend_id))
....
def picasa_sync_albums(user_profile, friend_id="default"):
logger.warn('picasa_sync_albums')
data, error = picasa_query_by_profile('albums', user_profile, replace=(friend_id))
...
def picasa_sync_pictures(user_profile, album_id, force_update=False, full_update=False):
friend_id = picasa_get_album(user_profile, album_id).friend.foreign_reference
subject = 'photos' if full_update else 'thumbs'
logger.warn('picasa_sync_pictures')
data, error = picasa_query_by_profile(subject, user_profile, replace=(friend_id, album_id))
...
def picasa_query_by_profile(subject, user_profile, args={}, replace=(), format='xml'):
logger.warn('picasa_query_by_profile: %s' % args)
access_token = picasa_get_token(user_profile).access_token
response = picasa_query(subject, access_token, args=args, replace=replace)
...
def picasa_query(subject, access_token='', args={}, replace=()):
logger.warn('picasa_query: %s' % args)
url, request_args, method = picasa_query_params(subject, access_token=access_token, args=args, replace=replace)
...
def picasa_query_params(subject, access_token='', args={}, replace=()):
method = 'GET'
base_url = 'https://accounts.google.com/o/oauth2/'
logger.warn('picasa_query_params (before): %s' % args)
if subject == 'albums':
args['access_token'] = access_token
subject = ''
base_url = 'https://picasaweb.google.com/data/feed/api/user/%s' % replace
args['kind'] = 'album'
args['v'] = '2.0'
args['fields'] = 'entry(title,gphoto:id,gphoto:numphotos,published)'
elif subject == 'photos':
args['access_token'] = access_token
base_url = 'https://picasaweb.google.com/data/feed/api/user/%s/albumid/%s' % replace
args['v'] = '2.0'
args['kind'] = 'photo'
args['fields'] = 'entry(gphoto:id,content(@src),gphoto:width,gphoto:height)'
subject = ''
elif subject == 'thumbs':
args['access_token'] = access_token
base_url = 'https://picasaweb.google.com/data/feed/api/user/%s/albumid/%s' % replace
args['v'] = '2.0'
args['kind'] = 'photo'
args['fields'] = 'entry(gphoto:id,content(@src),gphoto:width,gphoto:height)'
args['max-results'] = ALBUM_THUMBNAIL_LIMIT
subject = ''
logger.warn('picasa_query_params (after ): %s' % args)
url = '%s%s' % (base_url, subject)
return url, args, method
然后调用picasa_sync_friend
并将所有专辑数据返回给客户端的视图。
然后,对于每个相册,客户端会发出单独请求,为picasa_sync_albums
调用picasa_sync_pictures
。
初始好友/专辑请求的记录器输出如下所示:
album_id
请注意WARNING 2013-01-26 07:27:23,611 picasa_sync_friend
WARNING 2013-01-26 07:27:23,617 picasa_query_by_profile:
{}
WARNING 2013-01-26 07:27:23,633 picasa_query:
{}
WARNING 2013-01-26 07:27:23,633 picasa_query_params (albums:before):
{}
WARNING 2013-01-26 07:27:23,633 picasa_query_params (:after ):
{'access_token': u'xxx', 'fields': 'entry(title,gphoto:id,gphoto:numphotos,published)', 'kind': 'album', 'v': '2.0'}
WARNING 2013-01-26 07:27:24,388 picasa_sync_albums
WARNING 2013-01-26 07:27:24,388 picasa_query_by_profile:
{'access_token': u'xxx', 'fields': 'entry(title,gphoto:id,gphoto:numphotos,published)', 'kind': 'album', 'v': '2.0'}
WARNING 2013-01-26 07:27:24,389 picasa_query:
{'access_token': u'xxx', 'fields': 'entry(title,gphoto:id,gphoto:numphotos,published)', 'kind': 'album', 'v': '2.0'}
WARNING 2013-01-26 07:27:24,389 picasa_query_params (before):
{'access_token': u'xxx', 'fields': 'entry(title,gphoto:id,gphoto:numphotos,published)', 'kind': 'album', 'v': '2.0'}
WARNING 2013-01-26 07:27:24,389 picasa_query_params (after ):
{'access_token': u'xxx', 'fields': 'entry(title,gphoto:id,gphoto:numphotos,published)', 'kind': 'album', 'v': '2.0'}
- > picasa_sync_albums
,首字母picasa_query_by_profile
dict已经填充,尽管args
没有向args数组键发送任何数据。
以上记录器输出结束了朋友/专辑请求,接下来要做的是直接进入picasa_sync_albums
的单个专辑的图片列表:
picasa_sync_pictures
请注意,在WARNING 2013-01-26 07:27:25,981 picasa_sync_pictures
WARNING 2013-01-26 07:27:25,998 picasa_query_by_profile:
{'access_token': u'xxx', 'fields': 'entry(title,gphoto:id,gphoto:numphotos,published)', 'kind': 'album', 'v': '2.0'}
WARNING 2013-01-26 07:27:26,011 picasa_query:
{'access_token': u'xxx', 'fields': 'entry(title,gphoto:id,gphoto:numphotos,published)', 'kind': 'album', 'v': '2.0'}
WARNING 2013-01-26 07:27:26,020 picasa_query_params (before):
{'access_token': u'xxx', 'fields': 'entry(title,gphoto:id,gphoto:numphotos,published)', 'kind': 'album', 'v': '2.0'}
WARNING 2013-01-26 07:27:26,022 picasa_query_params (after ):
{'access_token': u'xxx', 'fields': 'entry(gphoto:id,content(@src),gphoto:width,gphoto:height)', 'kind': 'photo', 'max-results': 4, 'v': '2.0'}
中,args已经包含picasa_query_by_profile
,尽管这可能是一个新请求。
如果我刷新页面,再次呼叫好友/专辑,我会得到以下日志输出:
'kind': 'album'
这是它开始真正影响应用程序的地方,因为它将WARNING 2013-01-26 07:45:32,589 picasa_sync_friend
WARNING 2013-01-26 07:45:32,593 picasa_query_by_profile:
{'access_token': u'xxx', 'fields': 'entry(gphoto:id,content(@src),gphoto:width,gphoto:height)', 'kind': 'photo', 'max-results': 4, 'v': '2.0'}
WARNING 2013-01-26 07:45:32,597 picasa_query:
{'access_token': u'xxx', 'fields': 'entry(gphoto:id,content(@src),gphoto:width,gphoto:height)', 'kind': 'photo', 'max-results': 4, 'v': '2.0'}
WARNING 2013-01-26 07:45:32,598 picasa_query_params (before):
{'access_token': u'xxx', 'fields': 'entry(gphoto:id,content(@src),gphoto:width,gphoto:height)', 'kind': 'photo', 'max-results': 4, 'v': '2.0'}
WARNING 2013-01-26 07:45:32,600 picasa_query_params (after ):
{'access_token': u'xxx', 'fields': 'entry(title,gphoto:id,gphoto:numphotos,published)', 'kind': 'album', 'max-results': 4, 'v': '2.0'}
等内容应用于专辑列表,这是不可取的。
现在我可以通过非常明确地删除不应用于某些主题的dict项目来解决所有这些问题,但是这使得这非常难以维护,并且该计划的目标是可以扩展到许多不同的主题所以它需要灵活,不容易脱轨。
我很确定我在这里错过了python / django的一些基本部分,但我完全不知道解释上述行为!谢谢你的任何建议。
答案 0 :(得分:3)
您不应该使用可变值作为Python函数的默认参数。请考虑以下事项:
def f(arg={}):
print arg
if 'count' in arg:
arg['count'] += 1
else:
arg['count'] = 1
f()
f()
f()
这令人惊讶地打印出来
{}
{'count': 1}
{'count': 2}
{}
中的f(arg={})
被评估一次,并且每当调用f()
时都会传递相同的字典。因此,args
的任何更改都会在调用过程中持续存在。
修复上述代码的一种方法是:
def f(arg=None):
if not arg:
arg = {}
print arg
if 'count' in arg:
arg['count'] += 1
else:
arg['count'] = 1
您的代码中的以下函数会受到此问题的影响:
def picasa_query_by_profile(subject, user_profile, args={}, replace=(), format='xml'):
def picasa_query(subject, access_token='', args={}, replace=()):
def picasa_query_params(subject, access_token='', args={}, replace=()):
答案 1 :(得分:1)
不要将mutables用作默认值。更改所有代码案例:
def picasa_query(subject, access_token='', args={}, replace=()):
...
对此:
def picasa_query(subject, access_token='', args=None, replace=()):
if args is None:
args = {}
...
在创建函数对象时,仅对一次评估函数的默认值,并且从那时起将同一对象用作默认值。这是最常见的python gotchas之一。