python(八)——递归,排序,模块

递归

	一种直接或间接自身调用自身的过程
	必须设定递归程序的出口
	递归次数过多会报错,超过递归最大深度(一般不超过1000次,可以自己设置)
	递归会使代码变得简洁,但效率极低
	import sys
	sys.setrecursionlimit(10000)设置递归深度
	递归次数过多就不要用递归,会消耗大量内存

递归应用

斐波那契数列

#斐波那契数列
def fib(n):
    if n == 0 or n == 1:
        return 1,1
    a,b = fib(n-1)
    return b,a+b
print(fib(5))#(5, 8) 每次返回两个值 ,只需要返回一个值的话,可以设计一个标记值,每深入一层递归,值加1,每往上一层-1,当标记值为0,即为最外层,返回一个值即可

阶乘

#阶乘    3! = 3 * 2 * 1
def f(n):
    if n == 1:
        return 1
    return n * f(n-1)
print(f(3))#6

排序

冒泡排序

#冒泡排序
l = [36,45,79,12,31,54,47,25,15,55,74]
length = len(l)
for i in range(length):
    flag = False
    for j in range(length - i - 1):
        if l[j] > l[j + 1]: #如果前一个值大于后一个值就将较大的那个值后移 升序排序  < 就是降序排序
            l[j] , l[j + 1] = l[j + 1] , l[j]
            flag = True #发生了数值的位置互换
    if not flag :   #优化点,如果某一次没有发生数值的交换,说明此事列表已经排序好了,剩余的元素不需要继续去比较了
        break
print(l)#[79, 74, 55, 54, 47, 45, 36, 31, 25, 15, 12]

插入排序

#插入排序    
'''
一个序列中只有1个元素那它一定是有序的
取原序列第一个元素作为子序列,这个子序列一定是有序的
取出原序列第二个元素赋值给哨兵,将哨兵的值与子序列最后一个元素进行比较
        如果子序列最后一个元素大于哨兵的值,将子序列扩大一位,将子序列最后一个元素后移一位
        循环遍历哨兵与子序列前一位的值的大小,直到当前值小于哨兵的值,就将哨兵的值放在子序列当前下标+1处
        这样子序列一样是有序的

		如果子序列最后一个元素小于哨兵的值,就将哨兵的值放在子序列当前下标+1处,就是子序列最后一个元素下标 + 1处
取出原序列第三个元素赋值给哨兵。。。。
'''
l = [36,45,12,31,54,47,25,15,55,79,53,74]  # 原序列
ls = [0] + l #新序列 下标0的元素为哨兵 下标1元素为子序列
length = len(ls)
for i in range(2,length):#从原序列中取值
    ls[0] = ls[i] #放置哨兵
    j = i - 1 #子序列最后一个元素的下标,子序列为有序序列
    if ls[j] > ls[0]:   #如果子序列最后一个元素大于哨兵的值,可以放入这个有序序列中
        while ls[j] > ls[0]:
            ls[j+1] = ls[j]  #子序列最后一个后移一位
            j -= 1 #取出子序列前一位的下标
    ls[j+1] = ls[0] #将哨兵放置在子序列中相应位置 或者 哨兵值大于子序列最后一个值时,直接放在子序列最后一位
print(ls)

#比较操作耗时较大,可以用二分法提高效率,适合小规模数据,时间复杂度过大
#稳定排序(相同内容的元素不会发生位置的交换):冒泡排序、插入排序、归并排序和基数排序
#不稳定排序:选择排序、快速排序、希尔排序、堆排序。

选择排序

l = [36,45,12,31,54,47,25,15,55,79,53,74]  # 原序列
def selectionSort(arr):
    for i in range(len(arr) - 1):
        # 记录最小数的索引
        minIndex = i
        for j in range(i + 1, len(arr)):
            if arr[j] < arr[minIndex]:
                minIndex = j
        # i 不是最小数时,将 i 和最小数进行交换
        if i != minIndex:
            arr[i], arr[minIndex] = arr[minIndex], arr[i]
    return arr
print(selectionSort(l)) 

模块

	模块就是一个包含了python定义和声明的文件
	import加载的就是模块
	from 包名 import  模块名 as 重命名
	或者from 模块名 import  函数名	as 重命名
	可以在一行一次性导入多个模块,但不建议
