python3经典实例
本文用于记录一些学习过程中使用python3写过的小程序,和一些经典的编程小例题。
【例题1】
编写一个简单的个人所得税计算器,设定起征点为3500元。print("个人所得税计算器\n")gongZi = int(input("请输入你的工资:"))qiZheng = gongZi - 3500suiWu = 0if gongZi <= 3500: print("无需缴纳个人所得税!")elif qiZheng <= 1500: suiWu = int(qiZheng * 0.03)elif qiZheng <= 4500: suiWu = int(qiZheng * 0.1) - 105elif qiZheng <= 9000: suiWu = int(qiZheng * 0.2) - 555elif qiZheng <= 35000: suiWu = int(qiZheng * 0.25) - 1005elif qiZheng <= 55000: suiWu = int(qiZheng * 0.30) - 2755elif qiZheng <= 80000: suiWu = int(qiZheng * 0.35) - 5505else: suiWu = int(qiZheng * 0.45) - 13505print("税前工资:", gongZi, "元")print("税后工资:", gongZi - suiWu, "元")print("需要缴纳个人所得税:", suiWu, "元")
【例题2】
使用for循环打印菱形#打印菱形for i in range(5): for j in range(5-i): print(" ", end=" ") for k in range(2 * i - 1): print("*", end=" ") print()for i2 in range(5): for j2 in range(i2): print(" ", end=" ") for k2 in range(2 * (5-i2) - 1): print("*", end=" ") k2+=1 print()
【例题3】
题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?# 用于计数的变量count = 0# 使用三个循环生成三个不同的数字for i in range(1, 5): for j in range(1, 5): for k in range(1, 5): # 三位数字不重复才进行组合 if i != j and i != k and j != k: # i组合第一位,j第二位,k第三位 print((i * 100) + (j * 10) + k) # 组合一次就计数一次 count += 1print(count)
【例题3】
使用python代码编写一个简单的爬虫:''' This is a spider'''from urllib import requestimport reclass Spider(): # 目标页面 url = '' # 如果不使用非贪婪模式就会匹配多个
root_pattern = ' ([\s\S]*?) ' name_pattern='([\s\S]*?)' number_pattern=' ([\s\S]*?)' # 读取网页数据 def __fetch_content(self): r = request.urlopen(Spider.url) # 读出来的是字节 htmls = r.read() htmls = str(htmls,encoding='utf-8') return htmls # 使用正则表达式匹配数据 def __analysis(self, htmls): root_html = re.findall(Spider.root_pattern, htmls) anchors = [] for html in root_html: name = re.findall(Spider.name_pattern,html) number = re.findall(Spider.number_pattern,html) anchor = {'name' : name, 'number' : number} anchors.append(anchor) return anchors # 数据精炼 def __refine(self, anchors): l = lambda anchor: { 'name':anchor['name'][0].strip(), 'number':anchor['number'][0] } return map(l, anchors) # 数据处理(排序) def __sort(self, anchors): # key指定排序元素 anchors = sorted(anchors, key=self.__sort_seed, reverse=True) return anchors # 排序种子 def __sort_seed(self, anchor): r = re.findall('\d*', anchor['number']) number = float(r[0]) if '万' in anchor['number']: number *= 10000 return number # 打印数据 def __show(self, anchors): for rank in range(0, len(anchors)): print('rank' + str(rank + 1) + ' : ' + anchors[rank]['name'] + '\t\t' + anchors[rank]['number'] + '人') # 总控方法 def go(self): htmls = self.__fetch_content() anchors = self.__analysis(htmls) anchors = list(self.__refine(anchors)) anchors = self.__sort(anchors) self.__show(anchors)s = Spider()s.go()【例题4】
题目:已知1颗六级石头的市场售价为750金,请问是自己合成石头划算还是直接购买划算''' 计算五行石是自己合成划算还是直接购买已经合成好的划算; 自己合成只能购买一级五行石; 七级和八级只能通过剥离获得 市场货币:金 还需要消耗金、钻石、体力'''''' 合成规律 1. 购买1级五行石:消耗金和钻石 2. 1级五行石合成3级五行石:消耗金、体力和1级五行石 3. 3级五行石合成4级五行石:消耗金、体力和1级五行石、一定概率 4. 4级五行石合成6级五行石:消耗金、体力和4级五行石 目标: 合成6级五行石'''''' 购买1级石头'''l1_value = 0.75 # 1颗1级石头消耗0.75金l1_value_diamond = 8 # 1颗1级石头同时还需要消耗8颗钻石''' 1级合成3级'''l1_to_l3 = 12 # 1颗1级石头变成1颗3级石头,需要消耗13颗1级石头l1_to_l3_gold = 0.39 # 同时还需要消耗0.39金l1_to_l3_vit = 10 # 同时还需要消耗10点体力''' 3级合成4级'''l3_to_l4 = 16 # 1颗3级石头变成1颗4级石头,需要消耗16个1级石头l3_to_14_gold = 0.897 # 1颗3级石头变成1颗4级石头,需要消耗0.897金l3_to_l4_vit = 10l3_to_l4_rate = 0.4878 # 1颗3级石头变成1颗4级石头,成功概率只有0.4878,并非100% # 如果失败,则金和16级1级石头也将被扣除,但是不消耗体力''' 4级合成6级'''l4_to_l6 = 12 # 12颗4级石头变成6级石头,概率100%l4_to_l6_gold = 19.75 # 需要消耗19.75金l4_to_l6_vit = 10''' 已知1颗六级石头的市场售价为750金,请问是自己合成石头划算还是直接购买划算 其他数据: 1颗钻石diamond 卖出0.05金 1点体力vit 可以卖出1金'''
实现代码:# 购买1级石头def buy_l1(l1_number): gold = l1_number * 0.75 diamond = l1_number * 8 return gold, diamond# 合成3级石头def l1_to_l3(l3_number): gold, diamond = buy_l1(l3_number * 12) gold += l3_number * 0.39 vit = l3_number * 10 return gold, diamond, vit# 合成4级石头def l3_to_l4(l4_number): # 需要先有相应的3级石头 gold, diamond, vit = l1_to_l3(l4_number) # 按照成功的前提计算出实际消耗的1级石头 count = l4_number * 16 wastage = count // 0.4878 # 购买实际消耗的1级石头 gold_l4, diamond_l4 = buy_l1(wastage) gold += gold_l4 diamond += diamond_l4 # 计算实际消耗的体力值 vit = (wastage//16) * l4_number gold += l4_number * 0.897 return gold, diamond, vit# 合成6级石头def l4_to_l6(l6_number): # 需要先有相应的4级石头 gold, diamond, vit = l3_to_l4(l6_number * 12) gold += l6_number * 19.75 vit += l6_number * 10 return gold, diamond, vit# 根据需要合成的数量与石头的级别,得到合成所需要消耗的金def synthesis(ln_name, number): if ln_name == 'L3': gold, diamond, vit = l1_to_l3(number) elif ln_name == 'L4': gold, diamond, vit = l3_to_l4(number) elif ln_name == 'L6': gold, diamond, vit = l4_to_l6(number) else: print("输入有误!") gold += vit gold += diamond*0.05 return gold# 处理用户的输入def user_input(): print("1.计算合成五行石所耗费的金", "\t", "2.计算购买1级五行石所耗费的金") input_str = input("请输入:") if input_str == "1": print("\n1.合成3级五行石", "\t", "2.合成4级五行石", "\t", "3.合成6级五行石") input_str = input("请输入:") num = int(input("请输入需要合成的数量:")) if input_str == "1": gold = synthesis('L3',num) print('\n需要消耗:', gold, '金') elif input_str == "2": gold = synthesis('L4',num) print('\n需要消耗:', gold, '金') elif input_str == "3": gold = synthesis('L6',num) print('\n需要消耗:', gold, '金') else: print("输入错误!") elif input_str == "2": num = int(input("请输入购买数量:")) gold, diamond = buy_l1(num) print("需要消耗", gold, '金,', diamond, '个钻石。') else: print("输入错误!")user_input()
【例题5】
过滤列表中的负数:from random import randint# randint生成-10到10之间的随机数data = [randint(-10,10) for _ in range(10)]print(data)# 需求:过滤列表中的负数lists = filter(lambda x:x >= 0,data)print(*lists)# 第二种解法lists2 = [x for x in data if x >= 0]print(lists2)# 列表推导式的性能要比filter高
【例题6】
筛出字典中值高于90的元素:from random import randintd = {x: randint(60, 100) for x in range(1, 21)}print(d)# 使用字典推导式实现di = {k: v for k,v in d.items() if v > 90}print(di)
【例题7】
过滤集合中能被3整除的子集:from random import randintdata = [randint(-10,10) for _ in range(10)]s = set(data)print(s)# 使用集合推导式实现si = {x for x in s if x % 3 ==0}print(si)
【例题8】
如何为元组中的每个元素命名, 提高程序可读性:# 学生信息系统中数据为固定格式:(名字,年龄,性别,邮箱地址,。。。。)# 学生数量很大为了减小存储开销,对每个学生信息用元组表示:# ('Jim', 16, 'man', 'jim8721@gmail')# 问题:访问时,我们使用下标访问,大量的使用下标会降低程序的可读性,如何解决这个问题?# 解决方案1:通过枚举类型来解决,也就是定义一系列数值常量from enum import Enumclass StudentEnum(Enum): NAME, AGE, SEX, EMAIL_ADDR = range(4)student = ('Jim', 16, 'man', 'jim8721@gmail')print(student[StudentEnum.NAME.value])print(student[StudentEnum.AGE.value])print(student[StudentEnum.SEX.value])print(student[StudentEnum.EMAIL_ADDR.value])# 解决方案2:使用标准库中collection.namedtuple替代内置tuplefrom collections import namedtuple# namedtuple会返回一个创建好的类,相当于是类的工厂Student = namedtuple('Student', ['name', 'age', 'sex', 'email_addr'])stu = Student('Jim', 16, 'man', 'jim8721@gmail')# 返回的类型是tuple的子类print(isinstance(stu, tuple))print(stu.name)print(stu.age)print(stu.sex)print(stu.email_addr)# 支持使用关键字传参stu2 = Student(name='Jim', age=16, sex='man', email_addr='jim8721@gmail')
【例题9】
从一个随机数列中,找到出现次数最高的3个元素,并统计出现的次数:# 需求:从一个随机数列中,找到出现次数最高的3个元素,并统计出现的次数from random import randintfrom collections import Counter# 生成一个随机序列data = [randint(0, 20) for _ in range(30)]print(data)# 使用序列中的元素作为键,数字0作为初始值,创建一个字典count = dict.fromkeys(data, 0)# 统计序列元素出现的次数for x in data: count[x] += 1# 对字典的value进行排序di = sorted(count.items(), key=lambda item: item[1], reverse=True)# 拿出前三个元素print(di[0:3])''' 另一个解决方法是将序列传入Counter构造器中,得到的对象是元素频度的字典, 也就是说可以得到一个根据字典中的value排序后的字典'''count2 = Counter(data)print(count2)# 通过most_common方法可以拿出字典的前n个元素,返回类型是列表print(count2.most_common(3))
【例题10】
对某英文文章的单词,进行词频统计,找到出现次数最高的10个单词,并统计出现的次数:# 需求:对某英文文章的单词,进行词频统计,找到出现次数最高的10个单词,并统计出现的次数import refrom collections import Counter# 读取文本内容txt = open('E:\\test.txt').read()# 对非字母的文字进行分割txt_list = re.split('\W+', txt)# 统计排序c3 = Counter(txt_list)# 拿出前10个元素print(c3.most_common(10))
【例题11】
根据成绩高低,计算学生排名:# 某班英语成绩以字典形式存储为:{'Lilei':79,'Jim':88,'Lucy':92...}# 需求:根据成绩高低,计算学生排名from random import randint# 生成一个随机字典data_dict = {x: randint(60, 100) for x in 'xyzabc'}# 方案1:利用zip将字典转换为元组进行排序:data_tuple = zip(data_dict.values(), data_dict.keys())print(sorted(data_tuple))# 方案2:传递sorted函数的key参数:data_list = sorted(data_dict.items(), key=lambda item: item[1],reverse=False)print(data_list)
【例题12】
制作一个简单的猜数字小游戏,需要添加历史记录功能,能够显示用户最近5次猜过的数字,并且记录要持久存储:''' 很多应用程序都有浏览用户的历史记录功能,例如: 1.浏览器可以查看最近访问过的网页 2.视频播放器可以查看最近播放过的视频文件 3.shell可以查看用户输入过的命令 ...... 需求:制作一个简单的猜数字小游戏,需要添加历史记录功能, 能够显示用户最近5次猜过的数字,并且记录要持久存储'''from random import randintimport pickle''' 使用容量为n的队列来存储历史记录,可以用到 collections中的deque,deque是一个双端循环队列'''from collections import dequeN = randint(0, 100)# 运行程序时将文件数据导入def get_history(): try: with open('E:\\history.txt', 'rb') as history_txt: history = pickle.load(history_txt) if history : return history except FileNotFoundError as e: # 第一个参数为队列的初始值,第二个参数为队列的容量 history = deque([], 5) return history# 猜数字def guess(key): if key == N: print('right') return True if key < N: print(key, 'is less-than N') else: print(key, 'is greater-than N') return False# 获得队列对象history = get_history()while True: line = input('please input a number: ') if line.isdigit(): key = int(line) # append是从右边入队 history.append(key) if guess(key): break # 当用户输入history或者h?时打印历史记录 elif line == 'history' or line == 'h?': print(list(history)) elif line == 'exit': # 程序退出前,可以使用pickle将队列对象存储到本地文件中 with open('E:\\history.txt', 'wb') as output: pickle.dump(history, output) break
【例题13】
从网络抓取各个城市气温信息,并依次显示:''' 从网络抓取各个城市气温信息,并依次显示: 北京:15~20 天津:17~22 长春:12~18 ...... 如果一次抓取所有城市天气再显示,显示第一个城市气温时,有很高的延迟,并且 浪费存储空间,我们期望以“用时访问”的策略,并且能把所有城市气温封装到一个 对象里,可用for语句进行迭代,如何解决?'''from collections import Iterable, Iteratorfrom urllib import requestimport urllibimport jsonimport gzip''' 1.实现一个迭代器对象WeatherIterator,__next__方法每次返回一个城市的气温, 迭代器对象的实现需要继承 Iterator'''class WeatherIterator(Iterator): def __init__(self, cities): ''' 构造器需要接收一个可迭代的对象,在这里这个cities是一个城市列表 index用于记录迭代次数,也用于充当下标索引 ''' self.cities = cities self.index = 0 def getWeather(self, city): ''' 抓取城市天气信息 ''' url_str = '=' + city # 转换URL的中文,safe参数指定哪些符号不转换 url = urllib.parse.quote(url_str, safe='/:?=') resp = request.urlopen(url).read() # 由于返回的的数据是gzip的压缩格式,所以需要解压返回的数据 resp = gzip.decompress(resp) # 将字节转换成字符串,编码设置为utf-8 json_data = str(resp, encoding = 'utf-8') # 解析json数据 data = json.loads(json_data)['data']['forecast'][0] return '%s: %s , %s ' % (city, data['low'], data['high']) def __next__(self): if self.index == len(self.cities): # 被迭代的次数等于迭代对象的长度时就需要抛异常 raise StopIteration # 从城市列表中迭代取出城市名称,每被取出一个,就需要增加一次迭代次数 city = self.cities[self.index] self.index += 1 # 返回城市的天气数据 return self.getWeather(city)''' 2.实现一个可迭代对象WeatherIterable,__iter__方法返回一个迭代器对象 可迭代对象的实现需要继承 Iterable'''class WeatherIterable(Iterable): def __init__(self, cities): self.cities = cities def __iter__(self): # 返回迭代器对象的实例 return WeatherIterator(self.cities)cities = ['北京', '上海', '广州', '深圳']for x in WeatherIterable(cities): print(x)
【例题14】实现一个可迭代对象的类,它能迭代出给定范围内所有素数:''' 将该类的__iter__方法实现成生成器函数,每次yield返回一个素数'''class PrimeNumbers: def __init__(self, start, end): ''' 初始化数字的范围 ''' self.start = start self.end = end def isPrime(self, k): ''' 判断是否是素数 ''' if k < 2: return False for i in range(2, k): if k % i == 0: return False return True def __iter__(self): for k in range(self.start, self.end + 1): # 是素数就返回 if self.isPrime(k): yield kfor x in PrimeNumbers(1, 100): print(x, end=' ')
【例题15】
实现一个连续浮点数发生器,根据给定范围和步进值产生一些列连续浮点数:''' 实现一个连续浮点数发生器FloatRange,根据给定范围 和步进值产生一些列连续浮点数'''class FloatRange: def __init__(self, start , end, step = 0.1): self.start = start self.end = end self.step = step def __iter__(self): ''' 正向迭代 ''' t = self.start while t <= self.end: yield t t += self.step def __reversed__(self): ''' 反向迭代 ''' t = self.end while t >= self.start: yield t t -= self.stepfor x in FloatRange(1.0, 4.0, 0.5): print(x, end=' ')print()for x in reversed(FloatRange(1.0, 4.0, 0.5)): print(x, end=' ')
【例题16】
使用readlines方法对迭代对象进行切片:''' 有某个文本文件,我们想读取其中某范围的内容,如100~300行 之间的内容。python中文本文件是可迭代对象,我们是否可以 使用类似列表切片的方式得到一个100~300行文件内容的生成器?'''# 使用标准库中的itertools.islice,它能返回一个迭代对象切片的生成器from itertools import islicef = open('E:/test.txt')# 迭代10到20行的内容for line in islice(f, 10, 20): print(line)# 迭代前10行的内容for line in islice(f, 10): print(line)# 迭代第10行到末尾行的内容for line in islice(f, 10, None): print(line)lists = range(20)t = iter(lists)for x in islice(t, 5, 10): print(x, end=' ')
【例题17】''' 1.某班学生期末考试成绩,语文、数学、英语分别存储在3个列表中,同时 迭代三个列表,计算每个学生的总分数(并行)'''from random import randintchinese = [randint(60, 100) for _ in range(40)]math = [randint(60, 100) for _ in range(40)]english = [randint(60, 100) for _ in range(40)]# 第一种解决方案就是使用循环,通过下标拿出相应的值,进行计算,但是这种方式局限性很大for i in range(len(chinese)): chinese[i] + math[i] + english[i]# 第二种方式就是使用内置函数zip,它能将多个可迭代对象合并,每次迭代返回一个元组total = []for c, m, e in zip(chinese, math, english): total.append(c + m + e)print(total)
【例题18】''' 2.某年级有4个班,某次考试每班英语成绩分别存储在4个列表中,依次迭代 每个列表,统计全学年成绩高于90分的人数(串行)'''# 使用标准库中的itertools.chain,它能将多个可迭代对象进行连接from itertools import chainfrom random import randint# 生成4个班的英语成绩class1 = [randint(60, 100) for _ in range(40)]class2 = [randint(60, 100) for _ in range(42)]class3 = [randint(60, 100) for _ in range(39)]class4 = [randint(60, 100) for _ in range(41)]# 存储高于90分的人数count = 0for s in chain(class1, class2, class3, class4): if s > 90: count += 1print('全学年成绩高于90分的人数为:' + str(count) + '人')
python3经典实例
本文用于记录一些学习过程中使用python3写过的小程序,和一些经典的编程小例题。
【例题1】
编写一个简单的个人所得税计算器,设定起征点为3500元。print("个人所得税计算器\n")gongZi = int(input("请输入你的工资:"))qiZheng = gongZi - 3500suiWu = 0if gongZi <= 3500: print("无需缴纳个人所得税!")elif qiZheng <= 1500: suiWu = int(qiZheng * 0.03)elif qiZheng <= 4500: suiWu = int(qiZheng * 0.1) - 105elif qiZheng <= 9000: suiWu = int(qiZheng * 0.2) - 555elif qiZheng <= 35000: suiWu = int(qiZheng * 0.25) - 1005elif qiZheng <= 55000: suiWu = int(qiZheng * 0.30) - 2755elif qiZheng <= 80000: suiWu = int(qiZheng * 0.35) - 5505else: suiWu = int(qiZheng * 0.45) - 13505print("税前工资:", gongZi, "元")print("税后工资:", gongZi - suiWu, "元")print("需要缴纳个人所得税:", suiWu, "元")
【例题2】
使用for循环打印菱形#打印菱形for i in range(5): for j in range(5-i): print(" ", end=" ") for k in range(2 * i - 1): print("*", end=" ") print()for i2 in range(5): for j2 in range(i2): print(" ", end=" ") for k2 in range(2 * (5-i2) - 1): print("*", end=" ") k2+=1 print()
【例题3】
题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?# 用于计数的变量count = 0# 使用三个循环生成三个不同的数字for i in range(1, 5): for j in range(1, 5): for k in range(1, 5): # 三位数字不重复才进行组合 if i != j and i != k and j != k: # i组合第一位,j第二位,k第三位 print((i * 100) + (j * 10) + k) # 组合一次就计数一次 count += 1print(count)
【例题3】
使用python代码编写一个简单的爬虫:''' This is a spider'''from urllib import requestimport reclass Spider(): # 目标页面 url = '' # 如果不使用非贪婪模式就会匹配多个
root_pattern = ' ([\s\S]*?) ' name_pattern='([\s\S]*?)' number_pattern=' ([\s\S]*?)' # 读取网页数据 def __fetch_content(self): r = request.urlopen(Spider.url) # 读出来的是字节 htmls = r.read() htmls = str(htmls,encoding='utf-8') return htmls # 使用正则表达式匹配数据 def __analysis(self, htmls): root_html = re.findall(Spider.root_pattern, htmls) anchors = [] for html in root_html: name = re.findall(Spider.name_pattern,html) number = re.findall(Spider.number_pattern,html) anchor = {'name' : name, 'number' : number} anchors.append(anchor) return anchors # 数据精炼 def __refine(self, anchors): l = lambda anchor: { 'name':anchor['name'][0].strip(), 'number':anchor['number'][0] } return map(l, anchors) # 数据处理(排序) def __sort(self, anchors): # key指定排序元素 anchors = sorted(anchors, key=self.__sort_seed, reverse=True) return anchors # 排序种子 def __sort_seed(self, anchor): r = re.findall('\d*', anchor['number']) number = float(r[0]) if '万' in anchor['number']: number *= 10000 return number # 打印数据 def __show(self, anchors): for rank in range(0, len(anchors)): print('rank' + str(rank + 1) + ' : ' + anchors[rank]['name'] + '\t\t' + anchors[rank]['number'] + '人') # 总控方法 def go(self): htmls = self.__fetch_content() anchors = self.__analysis(htmls) anchors = list(self.__refine(anchors)) anchors = self.__sort(anchors) self.__show(anchors)s = Spider()s.go()【例题4】
题目:已知1颗六级石头的市场售价为750金,请问是自己合成石头划算还是直接购买划算''' 计算五行石是自己合成划算还是直接购买已经合成好的划算; 自己合成只能购买一级五行石; 七级和八级只能通过剥离获得 市场货币:金 还需要消耗金、钻石、体力'''''' 合成规律 1. 购买1级五行石:消耗金和钻石 2. 1级五行石合成3级五行石:消耗金、体力和1级五行石 3. 3级五行石合成4级五行石:消耗金、体力和1级五行石、一定概率 4. 4级五行石合成6级五行石:消耗金、体力和4级五行石 目标: 合成6级五行石'''''' 购买1级石头'''l1_value = 0.75 # 1颗1级石头消耗0.75金l1_value_diamond = 8 # 1颗1级石头同时还需要消耗8颗钻石''' 1级合成3级'''l1_to_l3 = 12 # 1颗1级石头变成1颗3级石头,需要消耗13颗1级石头l1_to_l3_gold = 0.39 # 同时还需要消耗0.39金l1_to_l3_vit = 10 # 同时还需要消耗10点体力''' 3级合成4级'''l3_to_l4 = 16 # 1颗3级石头变成1颗4级石头,需要消耗16个1级石头l3_to_14_gold = 0.897 # 1颗3级石头变成1颗4级石头,需要消耗0.897金l3_to_l4_vit = 10l3_to_l4_rate = 0.4878 # 1颗3级石头变成1颗4级石头,成功概率只有0.4878,并非100% # 如果失败,则金和16级1级石头也将被扣除,但是不消耗体力''' 4级合成6级'''l4_to_l6 = 12 # 12颗4级石头变成6级石头,概率100%l4_to_l6_gold = 19.75 # 需要消耗19.75金l4_to_l6_vit = 10''' 已知1颗六级石头的市场售价为750金,请问是自己合成石头划算还是直接购买划算 其他数据: 1颗钻石diamond 卖出0.05金 1点体力vit 可以卖出1金'''
实现代码:# 购买1级石头def buy_l1(l1_number): gold = l1_number * 0.75 diamond = l1_number * 8 return gold, diamond# 合成3级石头def l1_to_l3(l3_number): gold, diamond = buy_l1(l3_number * 12) gold += l3_number * 0.39 vit = l3_number * 10 return gold, diamond, vit# 合成4级石头def l3_to_l4(l4_number): # 需要先有相应的3级石头 gold, diamond, vit = l1_to_l3(l4_number) # 按照成功的前提计算出实际消耗的1级石头 count = l4_number * 16 wastage = count // 0.4878 # 购买实际消耗的1级石头 gold_l4, diamond_l4 = buy_l1(wastage) gold += gold_l4 diamond += diamond_l4 # 计算实际消耗的体力值 vit = (wastage//16) * l4_number gold += l4_number * 0.897 return gold, diamond, vit# 合成6级石头def l4_to_l6(l6_number): # 需要先有相应的4级石头 gold, diamond, vit = l3_to_l4(l6_number * 12) gold += l6_number * 19.75 vit += l6_number * 10 return gold, diamond, vit# 根据需要合成的数量与石头的级别,得到合成所需要消耗的金def synthesis(ln_name, number): if ln_name == 'L3': gold, diamond, vit = l1_to_l3(number) elif ln_name == 'L4': gold, diamond, vit = l3_to_l4(number) elif ln_name == 'L6': gold, diamond, vit = l4_to_l6(number) else: print("输入有误!") gold += vit gold += diamond*0.05 return gold# 处理用户的输入def user_input(): print("1.计算合成五行石所耗费的金", "\t", "2.计算购买1级五行石所耗费的金") input_str = input("请输入:") if input_str == "1": print("\n1.合成3级五行石", "\t", "2.合成4级五行石", "\t", "3.合成6级五行石") input_str = input("请输入:") num = int(input("请输入需要合成的数量:")) if input_str == "1": gold = synthesis('L3',num) print('\n需要消耗:', gold, '金') elif input_str == "2": gold = synthesis('L4',num) print('\n需要消耗:', gold, '金') elif input_str == "3": gold = synthesis('L6',num) print('\n需要消耗:', gold, '金') else: print("输入错误!") elif input_str == "2": num = int(input("请输入购买数量:")) gold, diamond = buy_l1(num) print("需要消耗", gold, '金,', diamond, '个钻石。') else: print("输入错误!")user_input()
【例题5】
过滤列表中的负数:from random import randint# randint生成-10到10之间的随机数data = [randint(-10,10) for _ in range(10)]print(data)# 需求:过滤列表中的负数lists = filter(lambda x:x >= 0,data)print(*lists)# 第二种解法lists2 = [x for x in data if x >= 0]print(lists2)# 列表推导式的性能要比filter高
【例题6】
筛出字典中值高于90的元素:from random import randintd = {x: randint(60, 100) for x in range(1, 21)}print(d)# 使用字典推导式实现di = {k: v for k,v in d.items() if v > 90}print(di)
【例题7】
过滤集合中能被3整除的子集:from random import randintdata = [randint(-10,10) for _ in range(10)]s = set(data)print(s)# 使用集合推导式实现si = {x for x in s if x % 3 ==0}print(si)
【例题8】
如何为元组中的每个元素命名, 提高程序可读性:# 学生信息系统中数据为固定格式:(名字,年龄,性别,邮箱地址,。。。。)# 学生数量很大为了减小存储开销,对每个学生信息用元组表示:# ('Jim', 16, 'man', 'jim8721@gmail')# 问题:访问时,我们使用下标访问,大量的使用下标会降低程序的可读性,如何解决这个问题?# 解决方案1:通过枚举类型来解决,也就是定义一系列数值常量from enum import Enumclass StudentEnum(Enum): NAME, AGE, SEX, EMAIL_ADDR = range(4)student = ('Jim', 16, 'man', 'jim8721@gmail')print(student[StudentEnum.NAME.value])print(student[StudentEnum.AGE.value])print(student[StudentEnum.SEX.value])print(student[StudentEnum.EMAIL_ADDR.value])# 解决方案2:使用标准库中collection.namedtuple替代内置tuplefrom collections import namedtuple# namedtuple会返回一个创建好的类,相当于是类的工厂Student = namedtuple('Student', ['name', 'age', 'sex', 'email_addr'])stu = Student('Jim', 16, 'man', 'jim8721@gmail')# 返回的类型是tuple的子类print(isinstance(stu, tuple))print(stu.name)print(stu.age)print(stu.sex)print(stu.email_addr)# 支持使用关键字传参stu2 = Student(name='Jim', age=16, sex='man', email_addr='jim8721@gmail')
【例题9】
从一个随机数列中,找到出现次数最高的3个元素,并统计出现的次数:# 需求:从一个随机数列中,找到出现次数最高的3个元素,并统计出现的次数from random import randintfrom collections import Counter# 生成一个随机序列data = [randint(0, 20) for _ in range(30)]print(data)# 使用序列中的元素作为键,数字0作为初始值,创建一个字典count = dict.fromkeys(data, 0)# 统计序列元素出现的次数for x in data: count[x] += 1# 对字典的value进行排序di = sorted(count.items(), key=lambda item: item[1], reverse=True)# 拿出前三个元素print(di[0:3])''' 另一个解决方法是将序列传入Counter构造器中,得到的对象是元素频度的字典, 也就是说可以得到一个根据字典中的value排序后的字典'''count2 = Counter(data)print(count2)# 通过most_common方法可以拿出字典的前n个元素,返回类型是列表print(count2.most_common(3))
【例题10】
对某英文文章的单词,进行词频统计,找到出现次数最高的10个单词,并统计出现的次数:# 需求:对某英文文章的单词,进行词频统计,找到出现次数最高的10个单词,并统计出现的次数import refrom collections import Counter# 读取文本内容txt = open('E:\\test.txt').read()# 对非字母的文字进行分割txt_list = re.split('\W+', txt)# 统计排序c3 = Counter(txt_list)# 拿出前10个元素print(c3.most_common(10))
【例题11】
根据成绩高低,计算学生排名:# 某班英语成绩以字典形式存储为:{'Lilei':79,'Jim':88,'Lucy':92...}# 需求:根据成绩高低,计算学生排名from random import randint# 生成一个随机字典data_dict = {x: randint(60, 100) for x in 'xyzabc'}# 方案1:利用zip将字典转换为元组进行排序:data_tuple = zip(data_dict.values(), data_dict.keys())print(sorted(data_tuple))# 方案2:传递sorted函数的key参数:data_list = sorted(data_dict.items(), key=lambda item: item[1],reverse=False)print(data_list)
【例题12】
制作一个简单的猜数字小游戏,需要添加历史记录功能,能够显示用户最近5次猜过的数字,并且记录要持久存储:''' 很多应用程序都有浏览用户的历史记录功能,例如: 1.浏览器可以查看最近访问过的网页 2.视频播放器可以查看最近播放过的视频文件 3.shell可以查看用户输入过的命令 ...... 需求:制作一个简单的猜数字小游戏,需要添加历史记录功能, 能够显示用户最近5次猜过的数字,并且记录要持久存储'''from random import randintimport pickle''' 使用容量为n的队列来存储历史记录,可以用到 collections中的deque,deque是一个双端循环队列'''from collections import dequeN = randint(0, 100)# 运行程序时将文件数据导入def get_history(): try: with open('E:\\history.txt', 'rb') as history_txt: history = pickle.load(history_txt) if history : return history except FileNotFoundError as e: # 第一个参数为队列的初始值,第二个参数为队列的容量 history = deque([], 5) return history# 猜数字def guess(key): if key == N: print('right') return True if key < N: print(key, 'is less-than N') else: print(key, 'is greater-than N') return False# 获得队列对象history = get_history()while True: line = input('please input a number: ') if line.isdigit(): key = int(line) # append是从右边入队 history.append(key) if guess(key): break # 当用户输入history或者h?时打印历史记录 elif line == 'history' or line == 'h?': print(list(history)) elif line == 'exit': # 程序退出前,可以使用pickle将队列对象存储到本地文件中 with open('E:\\history.txt', 'wb') as output: pickle.dump(history, output) break
【例题13】
从网络抓取各个城市气温信息,并依次显示:''' 从网络抓取各个城市气温信息,并依次显示: 北京:15~20 天津:17~22 长春:12~18 ...... 如果一次抓取所有城市天气再显示,显示第一个城市气温时,有很高的延迟,并且 浪费存储空间,我们期望以“用时访问”的策略,并且能把所有城市气温封装到一个 对象里,可用for语句进行迭代,如何解决?'''from collections import Iterable, Iteratorfrom urllib import requestimport urllibimport jsonimport gzip''' 1.实现一个迭代器对象WeatherIterator,__next__方法每次返回一个城市的气温, 迭代器对象的实现需要继承 Iterator'''class WeatherIterator(Iterator): def __init__(self, cities): ''' 构造器需要接收一个可迭代的对象,在这里这个cities是一个城市列表 index用于记录迭代次数,也用于充当下标索引 ''' self.cities = cities self.index = 0 def getWeather(self, city): ''' 抓取城市天气信息 ''' url_str = '=' + city # 转换URL的中文,safe参数指定哪些符号不转换 url = urllib.parse.quote(url_str, safe='/:?=') resp = request.urlopen(url).read() # 由于返回的的数据是gzip的压缩格式,所以需要解压返回的数据 resp = gzip.decompress(resp) # 将字节转换成字符串,编码设置为utf-8 json_data = str(resp, encoding = 'utf-8') # 解析json数据 data = json.loads(json_data)['data']['forecast'][0] return '%s: %s , %s ' % (city, data['low'], data['high']) def __next__(self): if self.index == len(self.cities): # 被迭代的次数等于迭代对象的长度时就需要抛异常 raise StopIteration # 从城市列表中迭代取出城市名称,每被取出一个,就需要增加一次迭代次数 city = self.cities[self.index] self.index += 1 # 返回城市的天气数据 return self.getWeather(city)''' 2.实现一个可迭代对象WeatherIterable,__iter__方法返回一个迭代器对象 可迭代对象的实现需要继承 Iterable'''class WeatherIterable(Iterable): def __init__(self, cities): self.cities = cities def __iter__(self): # 返回迭代器对象的实例 return WeatherIterator(self.cities)cities = ['北京', '上海', '广州', '深圳']for x in WeatherIterable(cities): print(x)
【例题14】实现一个可迭代对象的类,它能迭代出给定范围内所有素数:''' 将该类的__iter__方法实现成生成器函数,每次yield返回一个素数'''class PrimeNumbers: def __init__(self, start, end): ''' 初始化数字的范围 ''' self.start = start self.end = end def isPrime(self, k): ''' 判断是否是素数 ''' if k < 2: return False for i in range(2, k): if k % i == 0: return False return True def __iter__(self): for k in range(self.start, self.end + 1): # 是素数就返回 if self.isPrime(k): yield kfor x in PrimeNumbers(1, 100): print(x, end=' ')
【例题15】
实现一个连续浮点数发生器,根据给定范围和步进值产生一些列连续浮点数:''' 实现一个连续浮点数发生器FloatRange,根据给定范围 和步进值产生一些列连续浮点数'''class FloatRange: def __init__(self, start , end, step = 0.1): self.start = start self.end = end self.step = step def __iter__(self): ''' 正向迭代 ''' t = self.start while t <= self.end: yield t t += self.step def __reversed__(self): ''' 反向迭代 ''' t = self.end while t >= self.start: yield t t -= self.stepfor x in FloatRange(1.0, 4.0, 0.5): print(x, end=' ')print()for x in reversed(FloatRange(1.0, 4.0, 0.5)): print(x, end=' ')
【例题16】
使用readlines方法对迭代对象进行切片:''' 有某个文本文件,我们想读取其中某范围的内容,如100~300行 之间的内容。python中文本文件是可迭代对象,我们是否可以 使用类似列表切片的方式得到一个100~300行文件内容的生成器?'''# 使用标准库中的itertools.islice,它能返回一个迭代对象切片的生成器from itertools import islicef = open('E:/test.txt')# 迭代10到20行的内容for line in islice(f, 10, 20): print(line)# 迭代前10行的内容for line in islice(f, 10): print(line)# 迭代第10行到末尾行的内容for line in islice(f, 10, None): print(line)lists = range(20)t = iter(lists)for x in islice(t, 5, 10): print(x, end=' ')
【例题17】''' 1.某班学生期末考试成绩,语文、数学、英语分别存储在3个列表中,同时 迭代三个列表,计算每个学生的总分数(并行)'''from random import randintchinese = [randint(60, 100) for _ in range(40)]math = [randint(60, 100) for _ in range(40)]english = [randint(60, 100) for _ in range(40)]# 第一种解决方案就是使用循环,通过下标拿出相应的值,进行计算,但是这种方式局限性很大for i in range(len(chinese)): chinese[i] + math[i] + english[i]# 第二种方式就是使用内置函数zip,它能将多个可迭代对象合并,每次迭代返回一个元组total = []for c, m, e in zip(chinese, math, english): total.append(c + m + e)print(total)
【例题18】''' 2.某年级有4个班,某次考试每班英语成绩分别存储在4个列表中,依次迭代 每个列表,统计全学年成绩高于90分的人数(串行)'''# 使用标准库中的itertools.chain,它能将多个可迭代对象进行连接from itertools import chainfrom random import randint# 生成4个班的英语成绩class1 = [randint(60, 100) for _ in range(40)]class2 = [randint(60, 100) for _ in range(42)]class3 = [randint(60, 100) for _ in range(39)]class4 = [randint(60, 100) for _ in range(41)]# 存储高于90分的人数count = 0for s in chain(class1, class2, class3, class4): if s > 90: count += 1print('全学年成绩高于90分的人数为:' + str(count) + '人')
发布评论