VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > python入门教程 >
  • python--高级语法 10

day:15

1、自定义模块:

什么是模块:本质就是.py文件,封装语句的最小单位。

  • 多个模块对应包,在代码中包就是一个文件夹

自定义模块:实际上就是定义.py,其中可以包含:变量定义,可执行语句,for循环,函数定义等等,他们统称模块的成员。

2、模块的运行方式:

  • 脚本方式:直接用解释器执行。或者PyCharm中右键运行。

  • 模块方式:被其他的模块导入。为导入它的模块提供资源(变量,函数定义,类定义等)。

    '''
    测试自定义模块的导入
    '''
    
    #自定义模块被其他模块导入时,其中的可执行语句会路基执行
    import a
    
    [2, 11, 15, 7]
    
    Process finished with exit code 0
    
    #*******************************************************
    
    #a.py
    nums=[2,11,15,7]
    def fun(nums):
          print(nums)
    
    fun(nums)
    

思考:自定义模块被其他模块导入时,其中的可执行语句会路基执行,如何控制可执行语句不执行?

-----python中提供一种可以判断自定义模块是属于开发阶段还是使用阶段:

​ __name__

就是通过  if __name__ == '__main__': 来实现
    把可执行语句放在主函数main中执行,
    自定义模块在右键运行时,print(__name__) 的属性值 __main__,但是在以模块方式被导入时,在其他脚本中右键运行,print(__name__) 的属性值就是模块名了  如a ,
    所以通过if __name__ == '__main__':  可以控制被调用的模块中的可执行语句不被执行。

3、__name__属性的使用:

  • 在脚本方式运行时(右键执行),__name__是固定的字符串:__main__
nums=[2,11,15,7]
def fun(nums):
      print(nums)

fun(nums)
print(__name__)

[2, 11, 15, 7]
__main__

Process finished with exit code 0
  • 在以模块方式被导入时,__name__就是本模块的名字。
  • 在自定义模块中对__name__进行判断,决定是否执行可执行语句:开发阶段,就执行,使用阶段就不执行。
#开发阶段--会执行
nums=[2,11,15,7]

def fun(nums):
      print(nums)

#__name__
if __name__ == '__main__':
    fun(nums)

[2, 11, 15, 7]

Process finished with exit code 0

#**********************************************************
#使用阶段(调用阶段)---不执行
import a
	#右键执行


Process finished with exit code 0

4、系统导入模块的路径

  • 内存中:如果之前成功导入过某个模块,直接使用已经存在的模块
  • 内置路径中:安装路径下:Lib
  • PYTHONPATH:import时寻找模块的路径。
  • sys.path:是一个路径的列表。

如果上面都找不到,就报错。

通过动态修改sys.path的方式将自定义模块添加到sys.path中。

os.path.dirname():获取某个路径的父路径。通常用于获取当前模块的相对路径

#使用相对路径找到aa文件夹
#print(__file__)   #当前文件的绝对路径
#使用os模块获取一个路径的父路径
#os.path.dirname()
#添加 a.py所在的路径到  sys.path  中
#sys.path.append()

import sys
import os
sys.path.append(os.path.dirname(__file__) + '/aa')

5、导入模块的多种方式:

  • import xxx:导入一个模块的所有成员
  • import aaa,bbb:一次性导入多个模块的成员。不推荐这种写法,分开写。
  • from xxx import a:从某个模块中导入指定的成员。
  • from xxx import a,b,c:从某个模块中导入多个成员。
  • from xxx import *:从模块中导入所有成员。

5.1、import xxx 和 from xxx import * 的区别:

第一种方式在使用其中成员时,必须使用模块名作为前缀。不容易产生命名冲突。

第二种方式在使用其中成员时,不用使用模块名作为前缀,直接使用成员名即可。但是容易产生命名冲突。在后定义的成员生效(把前面的覆盖了。)

5.2、怎么解决名称冲突的问题?

  • 改用import xxx这种方式导入。
  • 自己避免使用同名
  • 使用别名解决冲突

5.3、使用别名:alias