#demo.py (function包下的demo文件)
print('这是demo模块')

def foo():
    print('这是demo模块的foo函数')
#	test.py
from function import demo as d#导入function包下的demo并重命名
def foo():
    print('这是test的foo函数')

d.foo()

if __name__ == '__main__':
    foo()
#这是demo模块
#这是demo模块的foo函数
#这是test的foo函数

'''
执行流程:测试文件从上至下一次执行,先加载demo,执行demo代码,执行demo输出代码,定义函数
回到测试文件向下执行,定义自己的foo函数,执行模块的foo函数,执行if语句,调用自己的foo函数,完成输出
'''

常用的模块

re模块

#re模块是一个用于使用正则表达式的模块
#正则表达式————匹配字符串的规则
#在线正则匹配网址http://tool.chinaz.com/regex
'''
正则表示式:
匹配内容
. 	匹配除换行符以外的任意字符
\w	匹配字母或数字或下划线
\s	匹配任意的空白符
\d	匹配数字
\n	匹配一个换行符
\t	匹配一个制表符
\b	匹配一个单词的结尾
^	匹配字符串的开始
$	匹配字符串的结尾
\W	匹配非字母或数字或下划线
\D	匹配非数字
\S	匹配非空白符
a|b	匹配字符a或字符b,优先匹配a
()	匹配括号内的表达式,也表示一个组
[...]	匹配字符组中的字符
[^...]	匹配除了字符组中字符的所有字符

量词
用法说明
*	重复零次或更多次
+	重复一次或更多次
?	重复零次或一次
{n}	重复n次
{n,}	重复n次或更多次
{n,m}	重复n到m次

示例:

s = 'gb2312.458hDFGj56h4j85'

匹配字符串中数字
正则:\d  

仅匹配两个字符,字母+数字
正则:[A-Za-z][\d]  
[A-Za-z] 匹配所有英文字母,单个字符
[\d]	匹配所有数据,单个字符

匹配小数
正则:\d+\.\d+

匹配所有数字
正则:(\d+\.\d+|\d+) 以组的形式优先匹配小数

匹配所有非大写字母
正则:[^A-Z]


()与 []的区别:
s = '1235'
正则:(\d+) 匹配一条结果1235
正则:[\d+]	匹配四条结果		1	2	3	5

贪婪匹配:
例:s = '123g2544g56454g464544h4587h'
匹配所有的三位数或四位数
正则:[\d]{3,4}   能匹配4位数就不会输出3位数的匹配结果,优先匹配4位数

非贪婪匹配:[\d]{3,4}? 能匹配3位数就不会输出4位数的匹配结果,优先匹配3位数





re模块常用方法:
findall(正则表达式,str,flags)	返回匹配的所有结果组成的列表
search(正则表达式,str,flags)	找到匹配的第一个结果就返回一个Match对象,使用group()取值,仅含有一条结果
match(正则表达式,str,flags)	匹配str的开头,匹配不是返回None,否则返回一个Match对象,使用group()取值
split(正则表达式, str, maxsplit, flags)	按照正则截取,返回一个列表
sub(正则表达式, 替换字符,str,替换次数, flags)	将str中匹配字符替换为新字符,可指定替换次数
subn(正则表达式, 替换字符,str,替换次数, flags)	将替换后的字符与替换次数放入元组中返回
compile(正则表达式,flags)	编译正则表达式,生成一个正则表达式对象,供函数使用
finditer(正则表达式, string, flags=0)	在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回,节省内存

flags的值
re.I	使匹配对大小写不敏感
re.L	做本地化识别(locale-aware)匹配
re.M	多行匹配,影响 ^ 和 $
re.S	使 . 匹配包括换行在内的所有字符
re.U	根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X	该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。
'''
import re
s = 'gb2312 utf-8 unicode buyts'
ret = re.findall('(\d+)', s)
print(ret)	#['2312', '8']

ret = re.search(r'(\d+)', s)
print(ret)#<re.Match object; span=(2, 6), match='2312'> 	返回一个Match对象
print(ret.group())#2312		使用group()取值
#如果未找到结果,返回None,ret.group()会报错
if ret :
	ret.group()#多次调用group(),输出的值一致的

