Py基础标准库及应用(os、sys、fileinput、time、random、shelve、json、re)

# -*- coding: utf-8 -*-

'''
Py基础标准库及应用.py
(os、 sys、 fileinput、 time、 random、 shelve、 json、 re)


标准库    标准安装包含一组称为 标准库 的模块。
模块      模块就是.py文件,模块用来定义变量、函数、类等。
包       包就是目录,包是模块的打包处理,包包括多个模块文件,其中必须包含__init__.py文件,因为这是类似与类定义中的初始化构造函数一样,是这个包的包内容、代码。


深入:
1、解码、编码
http://c.biancheng.net/view/4305.html

2、exce语句的作用域参数(exce/eval语句 结合 re.sub 实现替换模板文件作用)
在函数内运行exce语句需要注意 局部变量 的局限问题,需要引入一个全局变量(字典类型、空字典{})



注意:
1、包既然有初始化__init__.py文件,则文件内的变量、函数等,都可以通过 包名称.变量 或 包名称.函数 来进行调用。通常情况下默认为空。


使用:
0、入门教程
http://c.biancheng.net/python/
1、标准库官方文档
https://docs.python.org/zh-cn/3/library/
2、打包模块等参考网址
https://packaging.python.org/
3、python解释器开关 -m
'''


# =============================================================================
# #模块探索
# #使用方法help()、dir()
# #使用属性__doc__、__all__、__file__、__name__等
# =============================================================================

import copy

#help()函数查看帮助信息
#help() 比 __doc__ 提供的内容要多一些,如特征标(即接受的参数)
help(copy)                                          #help()查看包的帮助信息,
help(copy.copy)                                     #help()查看函数的帮助信息
copy.copy.__doc__                                   #.__doc__查看函数的文档

copy.__all__                                        #模块的__all__变量 定义了解释器从这个模块导入所有的名称都有哪些,如果不定义__all__变量,导入所有不以下划线开头的全局名称
copy.__file__                                       #模块的__file__变量 定义模块源文件的存储目录地址

dir(copy)                                           #列出对象的所有属性,对于模块则列出模块所有的 变量、函数、类等
[c for c in dir(copy) if not  c.startswith('_')]    #列表推导式过滤所有 _下滑线开头的私有函数










# =============================================================================
# #os模块
# #os模块访问多个操作系统服务
# #os及其子模块os.path包含多个查看、创建和删除目录及文件的函数,以及一些操作路径的函数。如os.path.split 和 os.path.join
# =============================================================================

####################
#探索os模块
import os

help(os)                        #获取帮助信息
os.__doc__                      #获取文档信息
os.__file__                     #获取源码文件路径
os.__all__                      #获取导入所有名称列表
os.__name__
dir(os)                         #打印所有 属性、方法、类。


help(os.environ)                #包含环境变量的映射  如访问环境变量PATHONPATH,则使用 os.environ['PYTHONPATH]
help(os.system)                 #系统命令  在子shell中执行命令
help(os.sep)                    #路径中使用的分隔符





####################
#常用的变量、函数、类

#访问环境变量 PYTHONPATH
os.environ['PYTHONPATH']        #访问环境变量 PYTHONPATH

#运行命令行命令  直接输入CMD命令   
os.system('cmd')                #运行命令行命令  直接输入CMD命令          
os.system('shutdown -s -t 300') #自动关机 300秒后

#打开一个路径/程序
os.startfile('C:\\Users\\Administrator\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe')


print(os.name)                  # 显示导入依赖模块的操作系统的名称
os.getenv('PYTHONPATH')         # 获取PYTHONPATH环境变量的值
os.getlogin()                   # 返回当前系统的登录用户名
os.getpid()                     # 获取当前进程ID
os.getppid()                    # 获取当前进程的父进程ID
os.cpu_count()                  # 返回当前系统的CPU数量
os.sep                          # 返回路径分隔符
os.pathsep                      # 返回当前系统的路径分隔符
os.linesep                      # 返回当前系统的换行符
os.urandom(3)                   # 返回适合作为加密使用的、最多3个字节组成的bytes





####################
#与目录相关的函数

#获取当前目录
os.getcwd()                     #获取当前目录

#改变当前目录到指定目录
os.chdir('F:/SpyderXIANGMUWENJIANJIA/编程基础')                    #改变当前目录到指定目录

os.getcwd()                     #再次获取当前目录

#返回指定目录下的所有文件和子目录
os.listdir(os.getcwd())         #返回指定目录下的所有文件和子目录


#创建、重命名、删除等操作
#os.mkdir('os.mkdir测试创建目录',777)                               #当前目录下创建子目录  如果中间目录为空则报错
#os.rename('os.mkdir测试创建目录','o')                              #重命名当前目录下的子目录

#os.makedirs('os.mkdir测试创建目录1\\递归目录1\\递归目录2',777)      #递归创建/a/b/c连环目录,比mkdir强大
#os.renames('os.mkdir测试创建目录1\\递归目录1\\递归目录2','a\\b\\c') #递归重命名连环目录

#os.remove('b.txt')             # 删除文件 b.txt
#os.rmdir('o')                                                     #删除当前目录下的子目录  目录需要为空,否则报错。
#os.removedirs('a\\b\\c')                                          #递归删除连环目录  如果没有找到目录则报错




####################
#os.path模块
#os.path模块提供了操作目录的方法。

