当前位置 主页 > 服务器问题 > Linux/apache问题 >

    使用 Python 写一个简易的抽奖程序

    栏目:Linux/apache问题 时间:2019-12-09 10:13

    不知道有多少人是被这个头图骗进来的:)

    事情的起因是这样的,上周有同学问小编,看着小编的示例代码敲代码,感觉自己也会写了,如果不看的话,七七八八可能也写的出来,但是一旦自己独立写一段程序,感觉到无从下手。

    其实这个很正常,刚开始学习写代码,都是跟着别人的套路往下写,看的套路少,很难形成自己的套路,这就和做数学题是一样的,做一道题就想会所有的题目,这个可能性微乎其微,都是通过大量的练习来摸索到自己的套路。

    正好快过年了,各个公司都会搞一些抽奖活动,小编今天就来聊一下,如果要写一个简单的抽奖程序,小编是怎么写的。

    分析需求

    我们先整理下思路,目标是什么?

    目标是要写一个抽奖程序,那么抽奖程序的核心是什么?

    当然是如何判断一个人中奖了。那么如何判断一个人中奖呢?

    是不是可以通过随机函数来操作呢?

    中奖方法

    一步一步来,我们先通过随机函数来判断是否中奖。代码是不是可以先写成下面这样:

    import random
    
    # 判断中奖函数
    def lottery():
     flag = random.randint(0, 9)
     if flag < 2:
     return True
     else:
     return False

    首先,我们获取 0 ~ 9 之间的随机正整数(这里不讨论 random 是不是真随机,从狭义上来讲我们可以认为它是随机的),如果中奖率为 20% 的话,我们可以认为小于 2 的数字为中奖,其余的为没有中奖。然后中奖后返回 True ,没有中奖返回 False 。

    我们加一个入口测试函数,测试一下上面的代码是否能正常运行,并且中奖率是否能维持在大约 20 % 左右。

    if __name__ == '__main__':
     # 中奖次数
     a = 0
     # 没有中奖次数
     b = 0
     for i in range(1000000) :
     if (lottery()):
      a += 1
     else:
      b += 1
    
     print('共计中奖:', a, ',未中奖:', b)

    执行结果:

    共计中奖: 200145 ,未中奖: 799855

    上面的测试总共循环了 1 百万次,大约执行需要 2 ~ 3 秒左右,速度还是蛮快的。可以看到,中奖结果确实接近 20% 左右。

    动态中奖率

    难道到这里就结束了么?当然不可能,这里只是刚刚开了个头。

    如果这时老板说,你这个概率不能调整啊,需要让中奖率可以动态调整的,活动刚开始的时候中奖率要高,随着时间的推移,中奖率要降下来。

    这时候咋整,傻眼了吧。

    既然中奖率要可调整,那么我们中奖率就不能定死在程序中了,这个中奖率需要有一个地方去做存储,在每次做随机的时候将这个中奖率取出来。

    简单易行的方法就是将这个中奖率放在数据库中或者缓存服务中,这个根据实际业务场景来定。一般是根据预估访问压力的大小来进行技术选型,如果压力不是特别大,那么放在数据库中也是可以的,如果并发会比较高的话,建议还是放在缓存中。

    我们来写一个从数据库获取中奖概率的方法(为了展示直观,小编这里直接使用 Mysql 数据库用作数据存储),先看下数据库的数据:

    很简单的设计了一张表,里面有意义的字段有两个,一个用作中奖率的分子部分,一个用作中奖率的分母部分。分母部分最好要设置成 100 、 1000 、 10000 这种,这样计算中奖率会比较好计算。

    def get_lottery_rate():
     conn = pymysql.connect(host='localhost', user='root', password='password', database='test', charset='utf8mb4')
     try:
     sql = 'SELECT fenzi, fenmu FROM rate'
     cursor = conn.cursor()
     cursor.execute(sql)
     result = cursor.fetchone()
     return result
     except Exception as ex:
     print(ex)
     finally:
     conn.close()