给成员起别名,避免名称冲突。

from my_module import age as a

给模块起别名,目的简化书写。

import my_module as m

5.4、from xxx import * 控制成员被导入

默认情况下,所有的成员都会被导入。

__all__是一个列表,用于表示本模块可以被外界使用的成员。元素是成员名的字符串。

注意:

__all__只是对from xxx import *这种导入方式生效。其余的方式都不生效。

5.5、相对导入

针对某个项目中的不同模块之间进行导入,称为相对导入。

只有一种格式:

from 相对路径 import xxx

相对路径:包含了点号的一个相对路径。

. 表示的是当前的路径。

..表示的是父路径。

...表示的是父路径的父路径。

# 相对导入同项目下的模块
# from ..z import zz            # 容易向外界暴露zz模块
from ..z.zz import *
# 不使用相对导入的方式,导入本项目中的模块
# 通过当前文件的路径找到z的路径
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(__file__)) + '/z')
from zz import *

6、内置模块

random

此模块提供了和随机数获取相关的方法:

  • random.random():获取 [0.0,1.0) 范围内的浮点数
  • random.randint(a,b):获取 [a,b] 范围内的一个整数
  • random.uniform(a,b):获取 [a,b) 范围内的浮点数
  • random.shuffle(x):把参数指定的数据中的元素打乱。参数必须是一个可变的数据类型。
  • random.sample(x,k):从x中随机抽取k个数据,组成一个列表返回。
import random

#random.random():获取 **[0.0,1.0)** 范围内的浮点数
l1=random.random()
print(l1)

#random.uniform(a,b):获取 **[a,b)** 范围内的浮点数
l2=random.uniform(3,5)
print(l2)

#random.randint(a,b):获取 **[a,b]** 范围内的一个整数
l3=random.randint(1,3)
print(l3)

#random.shuffle(x):把参数指定的数据中的元素打乱。参数必须是一个可变的数据类型。
l4=list(range(10))
print(l4)
random.shuffle(l4)
print(l4)

#random.sample(x,k):从x中随机抽取k个数据,组成一个列表返回
l5=(1,2,3)
l6=random.sample(l5,2)
print(l6)

0.41410924095974666
4.725643623367955
2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[5, 4, 2, 6, 7, 8, 1, 0, 3, 9]
[1, 3]

Process finished with exit code 0

time和时间相关

封装了获取时间戳和字符串形式的时间的一些方法。

  • time.time():获取时间戳
  • time.gmtime([seconds]):获取格式化时间对象:是九个字段组成的
  • time.localtime([seconds]):获取格式化时间对象:是九个字段组成的
  • time.mktime(t):时间对象 -> 时间戳
  • time.strftime(format[,t]):把时间对象格式化成字符串
  • time.strptime(str,format):把时间字符串转换成时间对象
import time

#(1)获取时间戳  #时间戳:从时间元年(1970 1 1 00:00:00)到现在经过的秒数。
l1=time.time()
print(l1)

#(2)获取格式化时间对象:是九个字段组成的。
print(time.gmtime())       #GMT
print(time.localtime())

# 默认参数是当前系统时间的时间戳。
print(time.gmtime(1))  # 时间元年过一秒后,对应的时间对象

#(3)格式化时间对象 转换为 字符串
s=time.strftime("year:%Y %m %d %H:%M:%S")
print(s)

#(4)把时间字符串 转换成 时间对象
time_obj = time.strptime('2010 10 10','%Y %m %d')
print(time_obj)

#(5)时间对象 -> 时间戳
t1 = time.localtime() # 时间对象
t2 = time.mktime(t1) # 获取对应的时间戳
print(t2)
print(time.time())

1663252449.9508088
time.struct_time(tm_year=2022, tm_mon=9, tm_mday=15, tm_hour=14, tm_min=34, tm_sec=9, tm_wday=3, tm_yday=258, tm_isdst=0)
time.struct_time(tm_year=2022, tm_mon=9, tm_mday=15, tm_hour=22, tm_min=34, tm_sec=9, tm_wday=3, tm_yday=258, tm_isdst=0)
time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=1, tm_wday=3, tm_yday=1, tm_isdst=0)
year:2022 09 15 22:34:09
time.struct_time(tm_year=2010, tm_mon=10, tm_mday=10, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=283, tm_isdst=-1)
1663252859.0
1663252859.9694235