ret = re.match(r'(\d+)', s)#匹配s是否以数字开头
if ret:
    print(ret)
    print(ret.group())

#split的优先级
ret = re.split(r'(\d+)', s)#以分组截取,保留截取字符
if ret:
    print(ret)#['gb', '2312', ' utf-', '8', ' unicode buyts']

ret = re.split(r'\d+', s)#以非分组截取,不保留截取字符
if ret:
    print(ret)  #['gb', ' utf-', ' unicode buyts']
    

ret = re.split(r'utf-8', s)#以具体字符截取,不会保留截取字符
if ret:
    print(ret)#['gb2312 ', ' unicode buyts']


ret = re.sub(r'utf-8','haha', s,1)
if ret:
    print(ret)#gb2312 haha unicode buyts

ret = re.subn(r'utf-8','haha', s,1)
if ret:
    print(ret)#('gb2312 haha unicode buyts', 1)


ret = re.compile(r'\d')
r = ret.subn('haha', s,1)
if r:
    print(r)#('gbhaha312 utf-8 unicode buyts', 1)


ret = re.finditer(r'\d', s)#返回一个迭代器
for i in ret:   #i是Match对象
    print(i.group(),end = ' ')#2 3 1 2 8 

#分组优先
ret = re.findall('(gb2312|gbk) utf-8 unicode buyts', s)
if ret:
    print(ret)  #['gb2312']
#优先匹配分组中的数据,所以输出是['gb2312'],不是['gb2312 utf-8 unicode buyts']

#取消分组优先,在分组中加 ?:
ret = re.findall('(?:gb2312|gbk) utf-8 unicode buyts', s)
if ret:
    print(ret)  #['gb2312 utf-8 unicode buyts']
 
#?的作用 :1.表示量词0或1次   2.在量词后表示非贪婪匹配(惰性匹配) 3.在分组中表示取消优先级

#分组取值
import re
line = "Cats are smarter than dogs"
 
matchObj = re.match( r'(.*) are (.*?) .*', line)
 
if matchObj:
    print ("matchObj.group() : ", matchObj.group())#matchObj.group() :  Cats Cats are smarter than dogs
    print ("matchObj.group(1) : ", matchObj.group(1))#matchObj.group(1) :  Cats Cats
    print ("matchObj.group(2) : ", matchObj.group(2))#matchObj.group(2) :  smarter
else:
    print ("No match!!")

#分组取值
matchObj = re.match( r'(?P<animal1>.*) are (?P<animal2>.*?) .*', line)
 
if matchObj:
    print ("matchObj.group() : ", matchObj.group())#matchObj.group() :  Cats are smarter than dogs
    print ("matchObj.group(animal1) : ", matchObj.group('animal1'))#matchObj.group(animal1) :  Cats
    print ("matchObj.group(animal2) : ", matchObj.group('animal2'))#matchObj.group(animal2) :  smarter
else:
    print ("No match!!")
#在分组使用(?P<name>xxxx)给分组重命名	使用ret.group('name')来取分组的结果


#分组序号引用 (\w+)的分组序号为1,分组的下标从1开始,</\1>引用第一个分组
import re
ret = re.search(r'<(\w+)>\w+</\1>','<h1>测试字体样式</h1>')
if ret :
    print(ret.group())#<h1>测试字体样式</h1>

#分组取值实际应用的部分代码
def parsePage(s):
    
    com=re.compile('<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?<span class="title">(?P<title>.*?)</span>'
                   '.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)评价</span>',re.S)

    ret=com.finditer(s)
    for i in ret:
        yield {
            "id":i.group("id"),
            "title":i.group("title"),
            "rating_num":i.group("rating_num"),
            "comment_num":i.group("comment_num"),
        }


time模块