import os,time

print(os.path.abspath('abc.txt'))                                  #获取绝对路径
print(os.path.abspath('.'))                                        #获取当前路径的绝对路径
print(os.path.commonprefix(['/usr/lib','/usr/local/lib']))         #获取共同前缀
print(os.path.commonpath(['usr/lib','usr/local/lib']))             #获取共同路径
print(os.path.dirname('abc/xyz/README.txt'))                       #获取目录


print(os.path.exists('abc/xyz/README.txt'))                         #判断指定目录是否存在
print(time.ctime(os.path.getatime('Py文件库linecache.py')))         #获取最近一次访问时间
print(time.ctime(os.path.getmtime('Py文件库linecache.py')))         #获取最后一次修改时间
print(time.ctime(os.path.getctime('Py文件库linecache.py')))         #获取创建时间
print(os.path.getsize('Py文件库linecache.py'))                      #获取文件大小
print(os.path.isfile('Py文件库linecache.py'))                       #判断是否为文件  # True
print(os.path.isdir('Py文件库linecache.py'))                        #判断是否为目录  # False
print(os.path.samefile('Py文件库linecache.py', './Py文件库linecache.py'))    #判断是否为同一个文件  # True
















# =============================================================================
# #sys模块
# #sys模块访问与python解释器紧密相关的变量和函数
# =============================================================================

####################
#探索sys模块
import sys,pprint                #打印函数,能够妥善的打印输出

help(sys)                        #获取帮助信息
sys.__doc__                      #获取文档信息
dir(sys)                         #打印包内所有 变量、函数、类等



help(sys.path)                   #python的搜索路径的目录列表,是一个字符串列表,其中每个字符串都是一个目录名
help(sys.modules)                #将模块名映射到模块(仅限当前导入的模块)

help(sys.exit)                   #退出当前程序。可提供一个整数参数,支出程序是否成功
                                 #应用于 try/finally 异常捕获时子句依然会执行。
help(sys.argv)                   #获取命令行输入参数 sys.argv[]
                                 #包含传传递给python解释器的参数,包括脚本名,
                                 #可应用于命令行



####################
#常用变量、函数、类

##########
#模块搜索路径列表中的 sit-packages目录 就是专门用来安放模块的目录。
print(sys.path)                                      #输出python的搜索路径的目录列表
pprint.pprint(sys.path)                              #格式化打印函数

##########
#程序退出 sys.exit()
'''
sys.exit()会引发一个异常:SystemExit,如果这个异常没有被捕获,那么python解释器将会退出。
如果有捕获此异常的代码,那么这些代码还是会执行。捕获这个异常可以做一些额外的清理工作。
0为正常退出,其他数值(1-127)为不正常,可抛异常事件供捕获。也可添加异常提示信息。

os._exit()会直接将python程序终止,之后的所有代码都不会继续执行。
'''
help(sys.exit)
sys.exit.__doc__

#sys.exit('hahaha')                                  #退出程序,并抛出异常。

try:
  sys.exit()
except  SystemExit:                                  #捕获异常,做一些额外的清理工作。
  print('die')
finally:
  print('这里通过sys.exit()方法已程序退出,余下代码不再执行。')

#import os
#os._exit(0)



####################
#示例1
#sys.argv示例        获取命令行输入参数 sys.argv[]

#从命令行输入命令,   通过提供命令行输入的参数来执行源码内容
#命令行输入格式:     python py文件名 参数1 参数2
  
#sys.argv[]         是用来获取命令行输入的参数的(参数和参数之间空格区分),
#sys.argv[0]        参数表示代码本身文件路径,所以从参数1开始,表示获取的参数了
  
'''
参考网址:
https://blog.csdn.net/u013205877/article/details/78571453
'''

#testSys_命令行参数.py
#自建测试文件 testSys_命令行参数.py      输出命令行参数
import sys
print('执行程序,参数为{}'.format(sys.argv[1:]))


#testSys_反转命令行参数.py
#自建测试文件 testSys_命令行参数.py      输出反向排序的命令行参数

import sys 
args=sys.argv[1:]
args.reverse()
print('反转参数输出: ',' '.join(args))     



####################
#示例2
#sys.path应用示例        sys.path.append() 动态修改添加python模块加载路径

#scrapy框架爬虫出现No module named:  的问题
'''
python执行的时候,是根据最初设置的python路径,
而我们创建的scrapy的路径不在上面路径的情况下,导致scrapy找不到路径,所以把该路径添加到python执行路径即可;

添加搜索路径至python搜索包路径的目录列表里就好,如下,然后重启程序运行即可。
'''
import os,sys

ffpath = os.path.dirname(os.path.dirname(os.path.abspath(".")))    #获取目录名称os.path.dirname(),获取绝对路径os.path.abspath('.')
sys.path.append(ffpath)











# =============================================================================
# #fileinput模块
# #fileinput模块能够轻松的迭代一系列文本文件中的所有行
# #fileinput模块提供了input函数,可以把多个输入流合并在一起,然后进行一些循环操作等

# #可以在命令行运行脚本  命令如:python testNumberlines.py testNumberlines.py
# =============================================================================

####################
#探索fileinput模块

import fileinput

help(fileinput)
fileinput.__doc__
fileinput.__file__
fileinput.__all__
dir(fileinput)