Process finished with exit code 0

time模块三大对象之间的转换关系:

其他方法:

  • time.sleep(x):休眠x秒.

datetime:日期时间相关

封装了一些和日期,时间相关的类,主要有:

  • date: 需要年,月,日三个参数
  • time: 需要时,分,秒三个参数
  • datetime: 需要年,月,日,时,分,秒六个参数.
  • timedelta: 需要一个时间段.可以是天,秒,微秒

获取以上类型的对象,主要作用是和时间段进行数学运算.

timedelta可以和以下三个类进行数学运算:

  • datetime.time,datetime.datetime,datetime.timedelta
import datetime

#(1):date类:   需要年,月,日三个参数
d=datetime.date(2010,10,10)   #把年月日三个参数转换成一个对象
print(d)
#获取date对象的各个属性
print(d.year)
print(d.month)
print(d.day)

#(2):time类:  需要时,分,秒三个参数
t=datetime.time(10,58,59)
print(t)
#获取time对象的各个属性
print(t.hour)
print(t.minute)
print(t.second)

#(3):datetime 类:  需要年,月,日,时,分,秒六个参数.
dt=datetime.datetime(2022,9,15,23,58,59)
print(dt)
#获取datetime对象的各个属性

#(4):timedelta类:  理解:时间的变化量    需要一个时间段.可以是天,秒,微秒
td=datetime.timedelta(days=1)
print(td)
#参与数学运算
#创建时间对象:
l1=datetime.date(2010,10,10)
res=l1+td
print(res)

2010-10-10
2010
10
10
10:58:59
10
58
59
2022-09-15 23:58:59
1 day, 0:00:00
2010-10-11

Process finished with exit code 0

练习:

  • 显示当前日期前三天是什么时间.
#练习:显示当前日期前三天是什么时间.

year=int(input("输入年份:"))
month=int(input("输入年份:"))
day=int(input("输入年份:"))

#创建指定年月日的date对象
d=datetime.date(year,month,day)
# 创建三天 的时间段
td = datetime.timedelta(days=3)
res = d - td
print(res)

输入年份:2020
输入年份:10
输入年份:4
2020-10-01

Process finished with exit code 0
  • 显示任意一年的二月份有多少天.
#练习:计算某一年的二月份有多少天?
# 普通算法:根据年份计算是否是闰年.是:29天,否:28

# 用datetime模块. # 首先创建出指定年份的3月1号.然后让它往前走一天.
year=int(input("输入年份:"))
# 创建指定年份的date对象
d=datetime.date(year,3,1)
# 创建一天 的时间段
td = datetime.timedelta(days=1)
res = d - td
print(res.day)

输入年份:2014
28
Process finished with exit code 0

os:操作系统接口

此模块提供了灵活的和操作系统相关的函数.

1、删除:

  • os.remove(file_path) : 删除文件
  • os.rmdir(dir_path) : 删除空文件夹
    • 删除非空文件夹使用另一个模块 : shutil
    • shutil.rmtree(path)
  • os.removedirs(name) : 递归删除空文件夹,先删除最里面的目录 然后继续删除父级

2、重命名

  • os.rename(src, dst) : 文件,目录重命名,目标不能事先存在.
#os:操作系统接口
import os

#和文件操作相关(重命名,删除等)
#删除
#os.remove(r'a.txt')

#删除目录,必须时空目录
#os.removedirs('aa')    #OSError: [WinError 145] 目录不是空的。: 'aa'

#使用shutil模块可以删除待内容的目录
import shutil
shutil.rmtree('aa')

#重命名
#os.rename('a.txt','b.txt')