'''
time是时间模块
python中表示时间的三种的形式
    1.时间戳(给计算机看的,从1970年1月1日00:00:00至今为止的时间偏移量)
        time.time()回当前时间的时间戳
    2.格式化的时间字符串(给人看的)
                    格式化字符:
                    %Y-年  %m-月  %d-日   %H-小时 %M-分钟  %S-秒  %a本地简化星期    %A-本地完整星期 
                    %b-简化月份名称  %D-完整月份  %j-年内的天数(001-366) %x-本地日期(年/月/日) %X-本地时间(时:分:秒)
                    %Z-本地时区    %%-输出%本身
    3.结构化时间(时间元组),有9个元素
            索引(Index)    属性(Attribute)    值(Values)
        0        tm_year(年)             比如2011
        1        tm_mon(月)                1 - 12
        2        tm_mday(日)             1 - 31
        3        tm_hour(时)              0 - 23
        4        tm_min(分)                0 - 59
        5        tm_sec(秒)                0 - 59
        6        tm_wday(weekday)    0 - 6(0表示周一)
        7        tm_yday(一年中的第几天)    1 - 366
        8        tm_isdst(是否是夏令时)    默认为0
'''
import time
t1 = time.time()#回当前时间的时间戳,1970年后经过的浮点秒数,是一个float类型的浮点数
t2 = time.strftime('%Y-%m-%d %H:%M:%S ')#返回自定义格式的时间字符串
t3 = time.localtime()#结构化时间

print(type(t3))#<class 'time.struct_time'>
print(t1)#1578726758.9102
print(t2)#2020-01-11 15:13:13
print(t3)#time.struct_time(tm_year=2020, tm_mon=1, tm_mday=11, tm_hour=15, tm_min=13, tm_sec=13, tm_wday=5, tm_yday=11, tm_isdst=0)

'''不同时间形式间的转换
字符串时间<————>结构化时间<————>时间戳
	
'''
#字符串时间转为结构化时间
struct_t = time.strptime('2012-12.11','%Y-%m.%d')#传入一个字符串时间和它的时间格式(不要有多余空格,会报错),返回一个结构化时间
print(struct_t)

#结构化时间转为字符串时间
str_t = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())#传入自定义的输出格式和结构化时间作为参数,返回一个字符串时间
print(str_t)

#结构化时间转为时间戳
stamp_t = time.mktime(time.localtime())#常用与字符串转时间戳的过渡方法
print(stamp_t)

#时间戳转为结构化时间
struct_t = time.localtime(time.time())#东八时区,tm_hour = x + 8
struct_t = time.gmtime(time.time())#非东八时区,tm_hour = x
print(struct_t)

#返回一个可读的形式为"星期 月份 日期 时:分:秒 年"的24个字符的字符串
str_t = time.asctime(time.localtime(time.time()))
print(str_t)#Sat Jan 11 15:45:38 2020

#返回一个可读的形式为"星期 月份 日期 时:分:秒 年"的24个字符的字符串
str_t = time.ctime()#无参数返回当前时间的字符串,或者添加一个时间戳作为参数,返回对应时间的字符串时间
print(str_t)#Sat Jan 11 15:45:38 2020

time.perf_counter()  # 返回系统运行时间
'''
菜鸟教程时间模块 https://www.runoob.com/python/python-date-time.html
计算代码运行时间
import time

scale = 50 

print("执行开始".center(scale//2,"-"))  # .center() 控制输出的样式,宽度为 25//2,即 22,汉字居中,两侧填充 -

start = time.perf_counter() # 调用一次 perf_counter(),从计算机系统里随机选一个时间点A,计算其距离当前时间点B1有多少秒。当第二次调用该函数时,默认从第一次调用的时间点A算起,距离当前时间点B2有多少秒。两个函数取差,即实现从时间点B1到B2的计时功能。
for i in range(scale+1):   
    a = '*' * i             # i 个长度的 * 符号
    b = '.' * (scale-i)  # scale-i) 个长度的 . 符号。符号 * 和 . 总长度为50 
    c = (i/scale)*100  # 显示当前进度,百分之多少
    dur = time.perf_counter() - start    # 计时,计算进度条走到某一百分比的用时
    print("\r{:^3.0f}%[{}->{}]{:.2f}s".format(c,a,b,dur),end='')  # \r用来在每次输出完成后,将光标移至行首,这样保证进度条始终在同一行输出,即在一行不断刷新的效果;{:^3.0f},输出格式为居中,占3位,小数点后0位,浮点型数,对应输出的数为c;{},对应输出的数为a;{},对应输出的数为b;{:.2f},输出有两位小数的浮点数,对应输出的数为dur;end='',用来保证不换行,不加这句默认换行。
    time.sleep(0.1)     # 在输出下一个百分之几的进度前,停止0.1秒
print("\n"+"执行结果".center(scale//2,'-'))
'''
time.process_time()  # 返回进程运行时间