help(fileinput.filename) 	    #返回正在读取的文件的文件名。
help(fileinput.fileno)  	    #返回当前文件的文件描述符(file descriptor),该文件描述符是一个整数。
help(fileinput.lineno)   	    #返回当前读取的行号。
help(fileinput.filelineno)      #返回当前读取的行在其文件中的行号。

help(fileinput.isfirstline) 	#返回当前读取的行在其文件中是否为第一行。
help(fileinput.isstdin)  	    #返回最后一行是否从 sys.stdin 读取。程序可以使用“-”代表从 sys.stdin 读取。

help(fileinput.nextfile)	    #关闭当前文件,开始读取下一个文件。
help(fileinput.close)	        #关闭 FileInput 对象。



####################
#常用属性、方法、类等
help(fileinput.input)
'''
#fileinput.input(files="filename1, filename2, ...", inplace=False, backup='', bufsize=0, mode='r', openhook=None)
#此函数会返回一个 FileInput 对象
#参数files:       多个文件的路径序列;
#参数inplace:     用于指定是否将标准输出的结果写回到文件,此参数默认值为 False;
#参数backup:      用于指定备份文件的扩展名;
#参数bufsize:     指定缓冲区的大小,默认为 0;
#参数mode:        打开文件的格式,默认为 r(只读格式);
#参数openhook:    控制文件的打开方式,例如编码格式等。
'''

#通过input函数创建了 FileInput 对象之后,即可通过 for 循环来遍历文件的每一行。
#在for循环里即可通过方法来进行相关操作
'''
#fileinput.filename()	    返回正在读取的文件的文件名。
#fileinput.fileno() 	    返回当前文件的文件描述符(file descriptor),该文件描述符是一个整数。
#fileinput.lineno() 	    返回当前读取的行号。
#fileinput.filelineno()	    返回当前读取的行在其文件中的行号。
#fileinput.isfirstline()	返回当前读取的行在其文件中是否为第一行。
#fileinput.isstdin()	    返回最后一行是否从 sys.stdin 读取。程序可以使用“-”代表从 sys.stdin 读取。
#fileinput.nextfile()	    关闭当前文件,开始读取下一个文件。
#fileinput.close()	        关闭 FileInput 对象。
'''



####################
#示例1

'''
不支持中文问题
通过参数打开模式 mode='rb' 即二进制模式打开,然后输出执行解码utf-8,输出中文成功
'''
import fileinput
for line in fileinput.input(files=('testFileinput_A.txt', 'testFileinput_B.txt'),mode='rb'):         # 一次读取多个文件
    print(fileinput.filename(), fileinput.filelineno(), line.decode('utf-8'))    # 输出文件名,当前行在当前文件中的行号,行内容。
fileinput.close()                                                # 关闭文件流


with fileinput.input(files=('testA.txt','testB.txt'),mode='rb') as f:
    for line in f:
        print(line.decode('utf-8'))



####################
#示例2         可改写格式,然后即可用于给文件进行格式添加
        
#自建脚本文件   testFileinput_格式添加.py    在程序右侧添加行号格式化

#然后在控制台运行这个脚本程序,并将其作为参数传入。
#命令如:python testFileinput_格式添加.py testFileinput_格式添加.py
'''
出现解码问题
通过参数打开模式 mode='rb' 即二进制模式打开,然后输出执行解码utf-8,输出中文成功
'''
import fileinput

for line in fileinput.input(mode='rb',inplace=False):         #inplace可选择是否本地修改
    line=line.rstrip()           #清洗右侧空白字符                         
    num=fileinput.lineno()       #输出当前文件的当前行号
    #print格式设置 冒号前为输出对象,冒号后面:整数部分代表宽度,符号<代表左对齐,d代表十进制格式
    print('{:<50} # {:2d}'.format(line.decode('utf-8'),num))    
fileinput.close()











# =============================================================================
# #time模块
# #time模块 获取当前时间、操作时间和日期;从字符串中读取日期、将日期格式化为字符串
# =============================================================================

####################
#探索time模块

import time

help(time)
time.__doc__
dir(time)


help(time.time)



####################
#常用属性、方法

##########
#获取当前时间的 秒数时间
time.time()                                         # 返回从1970年1970年1月1日0点整到现在过了多少秒。
time.sleep(1)                                       # 暂停指定秒


##########
#将当前时间 转换为 指定格式的时间字符串
time.strftime('%Y-%m-%d %H:%M:%S')                  # 将当前时间转换为指定格式的字符串

st = '2018年3月20日'
time.strptime(st,'%Y年%m月%d日')                     # 将指定时间字符串恢复成struct_time对象。


##########
#将当前时间 转换为 时间字符串
time.asctime()                                      # 将当前时间转换为时间字符串
time.ctime(300)                                     # 将以秒数为代表的时间转换为时间字符串# Thu Jan  1 08:00:30 1970
time.asctime((2018, 2, 4, 11, 8, 23, 0, 0 ,0))      # 将指定时间转换时间字符串,时间元组的后面3个元素没有设置# Mon Feb  4 11:08:23 2018

time.gmtime()                                       # 将当前时间转换为struct_time对象。
time.gmtime(300)                                    # 将以秒数为代表的时间转换为struct_time对象。
time.localtime(300)                                 # 将以秒数为代表的时间转换为代表当前时间的struct_time对象

time.mktime((2018, 2, 4, 11, 8, 23, 0, 0 ,0))       # 将元组格式的时间转换为秒数代表的时间# 1517713703.0


