欢迎关注公众号【哈希大数据】
系列文章目录:
【白话python连载(9.1)】 使用python处理文件
2 、python的程序结构——知其所以然
从小入手-python小应用
2017年已经步入尾声,听闻小伙伴们在畅想公司年会中的抽奖小惊喜,突然想到一个有意思的小应用--用Python实现抽奖流程,同时也借助该应用了解一下python程序的基本结构。
#问题描述:公司年终抽奖等级和人数的确定,并且从员工中进行随机抽选。 #!/usr/bin/python #coding=utf-8 importrandom importsys importcsv print('年终抽奖--你会是下一个幸运者吗') #定义抽奖的类 classLottery: #初始化所有抽奖人的名单地址 def__init__(self,filepath): self.datasource = filepath defGet_people(self): #获取待抽奖的用户的名单和用户个数 #获取方式,本次按照读取csv文件形式操作(也可以读取数据库等) people_list = [] withopen(self.datasource)assource : all_people = csv.reader(source) forpeopleinall_people: people_list.append(people) people_num = len(people_list) print('本次共有 {} 人参与抽奖'.format(people_num)) #用户输入确认抽奖的等级(一等奖、二等奖、三等奖),并且判断每个等级的奖品人数合理(不超过总人数) level = int(input('请输入本次抽奖分几等:')) level_dict = {} sum_level =0 foriinrange(level): print('请输入第 {} 等级的抽奖'.format(i+1)+'数:') one_level = int(sys.stdin.readline()) sum_level = sum_level + one_level ifsum_level <= people_num: level_dict[i] = one_level else: sum_origin = sum_level - one_level cha = people_num - sum_origin # print('输入人数超额,请重新输入小于%s的数'%cha) whileone_level > cha: print('人数超额,请重新输入小于 %s 的数'%cha) one_level = int(sys.stdin.readline()) sum_level = sum_origin + one_level level_dict[i] = one_level print('每个等级及对应人数',level_dict) # 抽取每个等级的获奖用户名单 foriinrange(len(level_dict)): level_peoples = [] forjinrange(int(level_dict[i])): level_people = random.choice(people_list) level_peoples.append(level_people) people_list.remove(level_people) print('第 %s 等级下被抽中的人员为:'% (i +1)) print(level_peoples) #类功能定义完毕,初始化并使用 if__name__ =='__main__': peoples = Lottery(r'D:\vernacular\data\5.csv') peoples.Get_people()
#运行结果
"D:\anaconda python\python3.6.exe"D:/vernacular/coding_ziyi/lottery.py
年终抽奖--你会是下一个幸运者吗
本次共有 18 人参与抽奖
请输入本次抽奖分几等:3
请输入第 1 等级的抽奖数:5
请输入第 2 等级的抽奖数:7
请输入第 3 等级的抽奖数:8
人数超额,请重新输入不大于 6 的数:7
人数超额,请重新输入不大于 6 的数:3
每个等级及对应人数 {0: 5, 1: 7,2: 3}
第 1 等级下被抽中的人员为:
[['zjdsj_014'], ['zjdsj_010'], ['zjdsj_007'], ['zjdsj_018'],['zjdsj_013']]
第 2 等级下被抽中的人员为:
[['zjdsj_001'], ['zjdsj_009'], ['zjdsj_004'], ['zjdsj_016'],['zjdsj_002'], ['zjdsj_008'], ['zjdsj_005']]
第 3 等级下被抽中的人员为:
[['zjdsj_011'], ['zjdsj_006'], ['zjdsj_015']]
Process finished with exit code 0
该应用实现的基本逻辑为:通过python读取员工信息表(核心:构建完整的抽奖员工名单列表)→设置本次抽奖的等级划分以及每个等级将获奖的人员数目(核心:要保证中奖的人数不能超过员工总人数)→依次抽出每个等级下的各个获奖人名单(核心:利用random函数保证抽奖的随机性)。
python程序结构详细介绍
依次来看该应用背后python的具体程序结构。一个规范的python程序,由起始行、文档字符串、模块导入部分、变量定义、函数定义、类定义、主程序等7大部分构成。其中起始行和文档字符串属于辅助程序架构,其余为核心程序架构。
起始行
为了保证良好的编程习惯,在每个python脚本文件起始行需要附上特殊标识和编码标识。
特殊标识
在Windows上虽然不能实现像.exe文件那样直接运行.py文件,但是,在Mac和Linux上是可以的,前提是需要在.py文件的第一行加上一个特殊的注释,然后,通过命令给***.py以执行权限,就可以直接运行.py文件了。
其中‘#’表示对python的单行代码进行注释(快捷键为:shift+3或Ctrl+/),而“’’’****’’’”表示同时对多行代码或整段代码进行注释。在python中单引号和双引号作用类似,但是必须成对出现,可以互相嵌入使用。
编码标识
Python3的字符串在内存中默认以Unicode进行编码,一个字符对应若干个字节。Unicode作为万国码,可以看做是一个符号集,它规定了如何编码,但没有规定如何传输、保存这个编码,而UTF-8作为Unicode的实现方式之一,最大的一个特点,根据不同的符号而变化字节长度,按照实际需求使用1~4个字节表示一个符号。因此在编写python程序时常采用utf-8的编码方式进行存储(可以确保代码的通用性)。
为方便代码的通用性,需要提前指定程序的编码方式,申明的方式主要有如下三种,这样可以保证python编译器在读取代码文件时按utf-8方式读取,但这个声明不能将py文件保存成utf-8格式的!而为了确保***.py文件是utf-8格式,需要在高级文档编辑器中设置。如果是使用pycharm的集成环境默认的保存的py文档为utf-8的。如果有需要可以通过查找‘file - settings – editor - fileencoding’进行修改。
如果想将Unicode的字符以utf-8形式保存,用encode(‘utf-8’)转化为utf-8编码的bytes,写入文件。对于可能采用gbk或其他编码方式进行存储的其他文件或者网页内容,需先明确源文件的编码格式,然后通过decode(‘gbk’)进行解码实现与其他数据进行交互。
统一设置
起始行的两条说明,需要在每个py文件中进行设置,因此pycharm也提供了统一设置的快捷方式,通过查找‘file -settings – editor - file and code templates – python scripte’进行设置。
文档字符串
文档字符串是辅助理解python程序的重要工具,而且属于程序某个对象的一个属性(__doc__),在运行程序时,可以从一个函数中返回文档字符串,提高交互性。
相关定义
包括模块导入的定义,变量的定义,函数的定义和类的定义。
主程序
Python程序在运行时其实并不需要主程序(main()),而是文件自上而下的依次执行,但是在很多python脚本中在最后的部分会执行一个判断语句if __name__ =="__main__:",之后还可能会有一些执行语句。这样做的目的是可以拓展python文件的多用性,既可以独立运行,也可以被当做模块导入(import)到其他文件。当导入到其他文件时,__name__一直将为导入程序的文件名,而不是__main__。这样也可以进一步控制可以执行的功能。只要将它们放到if __name__ =="__main__:"判断语句之后就可以了。
本次小结:
1.通过一个抽奖的小程序全面了解python程序的架构。
2.python程序的架构每部分的详细介绍,python的辅助部分起始行用于定义python的编码方式。文档字符串用于了解程序的说明。
3.python核心架构部分:模块导入方式,以及变量的定义、函数的定义、类的定义和主程序的编写等。
4.了解python的基本架构后,就可以愉快上手测试,进行基本程序的尝试。