import  calendar	#日历模块
cal = calendar.month(2020,1,w=2,l=1)	#输出年份 + 月份 参数,返回对应日历显示
#返回一个多行字符串格式的year年month月日历,两行标题,一周一行。每日宽度间隔为w字符。每行的长度为7* w+6。l是每星期的行数
print(cal)
'''
 January 2020
Mo Tu We Th Fr Sa Su
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
'''
#打印某一年的日历
cal = calendar.calendar(2020,w=2,l=1,c=6)
#返回一个多行字符串格式的year年年历,3个月一行,间隔距离为c。 每日宽度间隔为w字符。每行长度为21* W+18+2* C。l是每星期行数
print(cal)
'''
2020

      January                   February                   March
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
       1  2  3  4  5                      1  2                         1
 6  7  8  9 10 11 12       3  4  5  6  7  8  9       2  3  4  5  6  7  8
13 14 15 16 17 18 19      10 11 12 13 14 15 16       9 10 11 12 13 14 15
20 21 22 23 24 25 26      17 18 19 20 21 22 23      16 17 18 19 20 21 22
27 28 29 30 31            24 25 26 27 28 29         23 24 25 26 27 28 29
                                                    30 31

       April                      May                       June
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
       1  2  3  4  5                   1  2  3       1  2  3  4  5  6  7
 6  7  8  9 10 11 12       4  5  6  7  8  9 10       8  9 10 11 12 13 14
13 14 15 16 17 18 19      11 12 13 14 15 16 17      15 16 17 18 19 20 21
20 21 22 23 24 25 26      18 19 20 21 22 23 24      22 23 24 25 26 27 28
27 28 29 30               25 26 27 28 29 30 31      29 30

        July                     August                  September
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
       1  2  3  4  5                      1  2          1  2  3  4  5  6
 6  7  8  9 10 11 12       3  4  5  6  7  8  9       7  8  9 10 11 12 13
13 14 15 16 17 18 19      10 11 12 13 14 15 16      14 15 16 17 18 19 20
20 21 22 23 24 25 26      17 18 19 20 21 22 23      21 22 23 24 25 26 27
27 28 29 30 31            24 25 26 27 28 29 30      28 29 30
                          31

      October                   November                  December
Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su      Mo Tu We Th Fr Sa Su
          1  2  3  4                         1          1  2  3  4  5  6
 5  6  7  8  9 10 11       2  3  4  5  6  7  8       7  8  9 10 11 12 13
12 13 14 15 16 17 18       9 10 11 12 13 14 15      14 15 16 17 18 19 20
19 20 21 22 23 24 25      16 17 18 19 20 21 22      21 22 23 24 25 26 27
26 27 28 29 30 31         23 24 25 26 27 28 29      28 29 30 31
                          30
'''
#判断是否为闰年
cal = calendar.isleap(2020)
print(cal)#True
'''
源码def isleap(year):
    Return True for leap years, False for non-leap years.
    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
'''
cal = calendar.monthrange(2020,1)
print(cal)#(2, 31)
#返回两个整数。第一个是该月的星期几,第二个是该月有几天。星期几是从0(星期一)到 6(星期日)

#其他时间模块 datetime等

random模块

'''
random模块用于生成随机数
'''
import random
ran = random.random()   #生成一个0到1的随机浮点数(float),0 <= n < 1.0
print(ran)  #0.8096922858114752

ran = random.uniform(1,10)   #生成一个指定范围内的随机符点数(float),a <= n <= b
print(ran)  #3.3136303476718343

ran = random.randint(1,10)   #生成一个指定范围内的整数(int),a <= n <= b
print(ran)  #10

ran = random.randrange(2,10,2)   #生成2到10间的随机偶数(int),a <= n < b
print(ran)  #8

