关于使用base36的技巧 生成 优惠券兑换码的相关讨论

关于优惠券的生成后台的制作问题,已经拖了很久了还没有合并。但是持续暴露出来的问题 也很多,我的代码以及前面的一个人的代码被持续review暴露出了大量问题。昨天晚上在🔦大神review下 我又仔细 看了一下 前一个人 写的逻辑 发现他使用了一个 非常有趣的方法来生成 涵盖0-9a-zA-Z的兑换码。我戏称他为36位编码。

具体上一段代码

n_codes = 6 #这里可以随意传入想要生成的个数
rand_len = 6 #这里可以随意传入想要生成的位数
rand_limit = 36 ** rand_len
if n_codes > rand_limit / 2:
raise ValueError('n_codes and rand_len must satisfy ncodes > 36 ** rand_len / 2')
rand = _int_to_str(random.randrange(0, rand_limit), base=36).zfill(6)
code_text = prefix + rand
def _int_to_str(x, base=36):
    """Reversed version of int(s, base=?). src: http://stackoverflow.com/questions/2267362/"""
    numerals = string.digits + string.lowercase + string.uppercase

    if x == 0:
        return numerals[0]
    sign = -1 if x < 0 else 1
    x *= sign
    digits = []
    while x:
        digits.append(numerals[x % base])
        x /= base
    if sign < 0:
        digits.append(u'-')
    return u''.join(reversed(digits))

这里使用了一个_int_to_str的方法  传入的x则是0-36的n次方中间的任意一个数,然后 base为36. 下面为整个函数的解析

1. 下面_int_to_str函数 使用了一个 string模块 然后将0-9a-zA-Z包含到了一个叫numerals的变量之中。

2. 如果x==0 那么返回0

3. sign等于 如果x<0 sign等于-1 否则等于1 这一句判断传入的x是否为一个负数。并且取出其符号 从这一句可以看到 这个通用函数 其实并不是 前面这个作者自己写的。而是一个通用使用方法。用于解析指定base多少位数使用。 这里后面再讨论。

4. 如果为负数 转为正数

5. 申明一个digits = []

6. digits追加(numerals[传入x % base])

7. x/=base  这里注意了这里和上面式子呼应 一个取的是余数 处以36取到的余数一定是0-36之间的数,然后可以转换为string,而这里记录每次除以之后剩余的值

由于取的是36的n次方 这里也正好可以除n次,这样的话 就对应了生成多少个随机数了。

8. 然后跳出循环之后 判断符号 是否需要追加 负号 也就是 还原负号

9. 最后再将数组重新拼接成字符串返回

 

由此结束这样拆开来看 似乎还是比较清晰 合理的。后面再使用了一个 zfill()函数  不满这个数就往前用0补齐。 这样看来 的确也有够随机 而且 base参数实际上是可变化的。这个算法 蛮有意思 所以在这里 记录一下。与大家分享。

 

posted @ 2015-12-15 10:35  piperck  阅读(1361)  评论(0编辑  收藏  举报