3、和路径相关的属性,更多相关的操作被封装在os.path这个模块中.

  • os.curdir : 当前路径
  • os.sep : 路径分隔符
  • os.altsep : 备用的分隔符
  • os.extsep : 扩展名分隔符
  • os.pathsep : 路径分隔符
  • os.linesep : 行分隔符,不要在写文件的时候,使用这个属性

os.path 模块

此模块实现了一些在路径操作上的方法.

  • os.path.dirname(path) : 返回一个路径中的父目录部分

    如果只是一个盘符,或者是以路径分隔符结尾的字符串,则整体返回.

    否则返回的是路径中的父目录部分.

样例:

import os
print(os.path.dirname('.'))       # 
print(os.path.dirname('/aa/'))    # /aa 
print(os.path.dirname('D:/test')) # D:/ 
print(os.path.dirname('D:/'))     # D:/
  • os.path.basename(path) : 返回path指定的路径的最后一个内容.

    如果只是一个盘符,或者是以路径分隔符结尾的字符串,则返回空;

    否则返回的是路径中的最后一部分内容.

样例:

import os print(os.path.basename('.'))   # . 
print(os.path.basename('/aa'))           # aa 
print(os.path.basename('/aa/'))          # 
print(os.path.basename('D:/test'))       # test
  • os.path.split(path) : 把路径中的路径名和文件名切分开 ,结果是元祖

    返回一个元组,第二个元素表示的是最后一部分的内容,第一个元素表示的是剩余的内容.

    如果只是一个盘符或者是以路径分隔符结尾的字符串,则第二个元素为空.

    否则第二个元素就是最后一部分的内容.

    如果path中不包含路径分隔符,则第一个元素为空.

样例:

import os 
print(os.path.split('D:/'))  # ('D:/', '') 
print(os.path.split('.'))    # ('', '.') 
print(os.path.split('/aa'))  # ('/', 'aa')
  • os.path.join(path,*paths) : 连接若干个路径为一个路径.

    如果路径中有绝对路径,则在这个路径之前的路径都会被丢弃,而从这个路径开始往后拼接.

    Windows中盘符一定要带,否则不认为是一个盘符.

样例:

res = os.path.join('aa','bb','cc')
print(res) # aa\bb\cc 
res2 = os.path.join('D:/','test') 
print(res2) # D:/test
  • os.path.abspath(path) :返回一个路径的绝对路径.

    如果参数路径是相对的路径,就把当前路径和参数路径的组合字符串当成结果返回.

    如果参数路径已经是绝对路径,就直接把参数返回.

    如果参数路径以/开始,则把当前盘符和参数路径连接起来组成字符串返回.

    注意:

    此方法只是简单的将一个拼接好的字符串返回,并不会去检查这个字符串表示的文件是否存在.

样例:

import os 
print(os.path.abspath('aa'))           # D:\PycharmProjects\test03\test01\aa
print(os.path.abspath('D:/test/aa'))   # D:\test\aa 
print(os.path.abspath('/bb'))          # D:\bb

判断功能

os.path.exists(path) : 判断路径是否真正存在.

os.path.isabs(path) : 判断是否是绝对路径

os.path.isfile(path) : 判断是否是文件

os.path.isdir(path) : 判断是否是目录

sys:和python解释器相关

提供了解释器使用和维护的变量和函数.

  • sys.argv :当以脚本方式执行程序时,从命令行获取参数.

    argv[0]表示的是当前正在执行的脚本名.argv[1]表示第一个参数,以此类推.

样例:

有脚本 test.py 内容如下:

import sys print('脚本名称:',sys.argv[0]) 
print('第一个参数是:',sys.argv[1]) 
print('第二个参数是:',sys.argv[2])

使用命令行方式运行该脚本: python test.py hello world

解释器去寻找模块的路径

  • sys.path :系统寻找模块的路径.可以通过PYTHONPATH来进行初始化.

    由于是在程序执行的时候进行初始化的,所以,路径的第一项path[0]始终是调用解释器的脚本所在的路径.如果

    是动态调用的脚本,或者是从标准输入读取到脚本命令,则path[0]是一个空字符串.程序中可以随时对这个路径

    进行修改.以达到动态添加模块路径的目的.