ran = random.sample([1,2,3,4,5],3)   #从序列中随机取出n个元素组成的片段,不改变原序列
print(ran)  #[1, 5, 3]

ran = random.choice([1,2,3,4,5])   #从一个序列中随机返回一个元素
print(ran)  #4

l = [1,2,3,4,5]
ran = random.shuffle(l)   #接受一个序列,元素顺序打乱后返回,改变原有列表
print(l)  #[4, 3, 2, 5, 1]

random模块应用:

'''
Python - 100天从新手到大师    https://github.com/jackfrued/Python-100-Days
双色球选号  : 6个红色球 + 1个蓝色球 
        红色球(1-33) 蓝色球(1-16)
要求输入n注,返回n注球号
输出格式 : 01 31 25 16 12 | 03
'''
from random import randrange, randint, sample
def display(balls):
    """
    输出列表中的双色球号码
    """
    for index, ball in enumerate(balls):
        if index == len(balls) - 1:
            print('|', end=' ')
        print('%02d' % ball, end=' ')
    print()

def random_select():
    """
    随机选择一组号码
    """
    red_balls = [x for x in range(1, 34)]
    selected_balls = []
    selected_balls = sample(red_balls, 6)
    selected_balls.sort()
    selected_balls.append(randint(1, 16))
    return selected_balls
def main():
    n = int(input('机选几注: '))
    for _ in range(n):
        display(random_select())


if __name__ == '__main__':
    main()


#生成指定长度的验证码
import random
def generate_code(code_len=4):
    """
    生成指定长度的验证码

    :param code_len: 验证码的长度(默认4个字符)

    :return: 由大小写英文字母和数字构成的随机验证码
    """
    all_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    last_pos = len(all_chars) - 1
    code = ''
    for _ in range(code_len):
        index = random.randint(0, last_pos)
        code += all_chars[index]
    return code

os模块

import os
n = os.name	#输出正在使用的平台。window 用'nt'表示,Linux/Unix是'posix'。
print(n)#nt

n = os.getcwd()	#获取当前Python脚本工作的目录路径

os.chdir(path) #改变当前的工作路径

n = os.curdir	#返回当前目录
print(n)#.

n = os.pardir	#返回上一级目录
print(n)#..

os.makedirs('folder1/folder1_1')	#在当前路径下创建多级文件夹

os.removedirs(r'folder1/folder1_1') #删除路径最低层的空目录,之后上一级目录若也为空继续删除,查看上上层目录,直至遇到非空目录

os.mkdir('folder')	#创建单级目录

os.rmdir('folder') 	#删除单级空目录,非空会报错

n = os.listdir(os.getcwd())	#以列表元素形式返回指定路径下的所有文件可文件夹包括隐藏文件,不包括子文件夹,子文件
print(n)

os.remove(r'path\file.txt')	#删除指定路径下的指定文件,如果是一个文件夹会报错

os.rename('oldname','newname')	#重命名文件/目录

n = os.stat(os.getcwd())    #在给定的路径上执行一个系统 stat 的调用,返回当前路径的一些详细信息
print(n)

n = os.sep  #返回当前操作系统下的路径分隔符
print(n)    #window下为\ 

n = os.linesep  #返回当前操作系统行终止符

n = os.pathsep  #返回当前操作系统路径分隔符号
print(n)   #window下为;

os.system('dir')  #执行系统命令,直接在控制台输出显示,有中文乱码

n = os.popen('dir').read()  #执行系统命令,直接在控制台输出显示,无中文乱码
print(n)  

n = os.environ  #获取系统环境变量,以类似字典的形式返回
print(type(n))   #<class 'os._Environ'>
print(n)   #window下为;environ({xx:yyy})



#os.path模块主要用于文件的属性获取
os.path.abspath(r'path')  #返回路径的绝对路径,path中无盘符,即os.getcwd() + 'path',有盘符,直接输出path

n = os.path.split(r'folder1\folder2\h.txt')  #以最后一个路径分隔符\做分割,返回一个二元组
print(n)   #('folder1\\folder2', 'h.txt')

n = os.path.dirname(r'folder1\folder2\h.doc')  #返回os.path.split(r'folder1\folder2\h.txt')二元组的第一个元素
print(n)   #folder1\folder2