time.perf_counter()                                 # 返回性能计数器的值
time.process_time()                                 # 返回当前进程使用CPU的时间


time.timezone                                       # 返回本地时区的时间偏移,以秒为单位# 在国内东八区输出-28800












# =============================================================================
# #random模块
# #random模块包含生成伪随机数的函数,有助于编写模拟程序或生成随机输出的程序。
# 
# 些随机数看似随机,但实际上,它们是以一个可预测的系统作为基础。
# 果要求真正的随机,应考虑使用 os模块 中的 urandom,random模块中的SystemRandom类基于的功能与urandom类似,可提供接近于真是随机的数据。
# =============================================================================

####################
#探索random模块

import random

help(random)
random.__doc__
random.__all__
random.__file__
dir(random)

help(random.random)



####################
#常用属性、方法、类

random.random()                                  #生成范围为0.0≤x<1.0 的伪随机浮点数

random.uniform(2.5, 10.0)                        #生成范围为2.5≤x<10.0 的伪随机浮点数
random.uniform(1,5)                  

random.randrange(start=1,stop=10,step=2)         #生成从start=0 到end=9 step=2的伪随机整数
random.randrange(0, 101 , 2)                     #生成从0 到100 的随机偶数
random.randrange(9)

random.choice (['Python','Swift','Kotlin'])      #随机抽取一个元素

random.sample([10, 20 , 30 , 40 , 50], k=4)      #随机抽取4 个独立的元素

book_list = ['Python','Swift','Kotlin']
random.shuffle (book_list)                       #对列表元素进行随机排列
book_list

random.expovariate(1/5)                          #生成呈指数分布的伪随机浮点数



####################
#random示例1:
#随机选择两个时间点之内的时间

from random import *
from time import *

date1=(2016,1,1,0,0,0,-1,-1,-1)
time1=mktime(date1)                       #mktime()将元组时间 转换成 秒数时间

date2=(2019,8,20,0,0,0,-1,-1,-1)
time2=mktime(date2)                       #mktime()将元组时间 转换成 秒数时间

random_time=uniform(time1,time2)          #生成随机浮点数,在两个秒数时间内
print(asctime(localtime(random_time)))    #先localtime将秒数时间转换成对象时间,再asctime将对象时间转换字符串时间。



####################
#random示例2:
#掷骰子  询问用户要掷多少个骰子,每个骰子有多少面。  投骰子的机制使用randrange 和 for循环 来实现的。

from random import randrange

#num=int(input('要投的骰子数量为:'))
#sides=int(input('每个骰子有多少面:')
num=3
sides=6
sum=0
for i in range(num):
    sum+=randrange(sides)+1
print('您投下{}个骰子的总点数是{}'.format(num,sum))



####################
#random示例3:
#一副扑克牌
from pprint import pprint
from random import shuffle

values=list(range(1,11)) + 'Jack Queen King'.split()
suits='黑桃 红桃 梅花 方片'.split()
deck=['{}{}'.format(s,v) for v in values for s in suits] + ['小猫','大猫']
pprint(deck)

shuffle(deck)             #就地打乱序列,即就地洗牌。
pprint(deck)

while deck:
    '''实现输入一次即显示一张牌,直到整副牌发完'''
    input(deck.pop(0))    #pop() 方法会移除列表中指定索引处的元素,如果不指定,默认会移除列表中最后一个元素












# =============================================================================
# #shelve模块
# #shelve模块用于创建永久性映射,其内容存储在使用给定文件名的数据库中。
# #简单的存储方案
# =============================================================================
    
####################
#探索shelve模块

import shelve    

help(shelve)
shelve.__doc__
shelve.__all__
shelve.__file__
dir(shelve)

help(shelve.open)



####################
#常用属性、方法、类

help(shelve.open)

s=shelve.open('testShelve.dat',writeback=True)    #如果不指定writeback参数为True,则不能进行自动保存和关闭,除非进行 close关闭
s['x']=['a','b','c']
s['x'].append('e')
s.close()



####################
#shelve示例
#一个简单的数据库文件

import shelve

def store_person(db):
    '''
    让用户输入数据并存储到shelf对象中
    '''
    pid=input('Enter Unique ID number: ')
    person={}
    person['name']=input('Enter name: ')
    person['age']=input('Enter age: ')
    person['phone']=input('Enter phone number: ')
    db[pid]=person

def lookup_person(db):
    '''
    让用户输入ID和所需要的字段,并从shelf对象中获取相应的数据
    '''
    pid=input('Enter ID number: ')                    #用户输入ID
    field=input('What would you like to know?(name,age,phone): ')
    field=field.strip().lower()                       #清洗用户输入指令
    
    #.capitalize()首字母大写
    print(field.capitalize() + ':',db[pid][field])     #根据用户输入的ID和指令来查找 数据库对应内容 并输出

def print_help():
    print('The available commands are:')
    print('store: Stores information about a person')
    print('lookup: Looks up a person from ID number')
    print('quit: Save changes and exit')
    print('?: Prints this message')

def enter_command():
    cmd=input('Enter Command (? for help): ')          #提示用户输入指令
    cmd=cmd.strip().lower()                            #清洗 指令字符串 去空格、最小化
    return cmd                                         #返回清洗后的要用户指令