json模块

JSON : JavaScript Object Notation ------Java脚本对象标记语言.

已经成为一种简单的数据交换格式.

序列化和反序列化

序列化 : 将其他数据格式转换成json字符串的过程.

反序列化 : 将json字符串转换其他数据类型的过程.

涉及到的方法:

  • json.dumps(obj) : 将obj转换成json字符串返回到内存中. (dumps是从内存到内存)

  • json.dump(obj,fp) : 将obj转换成json字符串并保存在fp指向的文件中.

  • json.loads(s) : 将内存中的json字符串转换成对应的数据类型对象

  • json.load(f) : 从文件中读取json字符串,并转换回原来的数据类型.

注意:

  • json并不能序列化所有的数据类型:例如:set.

  • 元组数据类型经过json序列化后,变成列表数据类型.

  • json文件通常是一次性写入,一次性读取.但是可以利用文件本身的方式实现:一行存储一个序列化json字符串,在反序列化时,按行反序列化即可.

内存中的数据:结构化的数据:

磁盘上的数据:线性数据:

序列化比喻:

以下是Python中的可以被序列化的数据类型:

补充:写入文件必须要字符串

#t---text
#b---binary  字节
#a---append   追加写
#w---write   覆盖写
#r---read

#默认是 rt
#写入文件必须要字符串
with open('a.txt',mode='wt',encoding='utf-8')as f :
    f.write(10)
    
TypeError: write() argument must be str, not int

Process finished with exit code 1

序列化案例:

1、考察 json.dumps

import json

s=json.dumps([1,2,3])   #把指定的对象转换成json格式的字符串,并保存在内存中
print(type(s))
print(s)

s2=json.dumps((1,2,3))   #元祖序列化后变成列表
print(type(s2))
print(s2)

s3=json.dumps(10)
print(type(s3))
print(s3)

s4=json.dumps({'name':'andy','age':10})
print(type(s4))
print(s4)

<class 'str'>
[1, 2, 3]
<class 'str'>
[1, 2, 3]
<class 'str'>
10
<class 'str'>
{"name": "andy", "age": 10}

Process finished with exit code 0

2、考察 json.dump-----将json 结果写入文件中

#将json  结果写入文件中
with open('a.txt',mode='at',encoding='utf-8')as f:
    json.dump([1,2,3],f)

反序列化案例:

3、考察json.loads

#反序列化
s1=json.dumps([1,2,3])
s2=json.loads(s1)

print(type(s2))
print(s2)

<class 'list'>
[1, 2, 3]

Process finished with exit code 0

4、考察 json.load

#如何从文件中反序列化
with open('a.txt',encoding='utf-8')as f:
    res=json.load(f)
    print(type(res))
    print(res)
    
<class 'list'>
[1, 2, 3]

Process finished with exit code 0

pickle 序列化

python专用的序列化模块. (屁寇)

pickle: 
将python中所有的数据类型,转化成字节串  序列化过程 
将字节串,转化成python中的数据类型     反序列化过程 

pickle模块中的方法基本和json模块中的方法一样.只是适用的数据类型范围比json更广泛.

  • 将其他数据类型序列化成字节

  • 将字节反序列化成其他数据类型

  • 将其他数据类型序列化成字节并写入文件

  • 从文件中读取字节并反序列化成其他数据类型

区别在于:

json: 
1.不是所有的数据类型都可以序列化.结果是字符串. 
2.不能多次对同一个文件序列化. 
3.json数据可以跨语言 

pickle: 
1.所有python类型都能序列化,结果是字节串. 
2.可以多次对同一个文件序列化 
3.不能跨语言.

案例:

1.在内存中序列化和反序列化

import pickle
#序列化列表类型
bys=pickle.dumps([1,2,3])
print(type(bys))    #<class 'bytes'>
print(bys)          #b'\x80\x03]q\x00(K\x01K\x02K\x03e.'

#序列化元祖类型
s1=pickle.dumps((1,2,3))
print(s1)        #b'\x80\x03K\x01K\x02K\x03\x87q\x00.'