n = os.path.basename(r'folder1\folder2\h.doc')  #返回os.path.split(r'folder1\folder2\h.txt')二元组的第二个元素
print(n)   #h.txt

n = os.path.exists(r'folder1\folder2\h.doc')  #判断当前目录是否存在
print(n)   #False

n = os.path.isabs(r'folder1\folder2\h.doc')  #判断当前路径是否为绝对路径
print(n)   #False

n = os.path.isfile(r'folder1\folder2\h.doc')  #判断当前路径是否为一个存在的文件
print(n)   #False

n = os.path.isdir(r'folder1\folder2\h.doc')  #判断当前路径是否为一个存在的目录
#print(f)   #window下为;
print(n)   #False

n = os.path.join(r'c:\test',r'file.txt')  #拼接多个字符路径
print(n)   #c:\test\file.txt


n = os.path.getatime(os.getcwd())  #返回目录最后的访问时间戳
s = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(n))	#将时间戳转为字符串时间
print(s)

n = os.path.getsize(r'file')  #返回当前文件的占用字节数,对于文件夹不准(最大为4096),可以用循环或者递归查询所有文件大小的总和
print(n) 

os.walk(top, [,topdown][,onerror][,followlinks])

os模块应用

删除指定目录下所有文件和文件夹

import os
  
def delfiles(del_path):
    for i in os.listdir(del_path):	#遍历当前目录下的文件与文件夹
        file_path = os.path.join(del_path,i)	#拼接文件或文件夹的绝对路径
        if os.path.isfile(file_path):	#如果拼接后的路径是一个存在的文件
            os.remove(file_path)	#删除这个存在的文件
        else:	#如果是一个存在的文件夹
        	if os.listdir(file_path):	#且文件夹中有数据
            	delfiles(file_path)		#再次调用自身来删除其中的文件
            os.removedirs(file_path)	#如果文件夹中没有数据,直接删除,不再调用自身
    
def main():
    del_path =r'' + input('path...')	#输入指定文件路径,并取消 \ 转义
    delfiles(del_path)	#调用删除方法
  
if __name__ == '__main__':
    main()

sys模块

'''
sys模块 与python解释器交互
'''
import sys
print(sys.platform) #win32  返回操作系统的品台名称

print(sys.version) # 返回python解释器的版本详细信息 

sys.exit(0) #退出程序 参数0——正常退出  1——异常退出

print(sys.path) #返回当前模块的搜索路径,即path环境变量值,以列表形式
sys.path.clear()    #清空搜索路径

print(sys.argv) #以列表形式接受外部传入的参数,第一个参数是当前文件本身的路径

print(sys.modules) #记录了程序运行期间载入的所有模块,本身是一个字典

print(sys.getdefaultencoding()) #获取当前python的编码


序列化模块

'''
序列化:就是把不可传输的对象转换为可存储或可传输对象的过程,
简单理解就是将其他类型(dict,set,tuple等)转为字符串
反序列化:反之,将字符串还原为原本的其他的类型
一般用于文件或网络传输
常用的序列化模块:
    1.json模块 :通用的序列化模块,有很多编程语言也是使用json来序列化,但是json转化数据类型范围较小
                    序列化方法:dumps()    dump()
                    反序列化:loads()    load()
    2.pickle模块:所有python中的数据类型都可以转为字符串,python独有的,其他语言无法识别,且太依赖环境(序列化与反序列化的环境必须一致)
    3.shelve模块:序列化句柄,直接使用句柄操作,较pickle模块方便
'''
import json
dic = {'key':'value'}
print(type(dic))	#<class 'dict'>
d_json = json.dumps(dic)	#序列化
print(type(d_json))	#<class 'str'>
d_str = json.loads(d_json)	#反序列化
print(type(d_str))	#<class 'dict'>
#数字,字符串,列表,字典,元组都可以用json序列化(不包括集合,会报错)
#但是元组序列化时,内部先转为列表在序列化,所以元组反序列化得到的是一个列表

