我正在使用django开发ABtest框架。我想根据Cookie请求中的bucket_id分配变体编号。
bucket_id由前端设置,范围为0-99。
到目前为止,我已经创建了函数名称get_bucket_name:
def get_bucket_range(data):
range_bucket = []
first_val = 0
next_val = 0
for i, v in enumerate(data.split(",")):
v = int(v)
if i == 0:
first_val = v
range_bucket.append([0, first_val])
elif i == 1:
range_bucket.append([first_val, first_val + v])
next_val = first_val + v
else:
range_bucket.append([next_val, next_val + v])
next_val = next_val + v
return range_bucket
get_bucket_range的数据输入是一个逗号分隔的字符串,这意味着我们有3个变体,每个变体都有自己的权重,例如data =“ 25,25,50”,第一个变体的权重为25等。
然后我创建了一个函数来分配名为
的变体def assign_variant(range_bucket, num):
for i in range(len(range_bucket)):
if num in range(range_bucket[i][0], range_bucket[i][1]):
return i
此函数应具有2个参数,分别是get_bucket_range函数的range_bucket->和cookie的num-> bucket_id。
使用此函数,我可以返回属于变体ID的bucket_id。
例如,我们将25作为bucket_id,数据=“ 25,25,50”。这意味着我们的bucket_id应该属于变体ID1。或者在我们将25作为bucket_id的情况下,数据=“ 10,10,10,70”。这应该意味着我们的bucket_id将属于变体ID 2。
但是,感觉我的函数都不是pythonic或没有优化的。这里有人对我如何改进代码有任何建议吗?
答案 0 :(得分:1)
例如,您的函数可能如下所示:
def get_bucket_range(data):
last = 0
range_bucket = []
for v in map(int, data.split(',')):
range_bucket.append([last, last+v])
last += v
return range_bucket
def assign_variant(range_bucket, num):
for i, (low, high) in enumerate(range_bucket):
if low <= num < high:
return i
答案 1 :(得分:1)
使用itertools.accumulate和bisect.bisect函数可以大大减少函数的长度。第一个函数将所有权重求和(10,10,10,70
变成10,20,30,100
),第二个函数为您提供该元素所属位置的索引,在您的情况下,它等于组的索引它属于。
from itertools import accumulate
from bisect import bisect
def get_bucket_range(data):
return list(accumulate(map(int, data.split(',')))
def assign_variant(range_bucket, num):
return bisect(range_bucket, num)