def main():
    database=shelve.open('teseDataBase.dat')
    try:
        while True:
            cmd=enter_command()
            if cmd=='store':
                store_person(database)
            elif cmd=='lookup':
                lookup_person(database)
            elif cmd=='?':
                print_help()
            elif cmd=='quit':
                return
    finally:
        database.close()



if __name__ =='__main__':
    main()











# =============================================================================
# #json模块
# #http://c.biancheng.net/view/2423.html
# =============================================================================
'''

使用:

dumps() 和 dump() 函数的功能、所支持的选项基本相同,
只是 dumps() 函数直接返回转换得到的 JSON 字符串,而 dump() 函数则将转换得到的 JSON 字符串输出到文件


Python 类型	         转换相对应的        JSON 类型

字典(dict)	                            对象(object)
列表(list)和元组(tuple)	            数组(array)
字符串(str)	                        字符串(string)
整型、浮点数,以及
整型、浮点型派生的枚举
(float,int-& float-derived Enums)	    数值型(number)
True	                                true
False	                                false
None                                	null
'''


####################
#探索json模块

import json

help(json)
json.__doc__
json.__file__
json.__all__
dir(json)


help(json.dumps)    #将python对象 转换成为 json字符串
help(json.dump)     #将python对象 转换成为 json字符串,并输出到文件中。

help(json.loads)    #将json字符串 恢复成为 python对象
help(json.load)     #从文件中读取json字符串 恢复成为 python对象



####################
#常用属性、方法、类

#####
#dumps 将python对象 转换成为 json相对应的 json字符串各种类型
s1 = json.dumps(['yeeku', {'favorite': ('coding', None, 'game', 25)}])   # 将Python对象转JSON字符串(元组会当成数组)
s1 = json.dumps("\"foo\bar")                                             # 简单的Python字符串转JSON
s1 = json.dumps('\\')                                                    # 简单的Python字符串转JSON
s1 = json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)                # Python的dict对象转JSON,并对key排序

#指定JSON分隔符:逗号和冒号之后没有空格(默认有空格)
s1 = json.dumps([1, 2, 3, {'x': 5, 'y': 7}], separators=(',', ':'))      # 将Python列表转JSON,  # 并指定JSON分隔符:逗号和冒号之后没有空格(默认有空格)

#参数sort_key=True即 按键名正向排序。参数indent=4即 指定josn字符串有缩进。
s1 = json.dumps({'Python': 5, 'Kotlin': 7}, sort_keys=True, indent=4)    # 指定indent为4,意味着转换的JSON字符串有缩进

print(s1)


#dump 将python对象转换成为 json字符串,并输出到文件中。
help(json.dump)     #将python对象转换成为 json字符串,并输出到文件中。
f = open('F:\\SpyderXIANGMUWENJIANJIA\\编程基础\\Py基础标准库及应用\\测试文件\\testJson_a.json', 'w')
json.dump(['Kotlin', {'Python': 'excellent'}], f)                        # 使用dump()函数将转换得到JSON字符串输出到文件
f.close


##########
#loads 将json字符串恢复成为 python对象
help(json.loads)
result1 = json.loads('["yeeku", {"favorite": ["coding", null, "game", 25]}]') # 将JSON字符串恢复成Python列表
print(result1)                                                                # ['yeeku', {'favorite': ['coding', None, 'game', 25]}]

result2 = json.loads('"\\"foo\\"bar"')                                        # 将JSON字符串恢复成Python字符串
print(result2)                                                                # "foo"bar


#load 从文件中读取json字符串恢复成为 python对象
help(json.load)
f = open('F:\\SpyderXIANGMUWENJIANJIA\\编程基础\\Py基础标准库及应用\\测试文件\\testJson_a.json')
result4 = json.load(f)                                                        # 从文件流恢复JSON列表
print(result4)                                                                # ['Kotlin', {'Python': 'excellent'}]
f.close()




##########
help(json.JSONEncoder)
dir(json.JSONEncoder)
s7 = json.JSONEncoder().encode({"names": ("孙悟空", "齐天大圣")})         # 使用JSONEncoder的encode方法将Python转JSON
print(s7)                                                                # {"names": ["\u5b59\u609f\u7a7a", "\u9f50\u5929\u5927\u5723"]}


# 定义一个自定义的转化函数
def as_complex(dct):
    if '__complex__' in dct:
        return complex(dct['real'], dct['imag'])
    return dct
# 使用自定义的恢复函数
# 自定义回复函数将real数据转成复数的实部,将imag转成复数的虚部
result3 = json.loads('{"__complex__": true, "real": 1, "imag": 2}',\
    object_hook=as_complex)
print(result3)                                                                # (1+2j)




# 定义JSONEncoder的子类
class ComplexEncoder(json.JSONEncoder):
    '''
    扩展了 JSONEncoder 类的子类,并重写了它的 default() 方法,
    在方法中判断如果要转换的目标类型是复数(complex),程序就会进行自定义转换,即将复数转换成 JSON 对象,且该对象包含 "_complex_":'true' 属性。
    '''
    def default(self, obj):
        # 如果要转换的对象是复数类型,程序负责处理
        if isinstance(obj, complex):
            return {"__complex__": 'true', 'real': obj.real, 'imag': obj.imag}
        # 对于其他类型,还使用JSONEncoder的默认处理
        return json.JSONEncoder.default(self, obj)
    
