Python软件开发目录规范
绝对导入与相对导入
"""
在程序中涉及到多个文件之间导入模块的情况,一律按照执行文件所在的路径为准
"""
from ty import test01
# 以执行路径所在的路径为准
绝对导入
始终按照执行文件所在的sys.path查找模块
ps:由于pycharm会自动将项目根目录添加到sys.path中,所以查找模块肯定不报错的方法就是永远从根路径往下一层层找
如果不是用pycharm运行 则需要将项目跟目录添加到sys.path(针对项目根目录的绝对路径有模块可以帮助我们获取>>>:os模块)
相对导入
"""
句点符(.)
.表示当前文件路径
..表示上一层文件路径
../..在路径中意思是上上一层路径
"""
能够打破始终以执行文件为准的规则 只考虑两个文件之间的位置
缺陷:
1.相对导入只能用在模块文件中 不能在执行文件中使用
2.相对导入在项目比较复杂的情况下 可能会出错
ps:相对导入尽量少用 推荐使用绝对导入![](https://www.icode9.com/i/l/?n=22&i=blog/2805882/202207/2805882-20220714215126619-1739530038.png)
-
绝对导入和相对导入插图(1)
-
绝对导入和相对导入插图(2)
- 使用from…import语句解决
包的概念
在Python中,一个包可以说是一个带特定信息的目录结构:
1、 一个包对应一个目录,包名和目录名保持一致;
2、 包对应目录下必须有一个__init__.py文件,该文件用来标记该目录为包;
3、 init.py文件可以为空,也可以是一个有效的python文件,加载包时实际上就是执行__init__.py文件;
4、 要将模块加入包中,只需将模块文件放在包目录中即可,一个包目录可以存放多个模块文件;
5、 包的组织结构中还可以套包,即包可以嵌套,也就是包目录下还可以有子包目录;
6、 从逻辑上看,包的本质是模块的集合,是多个模块依靠目录结构组织在一起形成功能集合对外提供能力输出;
7、 导入包的本质就是加载井执行该包下的__init__.py文件,然后将整个文件内容赋值给与包同名的变量,该变量的类型是 module;
8、 与模块类似,包被导入后会在包目录下生成一个__pycache__子目录,并在该目录内为包生成一个 init.cpython-37.pyc 文件。
init.py文件的使用
1.Python对于定义目录为包的__init__.py文件没有强制要求,只要是一个符合Python代码源文件的文件即可,甚至是一个空文件也可以;
2.包的主要作用是组织多个模块或子包提供功能集,而导入包就相当于导入该包下的 init.py 文件,因此实际使用时是将包的__init__.py 文件的用于导入该包内包含的模块,而不是用来定义程序单元;
3.通过导入包时自动导入包内模块,可把模块中的成员导入变成包内成员这样通过导入包就完成了包内模块的导入,对于调用者来说,只要完成包导入就可以了,不用关注包内的每个模块,通过包就可以访问包内每个模块或子包提供的功能,以后使用起来会更加方便;
4.当然也可以导入包时不自动导入包内所有模块,而让调用方自行导入包内的模块,这样调用方仅需导入包内调用方需要使用的模块,可以节省系统开销。
"""
针对python3解释器 其实文件夹里面有没有__init__.py已经无所谓了 都是包
但是针对Python2解释器 文件夹下面必须要有__init__.py才能被当做包
"""
编程思想演变
1.小白阶段
按照需求从上往下堆叠代码(面条版) 单文件
2.函数阶段
将代码按照功能的不同封装成不同的函数 单文件
3.模块阶段
根据功能的不同拆分不同的模块文件 多文件
"""
小白阶段相当于将所有的文件全部存储在C盘并且不分类
函数阶段相当于将所有的文件在C盘下分类存储
模块阶段相当于将所有的文件按照功能的不同分门别类到不同的盘中
目的为了更加方便快捷高效的管理资源
"""
软件开发目录规范
针对上述的第三个阶段 模块文件多了之后还需要有文件夹
我们所使用的所有的程序目录都有一定的规范(有多个文件夹)
目录规范并无固定的要求,只要符合清晰可读即可
bin文件夹
存放程序的启动文件
# start.py (start.py可以放在bin文件夹下也可以直接放在项目根目录)
conf文件夹
存放一系列配置文件
# settings.py
core文件夹
存放项目核心代码文件
# src.py
lib文件夹
存放程序公共功能
# common.py
db文件夹
存放数据相关文件
# userinfo.py
log文件夹
存放日志记录文件
# log.log
interfance文件夹
存放程序的接口文件
# user.py order.py goods.py
# readme
存放说明相关信息(类似于说明书 广告 章程)
# requirements.txt
存放所需要的第三方模块及版本
常见内置模块
数据类型模块
1.collections模块
在python中,除了整型、浮点型、字符串、列表、字典、元组、集合、布尔值这八种基本数据类型以外,还提供了更多特殊的数据类型
1.1 具名元组(namedtuple):生成可以使用名字来访问元素内容的tuple
from collections import namedtuple
# Point = namedtuple('二维坐标系', ['x', 'y'])
# print(Point) # <class '__main__.二维坐标系'>
# coordinate1 = Point(10, 20)
# coordinate2 = Point(100, 200)
# print(coordinate1) # 二维坐标系(x=10, y=20)
# print(coordinate2) # 二维坐标系(x=100, y=200)
# print(coordinate1.y) # 20
# print(coordinate2.x) # 100
# Point = namedtuple('三维坐标系', 'x y z')
# print(Point) # <class '__main__.三维坐标系'>
# coordinate1 = Point(10, 20, 30)
# coordinate2 = Point(100, 200, 300)
# print(coordinate1) # 二维坐标系(x=10, y=20, z=30)
# print(coordinate2) # 二维坐标系(x=100, y=200, z=300)
# print(coordinate1.y) # 20
# print(coordinate2.x) # 100
# poker = namedtuple('扑克牌', ['花色', '点数'])
# Game1 = poker('♥', '7')
# Game2 = poker('♠', '8')
# Game3 = poker('♦', '9')
# Game4 = poker('♣', 'k')
# print(Game1) # 扑克牌(花色='♥', 点数='7')
# print(Game2) # 扑克牌(花色='♠', 点数='8')
# print(Game3) # 扑克牌(花色='♦', 点数='9')
# print(Game4) # 扑克牌(花色='♣', 点数='k')
"""
模拟扑克牌21点游戏,网上找到的,看见有趣,于是乎发挥了我的拿来主义!!!
"""
# import random
# import sys
#
# # 牌面列表
# card_code = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
# # 花色列表
# card_symbol = ['♦', '♣', '♥', '♠']
#
#
# # 游戏初始化
# def init(player_count):
# # 根据玩家数来生成玩家记牌器
# player_group = [[] for _ in range(player_count)]
# # 根据玩家数来生成玩家是否要牌
# player_isWant = [True for _ in range(player_count)]
# # 生成元素1~52的列表 (去掉大小鬼的扑克牌[52张])
# poker = list(range(1, 53))
# # 用random的shuffle函数对列表打乱顺序 (洗牌)
# random.shuffle(poker)
# # 返回玩家组 玩家是否要牌 乱序52张扑克
# return player_group, player_isWant, poker
#
#
# # 打印玩家点数
# def print_player_point(player_group):
# # 存放玩家点数
# player_point = []
# # 遍历每一位玩家
# for index in range(len(player_group)):
# # 打印每位玩家的牌和点数
# print("-------玩家"+str(index+1)+"------")
# # 初始化玩家点数 如果含有牌A 因为A可视为1点或11点 则有两种点数
# current_player = [0, 0]
# # 遍历每位玩家的手牌
# for card in player_group[index]:
# """
# 核心代码
# 由于牌面的数字是从1到52 所以牌面要先减1再求余才是牌面列表真正的下标
# 若玩家抽到牌为15 即牌面为15 - 13 = 2 且按花色顺序为♣ 即2♣
# 牌面 15 - 1 = 14 再 14 % 13 = 1 这个就是对应牌面列表的第二位元素 即2
# 花色 15 - 1 = 14 再 14 / 13 = 1 对应花色列表第二位元素 即♣
# """
# # 获取牌面和花色下标
# code_index = int((card - 1) % 13)
# symbol_index = int((card - 1) / 13)
# # 打印玩家牌信息
# print(card_code[code_index] + card_symbol[symbol_index], end="/t")
# # 如果牌面含有A 则添加不同点数1和11
# if (code_index + 1) == 1:
# current_player[0] += 1
# current_player[1] += 11
# # 如果牌面不含A 则添加相同点数
# else:
# current_player[0] += code_index + 1
# current_player[1] += code_index + 1
# # 如果两个点数一致 则打印一个点数
# if current_player[0] == current_player[1]:
# print("点数为"+str(current_player[0])+"点")
# # 否则打印两个点数
# else:
# print("点数为"+str(current_player[0])+"点或"+str(current_player[1]))
# # 添加当前玩家点数
# player_point.append(current_player)
# # 返回所有玩家点数
# return player_point
#
#
# # 玩游戏
# def play_game():
# # 打印游戏规则
# print("-------21点游戏------")
# print("---A可看做1点或11点---")
# # 死循环一直进行游戏
# while True:
# # 初始化玩家数为0
# player_count = 0
# # 当玩家数小于等于1或大于5时继续询问
# while player_count <= 1 or player_count > 5:
# # 询问玩家数
# print("有多少位玩家?(2~5位)", end="")
# # 获取控制台输入的数字 无验证输入 若输入非数字 程序直接报错
# player_count = int(input())
# # 初始化游戏 返回玩家组 玩家是否要牌 乱序52张扑克
# player_group, player_isWant, poker = init(player_count)
# # 开始发牌 先为每位玩家发两张牌 循环玩家数
# for index in range(player_count):
# for i in range(2):
# # pop() 函数用于移除列表中的一个元素(默认最后一个元素)并且返回该元素的值。
# player_group[index].append(poker.pop())
# # 打印玩家点数 并获取当前玩家点数
# player_point = print_player_point(player_group)
# # 只要玩家继续要牌 且 还有剩余牌 则一直询问玩家是否要牌
# while True in player_isWant and len(poker) > 0:
# # 遍历玩家
# for index in range(player_count):
# # 判断玩家是否有可能还需要牌
# if player_isWant[index] is True:
# # 询问玩家是否要牌
# print("玩家"+str(index+1)+",您再要一张?(y/n)")
# # 获取控制台输入
# isWant = str(input())[0]
# # 如果输入的字符为"n" 则将玩家标记为不再需要牌
# if isWant == "n":
# player_isWant[index] = False
# # 如果不为字符"n" 默认为继续要牌 给该玩家发一张牌
# else:
# player_group[index].append(poker.pop())
# # 每轮询问结束 打印玩家点数 并获取当前玩家点数
# player_point = print_player_point(player_group)
# print("/n"*5+"====本轮游戏结束====")
# # 定义一个计分器
# score = []
# # 要牌结束 遍历所有玩家的点数 判断哪位玩家胜利
# for point_list in player_point:
# # 如果两个两个点数相同 说明没有A
# if point_list[0] == point_list[1]:
# # 如果分数大于21 直接取负数 小于等于21 任意取一个作为分数
# score.append(-point_list[0] if point_list[0] > 21 else point_list[0])
# # 如果两个点数不想同 说明含有A 则继续判断
# else:
# # 如果两个点数中大的那个点数还小于等于21
# if max(point_list) <= 21:
# # 去最大值为分数
# score.append(max(point_list))
# # 如果两个点数中大的那个点数大于21
# else:
# # 如果小的点数大于21 直接取负数 小于等于21 取最小值为分数
# score.append(-min(point_list) if min(point_list) > 21 else min(point_list))
# # 最高分
# max_point = max(score)
# # 如果最高分的人数为1 直接认为最高分的玩家获胜 打印游戏结果
# if score.count(max_point) == 1:
# print("玩家"+str(score.index(max_point) + 1)+"获胜!")
# # 否则最高分的分数有并列 认为有多个人获胜
# else:
# # 获胜玩家列表
# temp_list = []
# # 遍历分数
# for index in range(len(score)):
# # 分数等于最高分 记录玩家
# if score[index] == max_point:
# temp_list.append("玩家"+str(index+1))
# # 拼接获胜玩家列表 打印游戏结果
# print("恭喜"+",".join(temp_list)+"获胜!")
# # 询问是否继续游戏
# print("是否继续游戏?(y/n)")
# # 如果控制台输入不为字符"y" 表示退出
# if str(input())[0] != 'y':
# sys.exit()
#
#
# # 程序主入口
# if __name__ == '__main__':
# # 玩游戏
# play_game()
1.2 双端队列(deque)
deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈
deque除了实现list的append()和pop()外,还支持appendleft()和popleft(),这样就可以非常高效地往头部添加或删除元素
# from collections import deque
# l1 = deque()
# l1.append(666)
# l1.append(777)
# l1.append(888)
# l1.append(999)
# l1.appendleft(1000)
# print(l1) # deque([1000, 666, 777, 888, 999])
1.3 计数器(Counter) 主要用来计数
# from collections import Counter
# res = 'abcdeabcdabcaba'
# res1 = Counter(res)
# print(res1) # Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})
1.4 有序字典(Orderedict)
使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序
如果要保持Key的顺序,可以用OrderedDict
# from collections import OrderedDict
# d = dict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
# print(d) # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
# print(od) # OrderedDict([('a', 1), ('b', 2), ('c', 3)])
C:/Users/User_system>python2
Python 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:19:30) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> dict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
>>>
1.5 默认值字典(defaultdict)
# 有如下值集合 [11,22,33,44,55,66,77,88,99,90],
# 将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中
# {'k1':[], 'k2':[]}
# from collections import defaultdict
# res = defaultdict(k1=[],k2=[])
# print(res)
时间模块
2.时间模块之time模块
时间的三种格式
1.时间戳 time.time()
2.结构化时间 time.gmtime()
3.格式化时间 time.strftime()
# import time
# print(time.time()) # 1657805946.599186
# print(time.gmtime())
# time.struct_time(tm_year=2022, tm_mon=7, tm_mday=14, tm_hour=13, tm_min=39, tm_sec=6, tm_wday=3, tm_yday=195, tm_isdst=0)
# print(time.strftime('%Y-%m-%d %H:%M:%S')) # 2022-07-14 21:42:11
# print(time.strftime('%Y-%m-%d')) # 2022-07-14
# print(time.strftime('%H:%M:%S')) # 21:44:16
# print(time.strftime('%Y-%m-%d %X')) # 2022-07-14 21:44:16
# print(time.strptime('2022-07-14 21:44:16', '%Y-%m-%d %H:%M:%S'))
# time.struct_time(tm_year=2022, tm_mon=7, tm_mday=14, tm_hour=21, tm_min=44, tm_sec=16, tm_wday=3, tm_yday=195, tm_isdst=-1)
原创文章,作者:,如若转载,请注明出处:https://blog.ytso.com/tech/python/274408.html