#对文件进行序列化dump()和load()
import json
dic = {'键':'值'}
f = open('file', 'w',encoding = 'utf-8')
json.dump(dic, f,ensure_ascii=False)
#写入的字典类型中有中文,在file文件会是unicode的二进制显示,添加ensure_ascii=False正常显示中文
f.close()
f1 = open('file',encoding = 'utf-8')
res = json.load(f1)
print(type(res),res)
f1.close()
#dump可以多次运行写入数据,但是load不能多次获取(会报错),load是一次性获取

#可以用dumps和loads实现分段读写
import json
dic = [{'键1':'值1'},{'键2':'值2'},{'键3':'值3'}]
f = open('file', 'w',encoding = 'utf-8')
for i in dic:
    r = json.dumps(i ,ensure_ascii=False)
    r = r + '\n'	#一个字典元素单独放一行
    f.write(r)
f.close()

f1 = open('file',encoding = 'utf-8')
l = []
for j in f1:	#读取一行文件内容
    res = json.loads(j.strip())	#一行中含有多个字典元素转换时会报错
    l.append(res)
print(l)
f1.close()

'''
    pickle模块:所有python中的数据类型都可以转为字符串,python独有的,其他语言无法识别,且太依赖环境(序列化与反序列化的环境必须一致)
        dumps() 将其他不可传输对象转为bytes对象 
        loads 将bytes对象转为 其他对象
        dump()和load()只能用于'rb'和'wb'形式的文件操作(bytes类型)
'''
import pickle
dic = ('k','v')
st = pickle.dumps(dic)
print(type(st)) #<class 'bytes'>
print(st)   #b'\x80\x03X\x01\x00\x00\x00kq\x00X\x01\x00\x00\x00vq\x01\x86q\x02.'

dic2 = pickle.loads(st)
print(type(dic2))   #<class 'tuple'>#元组类型反序列化结果类型还是元组
print(dic2) #('k', 'v')

#pickle模块的文件操作
import time
str_time = time.localtime(time.time())
with open('file','wb') as f:
    st = pickle.dump(str_time, f,0)
    
    
with open('file','rb') as f1:
    st_ti = pickle.load(f1)
    print(st_ti)

'''
    shelve模块:只有open函数,获取一个shelve对象,用key访问,用法与字典类似
    key必须为字符串,而值可以是python所支持的数据类型
    open(filename, flag, protocol, writeback)
    flag : c/默认,不存在就创建新文件,可读写      r/只读    w/读写    n/每次调用创建新文件,可读写
    protocol:是序列化模式,默认值为None
'''
import shelve
s = shelve.open('file')	#先删除同名file文件,否则运行报错
s['name'] = '张三'    #增
s['age'] = '23'
s['sex'] = '男'
s['job'] = 'python'

del s['job'] #删

s['sex'] = '女'  #改

for i in s.items():
    print(i[0] , i[1])  #查	取所有值
print(s['name'])#取单个值,key不存在会报错
#这个模块运行后会存在同名的file.bak / file.dat /file.dir三个文件,缺一不可

#以上三个模块中,对于中文输入输出没有乱码,但是pickle和shelve模块写入文件中的数据显示为乱码或unicode码
#只有json写入的文件中还是中文(人能看懂)

模块的导入详解

#demo.py
print('这是demo模块')

def foo():
    print('这是demo模块的foo函数')
#test.py
from function import demo
print('test')
def foo():
    print('test的foo函数')
demo.foo()    
foo()
#这是demo模块
#test
#这是demo模块的foo函数
#test的foo函数

'''
模块导入:先找到这个模块,创建这个模块的命名空间,把文件名放入命名空间
所有模块只会导入一次,导入时,先去sys.modules里查看是否已经导入;已经导入,不再重复导入
未导入,根据sys.path去找模块,找到就导入,找不到就报错;找到就创建命名空间,执行文件,将名字放入

给模块起别名 from function import demo as d

模块一般的导入顺序:先导入内置模块,再导入扩展模块,再次就是自定义模块
import sys,time,os可以导入多个模块,但可读性差,不推荐
from collections import * 导入所有模块函数 ,不推荐,占用运行效率
'''




发布了16 篇原创文章 · 获赞 0 · 访问量 75

猜你喜欢

转载自blog.csdn.net/qq_31241107/article/details/103892620
今日推荐