s1 = json.dumps(2 + 1j, cls=ComplexEncoder)
print(s1)                                                                     # '{"__complex__": "true", "real": 2.0, "imag": 1.0}'
s2 = ComplexEncoder().encode(2 + 1j)
print(s2)                                                                     # '{"__complex__": "true", "real": 2.0, "imag": 1.0}'











# =============================================================================
# #re模块
# #正则表达式  用于描述一种字符串匹配的模式,它可用于检查一个字符串是否含有某个子串,
# #也可用于从字符串中提取匹配的子串,或者对字符串中匹配的子串执行替换操作。
# =============================================================================

'''
深入:
1、     exce语句的作用域参数(exce/eval语句 结合 re.sub 实现替换模板文件作用)
        在函数内运行exce语句需要注意 局部变量 的局限问题,需要引入一个全局变量(字典类型、空字典{})



注意:
#1、    正则表达式整个 匹配子串 和 匹配组() 的概念,字符集[]的概念
#2、    ^脱字符在 字符集 开头的位置时候表示是 排除运算符;而在 字符串 开头的位置时候表示是匹配开头位置。
#3、    [a-z] [a-zA-Z0-9]都属于字符集;所以注意谨慎末尾使用 -连字符。
#4、    re模块中的两种类及对象    一个是 正则表达式对象  另一个是 匹配对象
#5、    re.sub替换方法中的 替换内容参数的字符串中的任何 \1形式 表示对应替换为匹配模式中的 group(1)的内容。
#5.1    r'(?P<lang>\w+)' 正则表达式用圆括号表达式创建了一个组,并使用“?P”选项为该组起名为 lang(所起的组名要放在尖括号内)。



使用:

通配符:         .句点符号为通配符,除 换行符 以外可匹配所有字符
原始字符串:     r'python\.org'  #前面加上r 即为表示原始字符串
字符集:         []更细致的控制方法可以用[]将一个子串括起。如 [pj]ython 和python、jython都匹配,注意的是字符集只匹配一个字符。
#注意[^\*]字符集里为匹配单个字符,所有需要贪婪模式+
#注意:[a-z] [a-zA-Z0-9]都属于字符集;所以注意谨慎末尾使用 -连字符
#注意:字符集里的特殊字符可以用\转义,也可以不转义

二选一模式:      python|pipy 
子模式:          p(ython|ipy)               #注意子模式用()表示
可选模式:        (http:)?(www.)?            #在子模式后面加上?问号 即将其变成可选模式,匹配0次/1次,即可以有,也可以没有。
重复模式:        ? 问号表示0次/1次;  * 星号表示0次/多次;  + 加号表示1次/多次;
                 {m,n}表示m-n次;{m}表示m次    
贪婪模式:        +    
非贪婪模式:      ?


开头匹配:        ^脱字符在字符串开头时,表示要匹配开头位置,如:'^h+'  匹配的是 h开头1次/多次
#注意:^脱字符在 字符集 开头的位置时候表示是 排除运算符;而在 字符串 开头的位置时候表示是匹配开头位置。
                  re.match()方法也是匹配开头
末尾匹配:         $美元符号在字符串末尾时,表示要匹配末尾位置。

忽略大小写:      re.IGNORECASE 即 re.I 忽略大小写
'''

import re

####################
#探索re模块

help(re)
re.__doc__
re.__version__
re.__file__
re.__all__
dir(re)


help(re.match)                            #开始位置匹配
help(re.fullmatch)                        #整个字符串能匹配 pattern,如果匹配则返回包含匹配信息的 _sre.SRE_Match 对象;否则返回 None。
help(re.compile)                          #预先编译正则表达式,使之成为模式对象
help(re.search)                           #扫描整个字符串,只返回第一个匹配的子串。
help(re.findall)                          #返回字符串中所有匹配的子串
help(re.finditer)                         #所有匹配的子串组成的迭代器

help(re.sub)                              #替换方法,将参数1的模式(或函数)匹配的子串替换成参数2的内容,作用于参数3.
help(re.split)                            #根据与模式匹配的子串来 分割 字符串 

help(re.escape)                           #转义字符串中的特殊字符

 


####################
#常用属性、函数、方法

##########
#re.match 在字符串 开头 匹配模式
help(re.match)
m1 = re.match('www', 'www.fkit.org')      # 开始位置可以匹配  
m2 = re.match('fkit', 'www.fkit.com')     # 开始位置匹配不到,返回None
print(m2)
print(m1.span())                          # span返回匹配到的位置
print(m1.group())                         # group返回匹配到的组



##########
#re.search 在字符串 中 查找模式,前、中、后都可以查找。
#re.compile 预先编译正则表达式,使之成为模式对象,可用来重复使用 和 不需要重复转换
help(re.search)
help(re.compile)
p = re.compile('abc')                     #预先编译正则表达式,使之成为模式对象,可用来重复使用 和 不需要重复转换
p.search("www.abc.com")                   #在字符串 中 查找模式 search()    #调用_sre.SRE_Pattern 对象的search()方法
#等同于
re.search('abc','www.abc.com')            #与上等同    匹配模式 在 字符串里

#re.search()函数可扫描整个字符串,从中间任意位置开始匹配,但是只返回第一个匹配的子串。
s1 = re.search('www', 'www.fkit.org')     # 开始位置 和 中间位置等 都可以匹配
s2 = re.search('fkit', 'www.fkit.com')    # 中间位置可以匹配,返回Match对象
s3 = re.search('com','www.fkit.com')
print(s3)
print(s3.span())
print(s3.group())

