软件开发目录规范、python常用内置模块

编程思想的转变

1.面条版阶段

    所有的代码全部堆叠在一起。可以看成是直接将所有的数据放在C盘
        视频、音频、文本、图片

2.函数版阶段

    根据功能的不同封装不同的函数。可以看成是将C盘下的数据分类管理
       视频文件夹、音频文件夹、文本文件夹、图片文件夹

3.模块版阶段

    根据功能的不同拆分成不同的py文件。可以看成是将C盘下的数据根据功能的不同划分到更合适的位置

        系统文件夹 C盘、视频文件夹 D盘、图片文件夹 E盘

  • ps:类似于开公司(小作坊>>>小公司>>>上市公司)
  • 目的:更方便快捷高效的管理资源

 

软件开发目录规范

为了提高程序的可读性和可维护性,我们应该为软件设计良好的目录结构,这与规范的编码风格同等重要。软件的目录规范并无硬性标准,只要清晰可读即可。

目录的规范优点

1.可读性高: 不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等。从而非常快速的了解这个项目。

2.可维护性高: 定义好组织规则后,维护者就能很明确地知道,新增的哪个文件和代码应该放在什么目录之下。这个好处是,随着时间的推移,代码/配置的规模增加,项目结构不会混乱,仍然能够组织良好。

文件分类详细

1.bin文件夹:

  • 用于存储程序的启动文件

>>>>>start.py    启动文件可以放在bin目录下,也可以直接在项目根目录

2.conf文件夹:

  • 用于存储程序的配置文件

          settings.py    里面存放项目的默认配置,一般都是全大写

3.core文件夹:

  • 用于存储程序的核心逻辑

           src.py     里面存放项目核心功能

4.lib文件夹:

  • 用于存储程序的公共功能  

          common.py

5.db文件夹:

  • 用于存储程序的数据文件

          userinfo.txt

          db_handler.py   存放数据库操作相关的代码

6.log文件夹:

  • 用于存储程序的日志文件

           log.log

7.interface文件夹:

  • 用于存储程序的接口文件

          user.py order.py goods.py

8.README文件(文本文件):

  • 用于存储程序的说明、介绍、广告(类似于产品说明书)

9.requirements.txt文件:

  • 用于存储程序所需的第三方模块名称和版本

补充

README文件说明

  • README文件是每个项目都应该有的一个文件

  • 目的:能简要描述该项目的信息,让读者快速了解这个项目

  • 需要说明以下几个事项:

    1. 软件定位,软件的基本功能
    2. 运行代码的方法:安装环境、启动命令等
    3. 简要的使用说明
    4. 代码目录结构说明,更详细点可以说明软件的基本原理
    5. 常见的问题说明

requirements.txt文件说明

  • 这个文件的存在是为了方便开发者,维护软件的依赖库,我们需要的第三方库都可以写进去,pycharm非常智能,会通过识别版本号以及包名导入,这样也方便我们查看使用了哪些python包。

注意:在编写软件的时候,可以不完全遵循上面的文件名

  • start.py可以放在bin文件夹下也可以直接放在项目根目录下
  • db文件夹等学到真正的项目会被数据库软件替代
  • log文件夹等学到真正的项目会被专门的日志服务替代

 

常用内置模块之collections模块

在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。

  1. namedtuple:具名元组,生成可以使用名字来访问元素内容的元组
  2. deque:双端队列,可以快速的从另一侧追加和推出对象
  3. Counter:计数器,主要用来计数
  4. OrderedDict:有序字典
  5. defaultdict:带有默认值的字典

namedtuple

from collections import namedtuple
point = namedtuple('二维坐标系',['x','y'])
p1 = point(1, 3)

print(p1)    # 二维坐标系(x=1, y=3)

print(p1.x)    # 1

print(p1.y)    # 3



point = namedtuple('三维坐标系',['x', 'y', 'z'])
p2 = point(2, 5, 6)

print(p2)    # 三维坐标系(x=2, y=5, z=6)

print(p2.x)    # 2

print(p2.y)    # 5

print(p2.z)    # 6