#反序列化后,保存了元祖的数据类型  (json不行,json反序列化元祖后,类型是列表)
res=pickle.loads(s1)
print(type(res))     #<class 'tuple'>


#序列化集合类型

s2=pickle.dumps(set('abc'))
res=pickle.loads(s2)
print(type(res))     #<class 'set'>

2、在文件中序列化和反序列化

#把pickle 序列化内容写入文件中
with open('c.txt',mode='wb')as f:
    pickle.dump([1,2,3,4],f)

#从文件中反序列化pickle数据
with open('c.txt',mode='rb')as f:
    q=pickle.load(f)
    print(type(q))
    print(q)
    
<class 'list'>
[1, 2, 3, 4]

Process finished with exit code 0

**hashlib: **加密模块

封装一些用于加密的类.

md5()等

import hashlib
print(dir(hashlib))
['md5', 'new', 'pbkdf2_hmac', 'sha1', 'sha224', 'sha256', 'sha384', 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', 'sha512', 'shake_128', 'shake_256']

加密的目的:用于判断和验证,而并非解密.

特点:

  • 把一个大的数据,切分成不同块,分别对不同的块进行加密,再汇总的结果,和直接对整体数据加密的结果是一致的.
  • 单向加密,不可逆.
  • 原始数据的一点小的变化,将导致结果的非常大的差异,'雪崩'效应.

使用摘要算法加密一个数据的三大步骤:

  • 获取一个加密算法对象.

  • 调用加密对象的update方法给指定的数据加密.

  • 调用加密对象的digest或者是hexdigest获取加密后的结果.

样例:

import hashlib

#获取一个加密对象
m=hashlib.md5()

#使用加密对象的update,进行加密
m.update('abc中文'.encode('utf-8'))  # 对参数进行加密,参数必须是字节类型
#或 m.update(b'abc')

# 通过hexdigest获取加密后的字符串
res=m.hexdigest()

print(res)
# 字节形式的结果
print(m.digest())

1af98e0571f7a24468a85f91b908d335
b'\x1a\xf9\x8e\x05q\xf7\xa2Dh\xa8_\x91\xb9\x08\xd35'

Process finished with exit code 0

简化写法

加密对象的update方法可以调用多次,意味着在在前一次的update结果之上,再次进行加密.如果只是一次更新的话,

还可以直接把数据当成参数传递给构造方法.

例如:

m = md5() 
m.update(data) 
res = m.hexdigest()

和下面的语句是等价的:

res = md5(data).hexdigest()

这种在创建加密对象的时候,就指定初始化的数据,称为 salt (盐).

目的就是为了让加密的结果更加复杂.

练习:

需求:
把用户名和密码信息加密后,通过序列化的方式存储到本地文件中.
并通过控制台输入信息进行验证.
import hashlib
#注册,登录程序:

#加密方法
def get_md5(username,password):
    m=hashlib.md5()
    m.update(username.encode('utf-8'))
    m.update(password.encode('utf-8'))
    return m.hexdigest()

#注册方法
def register(username,password):
    #加密
    res=get_md5(username,password)
    #写入文件
    with open('login',mode='at',encoding='utf-8') as f :
        f.write(res)
        f.write('\n')

#登录方法:
def login(username,password):
    # 获取当前登录信息的加密结果
    res = get_md5(username, password)
    # 读文件,和其中的数据进行对比
    with open('login', mode='rt', encoding='utf-8') as f:
        for line in f:
            if res == line.strip():
                return True
            else:
                return False
            
while True:
    op = int(input("1.注册 2.登录 3.退出  ----请输入:"))
    if op == 3:
        break
    elif op == 1 :
        username=input("请输入用户名:")
        password=input("请输入密码:")
        register(username,password)

    elif op == 2 :
        username=input("请输入用户名:")
        password=input("请输入密码:")
        res=login(username,password)
        if res:
            print('登录成功')
        else:
            print('登录失败')


出处:https://www.cnblogs.com/wushaofan/p/17156647.html

相关教程