if re.search('(abc|def)','www.def.com'):  #如果匹配到,则输出字符串xxx
    print('Found it!')



##########
#re.findall() 和 re.finditer() 则返回字符串中所有匹配的子串。
help(re.findall)
#返回所有匹配的子串组成的列表,参数re.I忽略大小写
print(re.findall('fkit', 'FkIt is very good , Fkit.org is my favorite' , re.I))

help(re.finditer)
#返回所有匹配的子串组成的迭代器,参数re.I忽略大小写
it = re.finditer('fkit', 'FkIt is very good , Fkit.org is my favorite' , re.I) # 返回所有匹配pattern的子串组成的迭代器, 忽略大小写
for e in it:
    print(str(e.start()) + "-->" + e.group())
#    print(e)
#    print(e.group())



##########
#re.sub 替换函数
#将 string 字符串中所有匹配 pattern 的内容替换成 repl;
    
#参数repl 既可是被替换的字符串,也可是一个函数。
#参数count 控制最多替换多少次,如果指定 count 为 0 ,则表示全部首换。
    
'''

#注意re.sub替换方法中的 替换内容参数的字符串中的任何 \1形式 表示对应替换为匹配模式中的 group(1)的内容。
#注意r'(?P<lang>\w+)' 正则表达式用圆括号表达式创建了一个组,并使用“?P”选项为该组起名为 lang(所起的组名要放在尖括号内)。

'''  

help(re.sub)

my_date='2008-08-18'
print(re.sub(r'-','/',my_date))

def fun(matched):
    '''
    自建函数,用于匹配re.sub里的替换函数
    '''
    value='《基础' + (matched.group('lang')) +'教程》'
    return value
s='Python很好,Kotlin也很好'

#注意r'(?P<lang>\w+)' 正则表达式用圆括号表达式创建了一个组,并使用“?P”选项为该组起名为 lang(所起的组名要放在尖括号内)。
#剩下的“\w+”才是正则表达式的内容,其中“\w”代表任意字符;“+”用于限定前面的“\w”可出现一次到多次,因此“\w+”代表一个或多个任意字符。
print(re.sub(r'(?P<lang>\w+)',fun,s,flags=re.A))    #<>创建组,?P为该组起名



##########
#预先定义匹配模式的 匹配 替换函数
emphasis_pattern=r'\*([^\*]+)\*'          #匹配模式对象为 *星号开头并结尾,中间为排除*星号以外的任意字符
#同上
#注意[^\*]字符集里为匹配单个字符,所有需要贪婪模式+
emphasis_pattern1=re.compile(r'''
                             \*
                             ([^\*]+)
                             \*                             
                             ''',re.VERBOSE)
###
#注意 re.sub 替换方法中的 替换内容参数的字符串中的任何 \1形式 表示对应替换为匹配模式中的 group(1)的内容。
print(re.sub(emphasis_pattern1,r'<em>\1<em>','Hello,*word*!'))
#等同于
emphasis_pattern1.sub(r'<em>\1<em>','Hello,*word*!')



##########
#re.split 根据与模式匹配的子串来 分割 字符串
#参数maxsplit 指定最大分割次数
help(re.split)
some_text='alpha,beta,,,gamma   delta'
re.split('[, ]+',some_text)               #通过字符集[逗号,空格]来分割字符串。即根据逗号 和 空格 都分割
re.split('[, ]+',some_text, maxsplit=2)   #最大分割次数为2次

#根据与模式匹配的子串来 分割字符串,并在分割得到的子串之间 插入 括号中的内容。注意 括号中的内容与匹配模式需要一致。
re.split('o(o)','fooobar')                #通过o来匹配分割字符串,然后用X来插入匹配的位置。


##########
#re.escape 转义字符串中的特殊字符
help(re.escape)
print(re.escape(r'www.crazyit.org is good,i love it'))    #对模式中特殊字符进行转义
print(re.escape(r'A-Z and 0-9'))




####################
#re模块中的两种类及对象    一个是 正则表达式对象  另一个是 匹配对象
'''
#一个是正则表达式对象
#正则表达式对象的 search()、match()、fullmatch()、findall()、finditer() 方法的功能更强大一些,
#因为这些方法都可额外指定 pos 和 endpos 两个参数,用于指定只处理目标字符串从 pos 开始到 endpos 结束之间的子串

#另一个是匹配对象  
#匹配对象  则是 match()、search() 方法的返回值,该对象中包含了详细的正则表达式匹配信息,
#包括正则表达式匹配的 组(group)的信息、位置(span)、子串(start/end)等
#为组指定名字(用 ?P<名字> 为正则表达式的组指定名字),就可以调用 groupdict() 方法来获取所有组所匹配的字符串组成的宇典(其中组名作为字典的 key)
'''

##########
#正则表达式对象  编译预存先缓存重复使用。

#正则表达式对象的 search()、match()、fullmatch()、findall()、finditer() 方法的功能更强大一些,
#因为这些方法都可额外指定 pos 和 endpos 两个参数,用于指定只处理目标字符串从 pos 开始到 endpos 结束之间的子串
pa=re.compile('fkit')                    #预先编译缓存正则表达式
pa.match('www.fkit.org',4).span()        #指定从4的索引开始匹配就可以匹配到开头
pa.match('www.fkit.org',4,6)             #返回None
pa.fullmatch('www.fkit.org',4,8).span()  #返回该位置序列