c = namedtuple('扑克牌', ['花色', '点数'])
c1 = c('', 'A')
c2 = c('', 'A')

print(c1)    # 扑克牌(花色='♥', 点数='A')

print(c2)    # 扑克牌(花色='♠', 点数='A')

 

deque

使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。

deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:

from collections import deque

q = deque()
q.append(111)
q.append(222)
q.append(333)
print(q)    # deque([111, 222, 333])

q.appendleft(555)
print(q)    # deque([555, 111, 222, 333])

deque除了实现list的append()pop()外,还支持appendleft()popleft(),这样就可以非常高效地往头部添加或删除元素。

Counter

Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。Counter类和其他语言的bags或multisets很相似。

例:统计字符串中每个字母出现的次数:

   s = 'abccbbbacaacbcab'

方法1:

s = 'abccbbbacaacbcab'
d = {}
for i in s:
    if i not in d:
        d[i] = 1
    else:
        d[i] += 1
print(d)    # {'a': 5, 'b': 6, 'c': 5}

方法2

from collections import Counter

s = 'abccbbbacaacbcab'
print(Counter(s))    # Counter({'b': 6, 'a': 5, 'c': 5})

 

OrderedDict

使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。

如果要保持Key的顺序,可以用OrderedDict

from collections import OrderedDict
d = dict([('a', 1), ('b', 2), ('c', 3)])
print(d)  # {'a': 1, 'b': 2, 'c': 3}
od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
print(od)  # OrderedDict([('a', 1), ('b', 2), ('c', 3)])

 

defaultdict

defaultdict是对Python中字典dict的改善

如果是字典dict:用法是dict={},

添加元素是dict[element]=value

调用是dict[element]

但是前提是element是存在于字典的,不然会报错误KeyError错误。

对于这种情况,defaultdict就可以避免这个错误,defaultdict的作用是在于,当字典里的element不存在但被查找时,返回的不是keyError而是一个默认值。

例:有一个列表:l1 = [11, 22, 33, 44, 55, 66, 77, 88, 99],将所有小于60的数保存到字典的第一个键中,将所有小于60的数保存到字典的第二个键中,即{'k1': 小于60的数,'k2': 大于60的数}

方法1:

l1 = [11, 22, 33, 44, 55, 66, 77, 88, 99]
d1 = {'k1':[], 'k2': []}
for i in l1:
    if i < 60:
        d1.get('k1').append(i)
    else:
        d1.get('k2').append(i)
print(d1)    # {'k1': [11, 22, 33, 44, 55], 'k2': [66, 77, 88, 99]}

方法2:(用得不多)

from collections import defaultdict
res = defaultdict(k1=[i for i in l1 if i < 66], k2=[i for i in l1 if i >= 66])
print(res)    # defaultdict(None, {'k1': [11, 22, 33, 44, 55], 'k2': [66, 77, 88, 99]})

使dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict

from collections import defaultdict
d = defaultdict(lambda: 'N/A')
d['key1'] = 'abc'
print(d['key1'])     # key1存在    'abc'
print(d['key2'])     # key2不存在,返回默认值 'N/A'

 

常用内置模块之时间模块

在Python中,通常有这三种方式来表示时间:时间戳、结构化时间(struct_time)、格式化时间字符串:

1. 时间戳(Timestamp) 

通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。

import time    # 导入时间模块
time.time()    # 时间戳
print(time.time())    # 1666168231.4251723

2. 结构化时间(主要给计算机看的,用得少)

3. 格式化时间

  • time.strftime()

  • 格式化符号:"%Y-%m-%d %H:%M:%S" 或 "%Y-%m-%d %X"

import time    # 导入时间模块
print(time.strftime('%Y-%m-%d %H:%M:%S'))    # 2022-10-19 16:38:09
print(time.strftime('%Y-%m-%d %X'))    # 2022-10-19 16:38:09

 

几种时间之间的相互转换

 

 

    datetime模块

import datetime    # 导入datetime模块
print(datetime.datetime.now())    # 获取当前时间 2022-10-19 16:53:26.651335

