关于使用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参数实际上是可变化的。这个算法 蛮有意思 所以在这里 记录一下。与大家分享。