##########
#匹配对象  则是 match()、search() 方法的返回值,该对象中包含了详细的正则表达式匹配信息,包括正则表达式匹配的位置、正则表达式所匹配的子串。

#r'(tkit).(org)',在该正则表达式内包含两个组,即 (fkit) 和 (org),
#因此程序可以依次获取 group(0)、group(1)、group(2) 的值,也就是依次获取整个正则表达式所匹配的子串、第一个组所匹配的子串和第二个组所匹配的子串;
#程序也可以依次获取 span(0)、span(1)、span(2) 的值,
#也就是依次获取整个正则表达式所匹配的子串的开始位置和结束位置、第一个组所匹配的子串的开始位置和结束位置、第二个组所匹配的子串的开始位置和结束位置。

#注意正则表达式整个 匹配子串 和 匹配组 的概念
m=re.search(r'(fkit).(org)',r'www.fkit.org is a godd domain')
m.group(0)
m[0]                                     #简化写法,底层调用的是m.__getitem(0)
m.span(0)
m.group(1)
m.groups()                               #选取匹配对象的所有匹配条件元祖

#为组指定名字(用 ?P<名字> 为正则表达式的组指定名字),就可以调用 groupdict() 方法来获取所有组所匹配的字符串组成的宇典(其中组名作为字典的 key)
m2=re.search(r'(?P<组1>fkit).(?P<组2>org)',r'www.fkit.org is a good domain')
print(m2.groupdict())




####################
#re示例1  

#自建脚本文件  testRe_find_sender.py    找出发件人
#自建脚本文件  testRe_find_email.py     找出所有邮箱

#然后在控制台运行这个脚本文件,并输入 自建文件参数
#命令如:python testRe_find_sender.py textRe_message.txt


#testRe_find_sender.py
#找出发件人
import re,fileinput

pat=re.compile('From:(.*)<.*?>$')
for line in fileinput.input():
    m=pat.match(line)
    if m:
        print(m.group(1))



#testRe_find_email.py
#找出所有邮箱
import re,fileinput

help(re.compile)
pat=re.compile(r'[a-z0-9\-\.]+@[a-z0-9\-\.]+',re.IGNORECASE)        #re.IGNORECASE 即 re.I 忽略大小写
addresser=set()

#先把所有邮箱放进一个集合内,天然去重机制
for line in fileinput.input():
    for address in pat.findall(line):
        addresser.add(address)            #set集合的add方法,添加元素。类似于list列表的append方法。  需要知道set集合是无序且去重机制。
#然后遍历输出 正向排序的新的集合元素组成的列表
for address in sorted(addresser):         #sorted() 函数对所有可迭代的对象进行排序操作。内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
    print(address)


#testRe_message.txt
'''
From: Foo Fie <foo@bar.com>

290510@qq.com
tengxun@sina.com
hahaha@126.com
'''





####################
#示例2    一个模板系统文件  可控制台操作替换模板内容

#自建脚本文件        testRe_模板.py        定义模板系统文件
#自建模板定义文本    testRE_模板定义.txt    添加模板定义文本
#自建模板文本        testRe_模板文件.txt   模板文本

#然后在控制台运行脚本文件,并输入 模板定义文本 末班文本
#命令如下:python testRe_muban.py mubandingyi.txt muban.txt


#testRe_模板.py
#自建脚本文件        testRe_模板.py        定义模板系统文件
import re,fileinput


field_pat=re.compile(r'\[(.+?)\]')           #预先编译缓存匹配模式 即[]列表内所有内容

scope={}                                     #空字典,用来作为eval的作用域
def replaceMent(match):
    '''
    自定义函数,用于作为re.sub的替换内容参数
    参数为re.sub函数内的匹配模式
    '''
    code=match.group(1)                      #定义替换内容 为匹配到的[]列表内的所有内容
    try:
        #如果字段为表达式,则计算表达式并返回结果
        return str(eval(code,scope))         #尝试对替换内容中的语句执行 求值操作;否则返回空字符串
    except SyntaxError:
        #否则在当前作用域内执行赋值语句
        #并返回一个空字符串
        '''
        这里需要一个赋值语句
        '''
        exec(code,scope)     
        return ''                         


lines=[]
for line in fileinput.input():               #执行读取多个文件操作,读取所有文本并合并成一个字符串
    lines.append(line)
text=''.join(lines)


print(field_pat.sub(replaceMent,text))       #将读取的文件内容进行 替换操作,然后输出。



#testRe_模板.py
#自建脚本文件        testRe_模板.py        定义模板系统文件
'''
[name = '血皇敖天']
[email = '血皇敖天@foo.bar']
[language = 'Python派森']
'''



#testRe_模板文件.txt 
#自建模板文本        testRe_模板文件.txt   模板文本
'''
[import time]
Dear [name]

I would like to learn how to program. i hear you use the [language] language a lot...
And by the way,is [email] your correct email address?

Fooville,[time.asctime()]

Oscar Frozzbozz
'''




####################
#一个简单模板示例
slwj='''
[x=2]
[y=3]
The sum of [x] and [y] is [x+y]
'''
print(field_pat.sub(replaceMent,slwj))











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值