print(datetime.datetime.today())    # 获取当前时间 2022-10-19 16:53:26.651335

print(datetime.date.today())    # 获取当前日期  2022-10-19
from datetime import date, datetime    # 导入模块
print(date.today())    # 获取当前日期 2022-10-19
print(datetime.today())    # 获取当前时间 2022-10-19 16:58:13.340812

 

指定日期时间

c = datetime.datetime(2017, 5, 23, 12, 20)
# print('指定日期:',c)     # 指定日期: 2017-05-23 12:20:00

 

把不规则的时间转化为固定的格式

from datetime import datetime
d=datetime.strptime('2017/9/30','%Y/%m/%d')
print(d)  # 2017-09-30 00:00:00

e=datetime.strptime('2017年9月30日星期六','%Y年%m月%d日星期六')
print(e)    # 2017-09-30 00:00:00

f=datetime.strptime('2017年9月30日星期六8时42分24秒','%Y年%m月%d日星期六%H时%M分%S秒')
print(f)    # 2017-09-30 08:42:24

 

设置距离当前几天之后的时间

import datetime    # 导入模块
time1 = datetime.date.today()    # 设置当前模块
print(time1)
d_time = datetime.timedelta(days=3)    # 设置时间差值
print(time1 + d_time)    # 打印距离当前时间3天以后的时间
import datetime    # 导入模块
time1 = datetime.date.today()    # 设置当前模块
print(time1)    # 2022-10-19
d_time = datetime.timedelta(days=3)    # 设置时间差值
print(time1 + d_time)    # 打印距离当前时间3天以后的时间    # 2022-10-22

time2 = datetime.datetime.today()    # 设置当前模块
print(time2)    # 2022-10-19 17:22:55.336720
d_time = datetime.timedelta(minutes=20)    # 设置时间差值
print(time2 + d_time)    # 打印距离当前时间20分钟以后的时间    # 2022-10-19 17:42:55.336720

 

常用内置模块之随机数模块

  • import random
import random

print(random.random())    # 随机产生一个0-1之间的小数  0.4885910693172658

print(random.randint(1, 10))    # 随机产生一个1-10之间的整数  9

print(random.randrange(1,10, 2))    # 随机产生一个1-10之间的数,指定步长  3

print(random.choice(['一等奖', '二等奖', '三等奖', '谢谢惠顾']))   # 随机产生一个选项   一等奖

print(random.sample(['Alex', 'Bob', 'Cindy', 'Tony', 'Jason'], 2))    # 随机获取指数个数的样本  ['Alex', 'Bob']

l1 = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A']
random.shuffle(l1)    # 随机打乱数据集
print(l1)    # ['Q', 10, 9, 'J', 2, 3, 4, 5, 'A', 6, 'K', 8, 7]

 

小练习:

随机产生4位的图片验证码: 每一位都可以是大写字母、小写字母、数字 (搜狗公司的一道笔试题)

# 3. 循环取4次
for i in range(4):
    # 1. 先产生随机的大写字母、小写字母、数字
    random_upper = chr(random.randint(65,90))
    random_lower = chr(random.randint(97, 122))
    rand_int = str(random.randint(0, 9))

    # 2. 随机三选一
    temp = random.choice([random_upper, random_lower,rand_int])
    print(temp,end='')

拔高:如果要随机产生不同位数的验证码呢:

>>>考虑函数传参:

def get_code(n):
    code = ''
    # 3. 循环取4次
    for i in range(n):
        # 1. 先产生随机的大写字母、小写字母、数字
        random_upper = chr(random.randint(65,90))
        random_lower = chr(random.randint(97, 122))
        rand_int = str(random.randint(0, 9))

        # 2. 随机三选一
        temp = random.choice([random_upper, random_lower,rand_int])
        code += temp
    return code

res = get_code(5)   # 5位验证码,参数设置为5
print(res)

res = get_code(10)    # 10位验证码,参数设置为10
print(res)

 

posted @ 2022-10-19 18:16  莫~慌  阅读(198)  评论(0编辑  收藏  举报