上海网站制作顾,十大接单网站,软件开发工具性能审计不包括,银川网站建设网络测试基础-Python篇 基础①
变量名命名规则 - 遵循PEP8原则 普通变量#xff1a;max_value 全局变量#xff1a;MAX_VALUE 内部变量#xff1a;_local_var 和关键字重名#xff1a;class_ 函数名#xff1a;bar_function 类名#xff1a;FooClass 布尔类型的变量名…测试基础-Python篇 基础①
变量名命名规则 - 遵循PEP8原则 普通变量max_value 全局变量MAX_VALUE 内部变量_local_var 和关键字重名class_ 函数名bar_function 类名FooClass 布尔类型的变量名用 is,has 这类词语前缀 is_superuser has_errors allow_empty 释义为数字的单词 port age radius 以_id 为结尾的单词 user_id port_id 以 length/count 开头或结尾的词 length_of_username max_length users_count 注不要用名词的复数形式来作为 int 类型的变量名因为名词的负数形式更像是一个容器。建议使用 number_of_apples 或 trips_count 超短命名 数组索引三剑客 i、j、k 某个整数 n 某个字符串 s 某个异常 e 文件对象 fp
变量注解
在Python3.5之后可以使用类型注解功能来注明变量类型在变量后添加类型并用冒号隔开 def repeat_message(message: str, count: int) - str: return message * count
算术运算符 // 取整除 % 取余 ** 幂
不同类型变量之间的计算 数字型变量之间可以直接计算 如果变量是 bool 型在计算时true 对应的是1false 对应的是0 字符串变量之间使用 拼接字符串。
获取输入的信息-input 字符串变量 input(提示信息) input 输入的数据类型都是字符串类型 格式化输出 %s --字符串 %d --有符号十进制整数%06d 表示输出的整数显示位数不足的地方使用 0 补全 %f --浮点数%.2f 表示小数点后只显示两位会四舍五入 %% --输出%
vb1 Tomprint(hello %s % vb1)vb2 5print(有符号十进制整数%d % vb2)print(输出显示位数的整数%06d % vb2)vb3 3.1415926print(保留两位小数%.2f % vb3)print(保留三位小数%.3f % vb3)vb4 80print(正确率为%d%% % vb4)--------------------------------------------------------------------hello Tom有符号十进制整数5输出显示位数的整数000005保留两位小数3.14保留三位小数3.142正确率为80%
逻辑运算 and 条件1 and 条件2 or 条件1 or 条件2 not取反 not 条件 a 10b 20c 10if c a and c b:print(right)else:print(error)-------------------------------error a 10b 20c 10if c a or c b:print(right)else:print(error)-------------------------------right
循环-while
初始条件设置 -- 通常是重复执行的 计数器 while 条件 1: 条件满足时做的事情 1 条件满足时做的事情 2 条件满足时做的事情 3 …… while 条件 2: 条件满足时做的事情 1 条件满足时做的事情 2 条件满足时做的事情 3 …… 处理条件 2 处理条件 1
print 函数增强
在默认情况下print 函数输出内容之后会自动在内容末尾增加换行 如果不希望末尾增加换行可以在 peint 函数输出内容的后面增加,end 其中中间可以指定 print 函数输出内容之后继续希望现实的内容 语法格式如下 print(*,end)
转义字符 \t--在控制台输出一个制表符协助在输出文本时垂直方向保持对齐 \n--在控制台输出一个换行符 \r--回车 \--反斜杠符号 \--单引号 \--双引号
列表 列表通过索引取值列表索引从0开始且不能超过范围 len(列表)--获取列表的长度 列表.count(数据)--数据在列表中出现的次数 列表.index(数据)--获取数据第一次出现的索引 del 列表 [索引]--删除指定索引的数据 列表.remove[数据]--删除第一个出现的指定数据 列表.pop--删除末尾数据 列表.pop(索引)--删除指定索引的数据 列表.insert(索引,数据)--在指定位置插入数据 列表.append(数据)--在末尾追加数据 列表.extend(列表 2)--将列表2的数据追加到列表1 列表.sort()--升序排序 列表.sort(reverseTrue)--降序排序 列表.reverse() 反转/逆序
元祖 Tuple元组与列表类似不同之处在于元组的 元素不能修改 创建空元组info_tuple () 元组中只包含一个元素时需要在元素后面添加逗号info_tuple (50, ) len(元组)--获取元组的长度 n1 元组.count(数据)--数据在元组中出现的次数 元组 [索引]--从元祖中取值 元组.index(数据)--获取数据第一次出现的索引。
元组和列表之间的转换 使用 list 函数可以把元组转换成列表 list(元组) 使用 tuple 函数可以把列表转换成元组 tuple(列表)
字典 Python 里的字典在底层使用了哈希表 (hash table) 数据结构 和列表的区别列表 是 有序 的对象集合 字典 是 无序 的对象集合 Python3.6 之后的字典是有序的如果解释器版本没有那么新也可以使用 collections 模块里的 OrderedDict 方法保证字典的有序性。 OrderedDict 与新版字典在比较上面的区别在对比两个内容相同但顺序不同的字典时新版字典会返回 TrueOrderedDict 则会返回 False。 from collections import OrderedDict d OrderedDict() d[one] 1 d[two] 2 print(d)———————————————————— OrderedDict([(one, 1), (two, 2)]) 键必须是唯一的 值可以取任何数据类型但键只能使用字符串、数字或元组 字典.keys()--所有 key 列表 字典.values()--所有 value 列表 字典.items()--所有keyvalue元组列表 字典 [key]--可以从字典中取值key 不存在会报错 1.返回的数据类型类似列表但不是真正意义的列表没有 append() 方法; 2.但是可以用于 for 循环; 3.可以用 list() 方转换成真正的列表; 字典.get(key)--可以从字典中取值key 不存在不会报错 del 字典 [key]--删除指定键值对key 不存在会报错 字典.pop(key)--删除指定键值对并且返回删除键对应的值key 不存在会报错 字典.pop(key, defaultmsg)--删除指定键值对并且返回删除键对应的值key 不存在不会报错会返回 msg 字典 popitem() 方法返回并删除字典中的最后一对键和值。 字典.clear()--清空字典 字典 [key] value 如果 key 存在修改数据 如果 key 不存在新建键值对 字典.setdefault(key,value) 如果 key 存在不会修改数据 如果 key 不存在新建键值对 字典.update(字典2)--将字典2的数据合并到字典1如果字典2中有和字典 1 重复的键值对则替换字典 1 中的键值对 生成字典的方法d dict.fromkeys([name,age,code],0) #0 为默认值
字符串 拼接多个字符串使用 str.join 和 同样好用 len(字符串)--获取字符串的长度 字符串.count(字符串)--小字符串在大字符串中出现的次数 字符串 [索引]--从字符串中取出单个字符 字符串.index(字符串)--获得小字符串第一次出现的索引 string.istitle() | 如果 string 是标题化的 (每个单词的首字母大写) 则返回 True string.startswith(str) | 检查字符串是否是以 str 开头是则返回 True string.endswith(str) | 检查字符串是否是以 str 结束是则返回 True string.find(str, start0, endlen(string)) | 检测 str 是否包含在 string 中如果 start 和 end 指定范围则检查是否包含在指定范围内如果是返回开始的索引值否则返回 -1 string.index(str, start0, endlen(string)) | 跟 find() 方法类似不过如果 str 不在 string 会报错 string.replace(old_str, new_str, numstring.count(old)) | 把 string 中的 old_str 替换成 new_str如果 num 指定则替换不超过 num 次 string.capitalize() | 把字符串的第一个字符大写 string.title() | 把字符串的每个单词首字母大写 string.lower() | 转换 string 中所有大写字符为小写 string.upper() | 转换 string 中的小写字母为大写 string.swapcase() | 翻转 string 中的大小写
字符串 - 切片 切片方法适用于字符串、列表、元组 字符串 [开始索引:结束索引:步长] 切片正反向索引正:从 0 开始反:从-1 开始 切片索引[startENDstep] start:开始截取的位置包含在截取内容内 end:结束截取的位置结束截取的位置并不包含 step:截取的步长默认值为 1 step:为正表示从左到右进行截取start 必须在 end 之前从左开始算前下标必须从左到右 step:为负表示从右到左进行截取start 必须在 end 之前从右开始算前下标必须从右到左 s hello,world print(s[:]) # 取全部 print(s[1:]) # 从第 2 位取到最后 print(s[:-1]) # 从开始取到倒数第二位 print(s[::2]) # 步长为 2 print(s[::-1]) # 反序 指定的区间属于左闭右开型 [开始索引, 结束索引) 开始索引 范围 结束索引 从 起始位开始到 结束位的前一位 结束不包含结束位本身) 从头开始开始索引 数字可以省略冒号不能省略 到末尾结束结束索引 数字可以省略冒号不能省略 步长默认为 1如果连续切片数字和冒号都可以省略 索引的顺序和倒序 在 Python 中不仅支持 顺序索引同时还支持 倒序索引 所谓倒序索引就是 从右向左 计算索引 最右边的索引值是 -1依次递减 字符串格式化 优先使用 f-string 方式 # 将username靠右对齐左侧补空格一共到20位username Liliprint(f{username:20})------------------------------------- Lili 对参数复用时可以使用 str.format 方式
username Lilysore 10print({0}:{0}的成绩是{1}.format(username, sore))
集合 集合是一个无序的可变容器类型他最大的特点就是成员不能重复 要初始化一个空集合只能调用 set() 方法因为{}表示的是一个空字典而不是一个空集合 集合也有自己的推导式-nums {n for n in range(10) if n % 2 0} 集合是可变类型可以通过.add() 追加元素 可以使用 update 方法可以将一个可迭代元素更新到集合中
s1 set([1,2,3])s2 set([2,3,4])s1.update(s2)s1.update(hello)print(s1)------------------------{1, 2, 3, 4, o, h, e, l} 使用.remove() 可以删除集合中的元素但元素不存在会报错-KeyError: 使用.discard() 可以删除集合中的元素元素不存在也不会报错 集合的元素不可以修改只能先删再加 我们可以使用 in 判断某个元素是否在某个集合中不能在集合中取值只能使用 for 循环遍历集合中的元素 集合只能存放可哈希对象
s1 set([1,2,3])s1.add([1])-----------------------TypeError: unhashable type: list
集合的运算
集合支持集合运算比如交集、并集、差集。所有的操作都可以用两种方式方法和运算符 交集
fruits_1 {apple,orange,pineapple}fruits_2 {tomato,orange,grapes,mango}print(fruits_1 fruits_2)-----------------------------{orange} 并集
fruits_1 {apple,orange,pineapple}fruits_2 {tomato,orange,grapes,mango}print(fruits_1 | fruits_2)----------------------------------------------------------{tomato, pineapple, orange, apple, grapes, mango} 差集前有后没有
fruits_1 {apple,orange,pineapple}fruits_2 {tomato,orange,grapes,mango}print(fruits_1 - fruits_2)------------------------------------{apple, pineapple} symmetric_difference返回两个集合中不重复的元素
fruits_1 {apple,orange,pineapple}fruits_2 {tomato,orange,grapes,mango}print(fruits_1.symmetric_difference(fruits_2)){apple, mango, tomato, pineapple, grapes} issubset用于判断集合的所有元素是否都包含在指定集合中
fruits_1 {apple,orange,pineapple}fruits_2 {apple,orange,pineapple,water}print(fruits_1.issubset(fruits_2))print(fruits_2.issubset(fruits_1))--------------------------------------------------TrueFalse
Python 循环结构 什么时候用 for当循环次数是一定的或者是循环对象是一定的比如说在一个固定的字符串或列表中进行循环那么最好使用 for 什么时候用 while当循环次数不是一定的只是满足某个条件时才进行循环那么最好使用 while 没有 do…while…循环 循环里面加 else当循环执行完毕时else 才会执行如果循环在中间退出则 else 不会运行 breakcontinue不管是 break 还是 continue 都只作用于当前循环
匿名函数-lambda lambda 关键字能够帮我们创建小型的匿名函数 lambda x:express lambda 返回的是该匿名函数的指针 func lambda x,y:x*y print(func(2,3))
类
类定义 类名首字母大写多个字母连接一起 默认继承 object 类若继承其他类则在类名后加继承父类
类方法 实例方法 1、只能通过对象 (实例) 调用的方法 2、实例方法在定义时总是以 self 作为第一个参数 3、实例方法在调用时不需要传入 self这个实例本身会自动传到方法中作为 self 初始化方法 (init()) 1.不需要显式调用在初始化对象时会有 python 自动调用 2.初始化方法一般只在定义对象属性的时候才会定义 类方法 1、可以直接通过类名调用的方法也可以通过实例调用 2、类方法必须通过classmethod装饰器进行装饰 3、所有的类方法第一个参数必须是 cls 4、类方法不能访问实例属性只能访问类属性 属性方法 使用场景属性方法对应的属性的值无法直接确定要通过一系列的操作才能得到这个值而且用户不关心这个操作过程只想得到这个值。 定义当成属性使用的方法调用属性方法时不需要加 () 静态方法 1、通过staticmethod装饰器来进行装饰的方法 2、静态方法既不能访问实例属性也不能访问类属性 3、可以通过类名直接调用也可以通过对象调用
类的三大特征 封装 暴露接口隐藏细节 继承 1.子类通过继承直接获得父类的全部属性和方法实现代码复用 2.初始化的几种情况 2.1 当子类中没有定义init() 方法则初始化子类时将默认使用父类的初始化方法并传入对应的参数 2.2 当子类定义了自己的初始化方法但没有调用父类的初始化方法则父类中的相关属性不会被初始化 2.3 若在子类中重新定义了 init 方法若仍要继承父类的属性则需要显示调用父类的 init 方法super().init() 多态
类的反射 反射原理 通过字符串的形式在运行时动态修改程序的变量、方法及属性所有的修改都在内存中进行所以他并不会实际修改代码主要目的就是提高代码在运行时的灵活性 反射相关的方法 hasattr 输入一个字符串判断对象有没有这个方法或属性 getattr 获取对象属性值或方法的引用如果是方法则返回方法的引用如果是属性则返回属性的值如果该方法或属性不存在则抛出异常 setattr 动态添加一个方法或属性 delattr 动态删除一个方法或属性。
异常处理
Python 异常处理依赖的关键字 try except else finally try try 块里面放置所有可能引起异常的代码一个异常处理块里面只能有一个 try except 放置要处理的异常类型和相应语句块用于表明该 except 要处理的异常类型 一个异常处理块里面可以跟 1 到 n 个 except 块 每个 except 块后面可以跟 1 到 n 个异常类型也可以不跟任何异常类型 else 如果 try 块里面的语句没有引起异常则会运行 else 里面的语句 finally 主要用于回收再 try 块里面打开的物理资源异常处理机制会保证 finally 块一定会被执行 异常处理语法结构 1.只有 try 是必须的 2.如果没有 try就不能有 except 和 finally 3.except 块和 finally 块都是可选的但 except 和 finally 必须出现其中之一也可以同时出现 4.可以有多个 except 块但捕获父类异常的 except 块要写在捕获子类异常的 except 块的后面 5.多个 except 块必须位于 try 块之后finally 块必须位于所有块的最后
IO 读写 - 文本文件 open (path,mode) 默认是 r只读模式文件必须事先存在不主动生成文件从文件开头开始读 r读写模式文件也必须事先存在不主动生成文件从文件开头开始读或写 w只写模式如果用 w 模式打开一律会清空之前文件的所有内容如果文件不存在则自动创建文件从头开始写 w读写模式也会清空之前文件的所有内容如果文件不存在则自动创建文件从头开始写 a追加模式只写不会清空以前文件的内容主动生成文件从文件尾开始写入 a:追加模式读和写不会清空以前文件的内容主动生成文件从文件尾开始写入或读取 二进制读写一般用于图片或音视频rb,wb,ab 查看和设置文件指针位置 with open(user.txt, a) as f: # 将文件指针重置至开始位置(这样就不会导致f.readlines()读不到数据了) f.seek(0) # 返回文件指针位置 print(f.tell()) with 是 python 中的上下文管理器它会自动帮你管理文件的句柄 with open(rD:\testlog.txt) as f:for line in f.readlines(): print(line,end) 文件与文件夹 windows 文件路径用反斜线Linux 文件路径用正斜线要想将程序在不同系统上运行则可用 os.path.join() 方法 myFiles [accounts.txt,details.csv,invite.docx] for filename in myFiles: print(os.path.join(c:\\User\\asweigart,filename))-----------------------------------------------------------------------------------------c:\User\asweigart\accounts.txtc:\User\asweigart\details.csvc:\User\asweigart\invite.docx
其余相关知识点附张图吧 多线程和多进程编程 概念 程序指的是一段静态的代码指令 进程正在执行的程序将静态的执行代码运行起来进程内拥有该程序执行所需的全部资源 线程是指正在执行程序的最小单元。一个进程中至少必须有一个线程主线程在程序中线程是独立的可运行的流 多线程在单个程序中同时运行多个不同的线程完成不同的工作 进程特征 独立性进程是系统中独立存在的实体拥有独立的资源空间 动态性进程拥有自己的生命周期 并发性多个进程可以在单个处理器上并发执行互不影响 线程特征 每个线程都有自己的堆栈自己的程序计数器自己的局部变量这里体现了程序的独立性 在相同父进程下的所有线程共享进程内所有资源可以实现线程间的消息互通 多个线程之间也可以并发执行互不影响 创建多线程-threading 1.使用 threading 模块的 Thread 类的构造器创建线程对象。在创建线程对象时使用 target 参数指定函数线程的执行体 2.调用线程对象的 start() 方法启动线程 通过 join 方法去阻塞主线程 d Demo()t1 threading.Thread(targetd.music,args(摇篮曲,))t2 threading.Thread(targetd.movie, args(灰太狼,))t1.start()t2.start()t1.join()t2.join() 设置守护线程 主线程结束后立即结束所有设置为守护线程的子线程; 多线程锁 import threadingbalance 0lock threading.RLock()def change_it(n):lock.acquire()try: global balance balance n balance - nfinally: lock.release()def run_threading(n):for i in range(100000000): change_it(n)t1 threading.Thread(targetrun_threading, args(5,))t2 threading.Thread(targetrun_threading, args(5,))t1.start()t2.start()t1.join()t2.join()
GIL 全局解释器锁
什么是 GIL 全局解释器锁 GILGlobal Interpreter Lock是 Python 的一个重要特性它是一种机制用于保护多线程环境下共享内存数据的完整性。它锁定了整个解释器只允许一个线程同时执行 Python 字节码从而避免多线程下出现数据竞争问题。这意味着即使使用多核 CPUPython 程序也不能充分利用多核优势。GIL 在性能上可能带来一定的影响因此不适合处理需要大量的 CPU 运算的任务。
什么条件下会释放 GIL 当前活跃线程遇到 IO 等待比如要访问网络或建立数据库链接等情况; 活跃线程执行了 100 个字节码的程序后GIL 也会释放该线程的锁然后与其他线程参与竞争;
python 的多线程适合场景 python 的多线程只适合于 IO 密集型应用对于计算密集型的应用最好使用多进程或协程的方式解决
可迭代对象 通俗说可迭代对象就是可以放在 for 循环内进行迭代的对象 比如列表、字典、元祖、字符串 判断一个可迭代对象的依据是什么 必须至少实现getitem或iter这两个方法中的其中一个
迭代器 任何实现了iter和next方法的对象都是迭代器这两个方法必须同时实现 其中iter会返回迭代器本身 next会返回迭代器中的下一个元素如果没有元素了将抛出 stopIteration 异常 迭代器当然也可以用到 for 循环中 迭代器实际上就是一种工厂模式。
迭代器和可迭代对象的区别 迭代器是迭代对象的一种迭代器一定是可迭代对象可迭代对象不一定是迭代器 一个合法的迭代器必须同时实现iter和next两个魔法方法 可迭代对象只需要实现iter方法即可 判断对象 obj 可迭代的唯一方法就是调用 iter(obj)看返回结果是不是一个迭代器 每个迭代器的被迭代过程是一次性的可迭代对象则不一定
生成器 特殊的迭代器只需要使用 yield 关键字那么就会立即变为一个生成器也就是说只要一个函数中包含了一个 yield 关键字不管几个那么这个函数就会自动变成一个生成器函数 生成器一定是一个迭代器但反之不一定成立 特点 生成器中每次遇到 yield 关键字之后会返回相应的结果 保留函数当前的运行状态等待下一次调用下次调用时将从上一次返回 yield 语句处开始执行后面的语句 生成器的 send 方法可以向函数体内去传递值 对于 next 和 send 方法的异同 next 和 send 都可以去调用一次生成器从调用生成器的角度来说他们的作用完全一样 next 无法像生成器内部的变量赋值但 send 可以 next(gen) 等同于 send(None)可以互换 在生成器中使用 for 循环 每一次 for 循环相当于调用一次 next for 循环会自动帮助我们处理 stopIteration 异常。
装饰器 定义 装饰器本质是函数只是它的作用是为其他函数添加特定的附加功能 编写装饰器的原则 装饰器一定不能修改被装饰器的函数的源码 装饰器一定不能修改被装饰的函数的调用方式 实现装饰器的前置知识条件 1.函数即变量 函数和普通变量的存储原理是一样的函数名可以像变量名那样去使用比如可以进行赋值 2.掌握高阶函数相关知识 符合下面任意条件之一即为高阶函数 条件一接收函数名作为参数 条件二返回值中包含函数名 3.掌握函数嵌套相关知识 通过 def 关键字在一个函数 A 中去定义另外一个函数 B,则函数 B 称为嵌套函数 4.装饰器高阶函数 嵌套函数 了解装饰器的本质优势 1.运行时校验在执行阶段进行特定校验当校验不通过时终止执行 Django 框架中的用户登录态校验装饰器login_required 2.注入额外参数在函数被调用时自动注入额外的调用参数 unittest.mock 模块的装饰器patch 3.缓存执行结果通过调用参数等输入信息直接缓存函数执行结果 functools 模块的缓存装饰器lru_cache 4.注册函数将被装饰函数注册为某个外部流程的一部分 Flask 框架的路由注册装饰器app.route 5.替换为复杂对象将原函数 (方法) 替换为更复杂的对象比如类实例或特殊的描述符对象 静态方法的装饰器staticmethod。
正则表达式
正则表达式匹配步骤 1.import re 2.用 re.compile() 函数创建一个 Regex 对象记得使用原始字符串 3.向 Regex 对象的 search() 方法传入想查找的字符串。它返回一个 Match 对象一般用 mo 接收 4.调用 Match 对象的 group() 方法返回实际匹配的字符串 demo
import re phoneNumRegex re.compile(r(\d\d\d)-(\d\d\d-\d\d\d\d)) mo phoneNumRegex.search(my number is 415-555-4242.) mo.group(1)415 mo.group(2)555-4242 mo.group()415-555-4242 mo.group(0)415-555-4242
PLus
我在学习中发现正则表达式在任何语言中都占有很大部分的占比但正则表达式相关的知识点又过于零碎对于榆木脑袋的我真是学一遍忘一遍。在实际工作中我自己真正用到正则的地方并不多再看同事目前就发现前端同学有可能会用到正则去做一些事情并且用到的时候都是度娘一是自己真记不住二是度娘 copy 过来的多数情况是比自己写要严谨的多的。
基于此我把正则视为投入产出比太低的事情仅需要记住个大概印象真到用时能分清度娘上哪个轮子能用哪个轮子用不了就可以了。
测试基础-Python篇 基础②
常用模块-math
import math print(math.ceil(3.14)) # 取大于等于 x 的最小整数 print(math.fabs(-3)) # 取绝对值 print(math.floor(3.14)) # 取小于等于 x 的最大整数 print(math.fsum([1,2,3])) # 求和 print(math.pow(3,4)) #3 的 4 次方 等价于 3**4 print(math.sqrt(3)) # 开平方3 的平方根
常用模块-random
import random print(random.random()) # 返回 [0.0,1.0) 之间的浮点数 print(random.randint(10,20)) # 生成 10 到 20 之间的一个随机整数也就是 [10,20] print(random.randrange(10,20)) # 生成 10 到 20 之间的一个随机整数也就是 [10,20) print(random.uniform(10,20)) # 生成 10 到 20 之间的一个随机浮点数也就是 [10,20] print(random.choice([10,20,30])) # 随机从列表选择一个数 print(random.choices([10,20,30],k2)) # 随机从列表选择 k 个数返回列表形式取出放回方式意思是取出的数可以重复 print(random.sample(a1,3)) # 随机从列表选 k 个数返回列表形式取出不放回方式意思是取出的数不会重复 random.shuffle(a1) # 洗牌随机变换列表顺序
常用模块-json 用 loads() 函数读取 JSON 要将包含 JSON 数据的字符串转换为 Python 的值就将它传递给 json.loads() 函数 用 dumps() 函数写出 JSON 将一个 python 值转换成 JSON 格式的数据字符串就用 json.dumps() 函数 import jsond {name:Tom,age:26}j json.dumps(d)d2 json.loads(j)print(d)print(type(d))print()print(j)print(type(j))print()print(d2)print(type(d2))-------------------------------------{name: Tom, age: 26}class dict {name: Tom, age: 26} class str {name: Tom, age: 26} class dict
常用模块-time round() 第一个参数是要处理的数字第二个可选参数为四舍五入保留的位数若不传如第二个参数则默认四舍五入到最近的整数
import timen time.time()print(n)n1 round(n,3)print(n1)------------------------1675392067.29749661675392067.297 time.time() ---获取当前时间戳:1675392067.2974966 time.sleep(sec) ---睡眠 sec 秒
常用模块-datetime() datetime 模块有自己的 datetime 数据类型 datetime 的一些方法 import datetimedt datetime.datetime.now()print(dt)print(dt.year: str(dt.year) ---type: str(type(dt.year)))print(dt.month: str(dt.month) ---type: str(type(dt.month)))print(dt.day: str(dt.day) ---type: str(type(dt.day)))print(dt.hour: str(dt.hour) ---type: str(type(dt.hour)))print(dt.minute: str(dt.minute) ---type: str(type(dt.minute)))print(dt.second: str(dt.second) ---type: str(type(dt.second)))----------------------------------------------------------------------------------------------------------2023-02-03 11:00:08.205691dt.year:2023---type:class int dt.month:2---type:class int dt.day:3---type:class int dt.hour:11---type:class int dt.minute:0---type:class int dt.second:8---type:class int Unix 时间戳可以通过 datetime.datetime.fromtimestamp() 转换为 datetime 对象
import datetimeimport timenow time.time()date datetime.datetime.fromtimestamp(now)print(now)print(date)----------------------------------------------------------------------------1675393953.08603122023-02-03 11:12:33.086031 datetime对象可以用比较操作符进行比较后面的datetime对象时更大的值
import datetimeimport timed1 datetime.datetime.now()time.sleep(1)d2 datetime.datetime.now()print(d2d1)-----------------------------------------------True datetime 对象的差的数据类型是timedelta
import datetimeimport timed1 datetime.datetime.now()time.sleep(1)d2 datetime.datetime.now()d3 d2 -d1print(d3)print(type(d3))------------------------------------------------0:00:01.002022class datetime.timedelta 要创建 timedelta 对象就用 datetime.timedelta() 函数 import datetimedt datetime.timedelta(days11,hours10,minutes9,seconds8)print(dt)print(type(dt))print(dt.days)print(dt.seconds) # 天不参与计算10*60*60 9*60 8 36548print(dt.total_seconds()) # 11*24*60*60 10*60*60 9*60 8 986948print(str(dt))---------------------------------------------------------------------------------------------------------11 days, 10:09:08class datetime.timedelta 11 36548 986948.0 11 days, 10:09:08 算数运算符可以用于对 datetime 值进行日期运算,例如要计算今天之后 1000天的日期;
import datetimedt datetime.datetime.now()print(dt)thounsandDays datetime.timedelta(days1000)print(thounsandDays)print(dt thounsandDays)------------------------------------------------------------------------------2023-02-06 14:20:46.2650841000 days, 0:00:002025-11-02 14:20:46.265084
常用模块-logging
Logging 库是非常常用的记录日志库通过 logging 模块存储各种格式的日志主要用于输出运行日志可以设置输出日志的等级、日志保存路径、日志文件回滚等; 日志级别 DEBUG --logging.debug() INFO --logging.info() WARNING --logging.warning() ERROR --logging.error() CRITICAL --logging.critical() 使用日志模块
import logginglogging.basicConfig(format%(levelname)s %(asctime)s: %(message)s: %(module)s,levellogging.DEBUG)logging.debug(This message should appear on the console)logging.info(So should this)logging.warning(And this, too)-----------------------------------------------------------------------------------------------------DEBUG 2023-02-07 17:04:37,473: This message should appear on the console: logging_practiceINFO 2023-02-07 17:04:37,473: So should this: logging_practiceWARNING 2023-02-07 17:04:37,473: And this, too: logging_practice 将日志记录到文件-logging.basicConfig() 函数接受 filename 关键字。
import logginglogging.basicConfig(filenamemyProgramLog,format%(levelname)s %(asctime)s: %(message)s: %(module)s,levellogging.DEBUG)logging.debug(This message should appear on the console)logging.info(So should this)logging.warning(And this, too) 禁用日志 只要向 logging.disable() 传入一个日志级别他就会禁止该级别和更低级别的所有日志消息; logging.disable(logging.CRITICAL) 加在代码前面即可隐藏日志信息接近 import.logging 的位置更容易找到和管理;
import logginglogging.disable(logging.CRITICAL)logging.basicConfig(filenamemyProgramLog,format%(levelname)s %(asctime)s: %(message)s: %(module)s,levellogging.DEBUG)logging.debug(This message should appear on the console)logging.info(So should this)logging.warning(And this, too)
常用模块-threading 要得到单独的线程首先要调用 threading.Thread() 函数生成一个 Thread 对象。 import timeimport threadingprint(Start of program.)def takeANap(): time.sleep(5) print(Wake up!)threadObj threading.Thread(targettakeANap)threadObj.start()print(End of program)----------------------------------------------------------------------------Start of program.End of programWake up! 注意target 参数名后传的是方法名不加 ()因为此处并不是调用。 向线程的目标函数传递参数 常规参数可以作为一个列表传递给 threading.Thread() 中的 args 关键字参数。关键字参数可以作为一个字典传递给 threading.Thread() 中的 kwargs 关键字参数 import threadingl [1,2,3,4]def a(*args): for _ in args: print(_)thread_a threading.Thread(targeta,argsl)thread_a.start()------------------------------------------------------------------------1234 import threadingd {name: Tom, age: 18}def b(**kwargs): for k, v in kwargs.items(): print(str(k) : str(v))thread_b threading.Thread(targetb, kwargsd)thread_b.start()----------------------------------------------------------------------------name:Tomage:18 并发问题需要注意的是为了避免并发问题绝不让多个线程读取或写入相同变量。当创建一个新的 Thread 对象时要确保其目标函数只使用该函数中的局部变量。 线程阻塞-thread.join() thread.join() 方法的作用是阻塞当前线程直到调用 join() 方法的线程结束。也就是说如果你有多个线程并希望在其中一个线程结束之后再继续执行则可以使用 join() 方法。 # 不使用join两个线程并行运行import timeimport threadingdef a(): time.sleep(1) print(我是a1/3) time.sleep(1) print(我是a2/3) time.sleep(1) print(我是a3/3)def b(): print(我是b1/2) print(我是b2/2)thread_a threading.Thread(targeta)thread_b threading.Thread(targetb)thread_a.start()thread_b.start()-------------------------------------------------------------我是b1/2我是b2/2我是a1/3我是a2/3我是a3/3 # 使用join线程b需要等线程a运行完后再运行import timeimport threadingdef a(): time.sleep(1) print(我是a1/3) time.sleep(1) print(我是a2/3) time.sleep(1) print(我是a3/3)def b(): print(我是b1/2) print(我是b2/2)thread_a threading.Thread(targeta)thread_b threading.Thread(targetb)thread_a.start()thread_a.join()thread_b.start()--------------------------------------------------------------我是a1/3我是a2/3我是a3/3我是b1/2我是b2/2 # join()方法可以自定义timeout参数意为最长暂用CPU时间如果不设置的话就永远等待import timeimport threadingdef a(): time.sleep(1) print(我是a1/3) time.sleep(1) print(我是a2/3) time.sleep(1) print(我是a3/3)def b(): print(我是b1/2) print(我是b2/2)thread_a threading.Thread(targeta)thread_b threading.Thread(targetb)thread_a.start()thread_a.join(timeout2)thread_b.start()-------------------------------------------------------------我是a1/3我是a2/3我是b1/2我是b2/2我是a3/3
深拷贝浅拷贝
不可变数据类型如整型字符串等在 Python 中只是拷贝了值因此在执行浅拷贝时实际上是创建了一个新的副本而不是拷贝引用。因此对原数据的更改不会影响到拷贝后的数据。
import copya 1000b ac copy.copy(a)d copy.deepcopy(a)print(a, b, c, d)print(id(a), id(b), id(c), id(d))a 1print(a, b, c, d)print(id(a), id(b), id(c), id(d))----------------------------------------------1000 1000 1000 10002518799374640 2518799374640 2518799374640 25187993746401001 1000 1000 10002518805613936 2518799374640 2518799374640 2518799374640
对于可变数据类型浅拷贝只拷贝第一层中的引用深拷贝在拷贝时会逐层进行拷贝直到所有的引用都是不可变对象为止。
import copya [1, 2, [3, 4]]b ac copy.copy(a)d copy.deepcopy(a)e a.copy()f a[:]print(a, b, c, d, e,f)print(id(a), id(b), id(c), id(d), id(e),id(f))print()a.append(5)print(a, b, c, d, e,f)print(id(a), id(b), id(c), id(d), id(e),id(f))print()a[2].append(6)print(a, b, c, d, e,f)print(id(a), id(b), id(c), id(d), id(e),id(f))----------------------------------------------------[1, 2, [3, 4]] [1, 2, [3, 4]] [1, 2, [3, 4]] [1, 2, [3, 4]] [1, 2, [3, 4]] [1, 2, [3, 4]]2213595331584 2213595331584 2213595362304 2213595356992 2213595443008 2213595442368[1, 2, [3, 4], 5] [1, 2, [3, 4], 5] [1, 2, [3, 4]] [1, 2, [3, 4]] [1, 2, [3, 4]] [1, 2, [3, 4]]2213595331584 2213595331584 2213595362304 2213595356992 2213595443008 2213595442368[1, 2, [3, 4, 6], 5] [1, 2, [3, 4, 6], 5] [1, 2, [3, 4, 6]] [1, 2, [3, 4]] [1, 2, [3, 4, 6]] [1, 2, [3, 4, 6]]2213595331584 2213595331584 2213595362304 2213595356992 2213595443008 2213595442368 Python 有多种方式实现浅拷贝copy 模块的 copy 函数 对象的 copy 函数 工厂方法切片等。 赋值符号如果是可变类型就是引用传递如果是不可变类型就是值传递。 浅拷贝的优点拷贝速度快占用空间少拷贝效率高。 因为浅拷贝不能解决嵌套问题所以引出了深拷贝深拷贝会遍历并拷贝 items 里所有的内容 - 包括他嵌套的子列表
对象的可哈希性 不可变的内置类型都是可哈希的比如 str、int、float、frozenset 可变的内置类型都是不可以哈希的比如 list、dict 对于不可变容器类型tuple、frozenset仅当他的所有成员都不可变时他自身才是可哈希的 用户定义的类型默认都是可哈希的 注意只有可哈希对象才能被放进集合或者作为字典的键 sorted() 函数
sorted 函数是 Python 内置函数用于对可迭代对象进行排序并返回一个新的列表。 注意sorted 函数不会改变原来的可迭代对象而是返回一个新的列表。如果需要改变原来的可迭代对象可以使用 sort 方法但它只能用于列表。 参数 iterable可以是列表、元组、字典等任意可迭代对象。 key一个函数用于提取每个元素的排序关键字。默认为 None表示按元素本身的顺序进行排序。 reverse是否按降序排列默认为 False表示按升序排列。
enumerate() 函数
enumerate() 适用于任何可迭代对象可以用于列表、元祖、字典、字符串等。 def enumerate_func(): names [lily,wenwen,tom] for index, s in enumerate(names,start1): print(index,s)---------------------------------------------1 lily2 wenwen3 tom 如果不指定 start 参数则 index 从 0 开始 测试基础-Python篇 基础③
浮点数精度问题
print(0.10.2)----------------------0.30000000000000004
可以使用 decimal 模块解决浮点数精度问题 from decimal import Decimalprint(Decimal(0.1) Decimal(0.2))print(type(Decimal(0.1) Decimal(0.2)))print(type(Decimal(0.1)))---------------------------------------------------------0.3class decimal.Decimal class decimal.Decimal 注意在使用 Decimal 时要用字符串来表示数字 布尔值其实也是数字 布尔类型其实是整型的子类型 True 和 False 这两个布尔值可以直接当做 1 和 0 来使用 通过这个特点最常用于统计总数 def sum_even(numbers: list[int]): 返回numbers中偶数的个数 :param numbers: 整数列表 return sum(i % 2 0 for i in numbers)
不常用但特别好用的字符串方法 str.partition(sep) 按照切分符 sep 切分字符串返回一个包含三个成员的元祖 (part_before, sep, part_after)若 s 不包括分隔符则最后一个成员默认是空字符串
s TomAndMarrys2 s.partition(And)print(s2)--------------------------------(Tom , And, Marry) 2.str.translate(table) 他可以按规则一次性替换多个字符使用它比调用多次 replace 方法更快也更简单
s 明明是中文,却使用了英文标点.table s.maketrans(,., 。)s2 s.translate(table)print(s2)-----------------------------------------------明明是中文却使用了英文标点。
使用枚举类型来替代字面量 更易读所有人都不需要记忆某个数字代表什么; 更健壮降低输错数字或字母产生 bug 的可能性; # 用户每日奖励积分数量DAILY_POINTS_REWARDS 100# VIP用户额外奖励20VIP_EXTRA_POINTS 20from enum import Enumclass UserType(int, Enum): # VIP用户 VIP 3 # 小黑屋用户 BANNED 13def add_daily_points(user): 用户每天第一次登录增加积分 if user.type UserType.BANNED: return if user.type UserType.VIP: user.points DAILY_POINTS_REWARDS VIP_EXTRA_POINTS return user.points DAILY_POINTS_REWARDS return
生成器 定义一个生成器需要生成器函数和 yield 关键字 yield 和 return 最大的区别在于return 会一次性返回结果使用它会直接中断函数执行而 yield 可以逐步给调用方生成结果 使用生成器的优点是它们占用的内存比列表要少因为它们只生成一个元素并在需要时生成下一个元素。这使得生成器特别适合于处理大量数据 每次调用生成器函数都会生成一个新的生成器对象 fruits {apple,orange,pineapple}def batch(item): for _ in item: yield _print(next(batch(fruits)))print(next(batch(fruits)))print(next(batch(fruits)))---------------------------------------appleappleapple 因为每次调用生成器函数都会生成一个新的生成器对象所以以上程序运行结果会输出三个 apple fruits {apple,orange,pineapple}def batch(item): for _ in item: yield _g batch(fruits)print(next(g))print(next(g))print(next(g))-------------------------------------------------pineappleappleorange 以上代码再次验证了每次调用生成器函数都会生成一个新的生成器对象结论 使用生成器的 next() 函数可以在需要时单独生成生成器中的元素而不是一次性生成整个列表。如果生成器中没有元素则会引发 StopIteration 异常 用生成器替代列表 def batch_process(item): result [] for i in item: # process_item ..处理item result.append(process_item) return result# 以上方法会有一个问题当item过大时会导致函数执行很耗时并且若调用方想在某个process_item达到条件时中断以上方法也是做不到的。所以可以使用生成器函数替代。def batch_process_2(item): for i in item: # process_item ..处理item yield process_item# 调用方for processed_item in batch_process_2(items): # 如果某个处理对象过期了就中断当前的所有处理 if processed_item.has_expired(): break
面向对象编程
内置类方法装饰器 类方法 1.用 def 在类里定义一个函数时这个函数通常被称作方法。调用这个方法需要先创建一个类实例 2.可以使用classmethod装饰器定义类方法它属于类无需实例化也能调用 3.作为一种特殊方法类方法最常见的使用场景就是定义工厂方法来生成新实例类方法的主角是类型本身当发现某个行为不属于实例而是属于整个类型是可以考虑使用类方法 静态方法 1.如果发现某个方法不需要使用当前实例里的任何内容那可以使用staticmethod来定义一个静态方法 2.和普通方法相比静态方法不需要访问实例的任何状态是一种与状态无关的方法因此静态方法其实可以写成脱离于类的外部普通函数 2.1.如果静态方法特别通用与类关系不大那么把他改成普通函数会更好; 2.2.如果静态方法与类关系密切那么用静态方法更好; 2.3.相比函数静态方法有一些先天优势比如能被子类继承和重写; 属性装饰器 1.property 装饰器模糊了属性和方法间的界限使用它可以把方法通过属性的方式暴露出来; 2.property 除了可以定义属性的读取逻辑外还支持自定义写入和删除逻辑; class FilePath: property def basename(self): .... property.setter def basename(self, name): .... property.deleter def basename(self): .... 经过property的装饰以后basename 已经从一个普通的方法变成了 property 对象所以可以使用 basename.setter 和 basename.deleter 方法; 定义 setter 方法该方法会在对属性赋值是被调用; 定义 deleter 方法该方法会在删除属性时被调用; 鸭子类型及其局限性 在鸭子类型编程风格下如果想操作某个对象你不会去判断他是否属于某种类型而会直接判断他是不是有你需要的方法 (或属性)。或者更激进一些。你甚至会直接尝试调用需要的方法假如失败了那就让她报错好了; 鸭子类型的优点就是编写简单使用灵活; 鸭子类型的缺点就是缺乏标准、过于隐式; 可以使用类型注解、静态检查 (mypy)、抽象类来补充鸭子类型;
抽象类 isinstance() 函数 利用 isinstance() 函数我们可以判断对象是否属于特定类型 isinstance() 函数能理解类之间的继承关系因此子类的实例同样可以通过基类的校验 校验对象是否是 Iterable 类型 在 collections.abc 模块中有许多和容器相关的抽象类比如代表集合的 Set、代表序列的 Sequence 等其中有一个最简单的抽象类Iterable他表示的是可迭代类型 鸭子类型和抽象类总结 鸭子类型是一种编码风格在这种风格下代码只关心对象的行为不关心对象的类型 鸭子类型降低了类型校验的成本让代码变得更灵活 传统的鸭子类型里各种对象接口和协议都是隐式的没有统一的显示标准 传统的 isinstance() 类型检查和鸭子类型的理念是相违背的 抽象类是一种特殊的类他可以通过钩子方法来定制动态的子类检查行为 因为抽象类的定制子类化特征isinstance() 也变得更灵活、更契合鸭子类型了 使用abstractmethod装饰器抽象类可以强制要求子类在继承时重写特定方法 除了抽象方法外抽象类也可以实现普通的基础方法供子类继承使用 在 collections.abc 模块中有许多与容器相关的抽象类
多重继承于MRO Python 里的一个类可以同时继承多个父类 调用类的 mro() 方法可以看到按 MRO 算法排好序的基类列表 在许多人印象中。super() 是一个用来调用父类方法的工具函数。但这么说并不准确super() 使用的其实不是当前类的父类而是当前类在 MRO 链条上的上一个类 应该避免多重继承
学习建议
对于Python入门及进阶我推荐两本我认为值得多次阅读的书籍 《Python编程从入门到实践第二版》- 第一部分为基础语法部分建议刚接触 Python 的同学多次阅读并实践夯实基础利器 《Python工匠》- 整本无尿点强烈建议多次阅读并实践是Python进阶的不二之选
其他琐碎但十分实用的知识点 for......else......的执行顺序 当迭代对象完成所有迭代后且此时的迭代对象为空时如果存在 else 子句则执行 else 子句没有则继续执行后续代码如果迭代对象因为某种原因如带有 break 关键字提前退出迭代则 else 子句不会被执行程序将会直接跳过 else 子句继续执行后续代码 数值型比较不能使用 not in因为 not in 本质是循环遍历右侧数据用左侧数据进行比对len() in range(1,5) 可以使用因为 range 是一个集合可以遍历 li in lili不建议使用因为返回结果为 True(包含)达不到预期结果所以准确比较建议使用 字典取值有两种方式a{name:lili} 第一种a[name] 第二种a.get(name) 区别a[wenwen] 报错-KeyError a.get(wenwen) 不报错-None 如果在方法中给全局变量赋值则要在方法中提前声明全局变量-global 列表转成字符串.join(list) 用中的字符串作为连接拼接 list 列表中的每个元素 --- 只能用在每个元素都是字符串的时候可以用要不然就会报错 集合数据类型 set 取值 因为集合set是一种无序的不重复的元素的集合。因为集合中的元素没有特定的顺序所以无法通过下标索引来访问。 可以使用循环遍历取值也可使用 in 判断目标元素是否在集合中。 当遇到复杂计算的数字字面量时保留整个数学公式提示可读性也不会降低性能; 要判断某个容器是否包含特定成员用集合比用列表更合适因为集合底层使用了哈希表数据结构 # 列表数据越多效果越明显VALID_NAMES [pip, lili, name]VALID_NAMES_SET set(VALID_NAMES)def validate_name(name): if name not in VALID_NAMES_SET: raise ValueError(f{name} is not a valid name) 使用集合去重会导致去重后的集合丢失原有的成员顺序若要去重又要保持原有的成员顺序可使用有序字典 OrderedDict nums [10, 2, 3, 21, 10, 3]def ordered_dict(member: list[int]): from collections import OrderedDict result list(OrderedDict.fromkeys(member).keys()) return resultprint(ordered_dict(nums))----------------------------------------------------[10, 2, 3, 21] 在遍历时不要直接修改原列表可以启用一个新列表来保存修改后的成员; 对于未来可能会变动的多返回值函数来说可以使用 NamedTuple 类型对返回结果进行建模可以减少后期代码变动对已有程序的影响 from typing import NamedTupleclass Address(NamedTuple): 地址信息结果 country: str province: str city: strdef latlon_to_address(lat, lon): return Address( country country, province province, city city, )addr latlon_to_address(lat, lon)# 通过属性名来使用addr # addr.city / addr.country / addr.province 使用 product() 扁平化多层嵌套循环 product() 接收多个可迭代对象作为参数然后根据他们的笛卡尔积不断生成结果
from itertools import productprint(list(product([1,2],[3,4])))----------------------------------------[(1, 3), (1, 4), (2, 3), (2, 4)] # 常用多层嵌套循环def find_twelve(nem_list1, num_list2, num_list3): 从这三个数字列表中寻找是否存在和为12的3个数 for num1 in num_list1: for num2 in num_list2: for num3 in num_list3: if num1 num2 num3 12: return num1, num2, num3# 使用product()扁平化多层嵌套循环from itertools import productdef find_tewlve_v2(num_list1, num_list2, num_list3): for num1, num2, num3 in product(num_list1, num_list2, num_list3): if num1 num2 num3 12: return num1, num2, num3 使用 islice 实现循环内隔行处理 需求有一个文件隔行读取文件中的内容。 # 方法1使用enumeratedef parse_titles(filename): 从各行数据文件中取数据 with open(filename, r) as fp: for i, line in enumerate(fp): if i % 2 0: yield lineif __name__ __main__: message_generator parse_titles(logs.txt) while True: try: print(next(message_generator)) except StopIteration as e: break 但如果需求变更为每隔3行读取或者每隔4行读取那我们按照以上的写法应该怎么筛选呢 # 方法2使用islicefrom itertools import islicedef parse_titles_v2(filename): 使用slice实现隔行取值 with open(filename, r) as fp: for line in islice(fp, 0, None, 2): # islice(seq, start, end, step) yield lineif __name__ __main__: message_generator parse_titles_v2(logs.txt) while True: try: print(next(message_generator)) except StopIteration as e: break 如果需求变更为每隔3行读取或者每隔4行读取我们只需要将 islice(seq, start, end, step) 中的 step 改成3或者4就行了 Python基础四十问
面对洋洋洒洒的知识点我往往 “一看就会一写就废”为了更有针对性的加深知识点的印象接下来我将以做题的形式继续总结Python系列如果有不正确的地方希望各位佬儿哥指正纠偏
1.列表的增删查改 增 l.insert(idx, value) ---指定索引位置增加 l.append(value) ---在末尾追加 l.extend(iterable) ---取出可迭代对象的值追加到列表末尾 l1 [1,2,3,3,4,5]l1.extend([1,[2]])print(l1)--------------------------[1, 2, 3, 3, 4, 5, 1, [2]] 删 del l[idx] ---删除索引处元素索引超出会报错IndexError: list assignment index out of range del l ---彻底删除列表 l.pop(idx) ---删除索引处元素索引超出会报错IndexError: pop index out of range l.pop() ---删除列表最后一个元素列表为空会报错IndexError: pop from empty list l.remove(value) ---删除列表中第一个出现 value 的元素值不在会报错ValueError: list.remove(x): x not in list l.clear() --清除列表中的所有元素 查 l[idx] l.count(value) ---统计列表中指定元素出现次数指定元素不在列表中会返回0 l.index(value) ---返回列表中第一个指定元素的索引指定元素不在列表中会报错ValueError: 11 is not in list 改 l[idx] value
2.字典的增删查改 增 d[new_key] value ---如果 key 已存在则是更新操作 d.update({key: value}) ---如果 key 存在则是更新操作 d dict.fromkeys(keys, value) ---dict.fromkeys(keys, value) 方法用于创建一个新字典其中包含指定的键并将所有键的值设置为相同的值 d.setdefault(key, default_value) ---如果 key 已存在则返回对应的 value若 key 不存在则返回 default_value并在原字典中新增键值对 key: default_value # 可用setdefault()统计每个单词的出现次数text Hello world! Hello python! Hello chatbot!word_list text.split()word_count {}for word in word_list:word_count[word] word_count.setdefault(word, 0) 1print(word_count)--------------------------------------------------------------------------------------------{Hello: 3, world!: 1, python!: 1, chatbot!: 1} 删 d.pop(key) ---key 不存在会报错KeyError: addr d.popitem() ---随机删除一个键值对因为字典无序所以是随机删除字典为空则报错KeyError: popitem(): dictionary is empty del d[key] ---删除指定 key若 key 不存在则报错KeyError: addr del d ---彻底删除字典 d.clear ---清空字典 查 d[key] ---若 key 不存在则报错KeyError: addr d.get(key) ---若 key 不存在则返回 None d.keys() ---以列表形式返回字典的所有 key d.values() ---以列表的形式返回字典的所有 value d.items() --以列表的形式返回字典的所有键值对每一组键值对是一组元祖 d1 {name: Tom, age: 25}print(d1.keys())print(type(d1.keys()))print()print(d1.values())print(type(d1.values()))print()print(d1.items())print(type(d1.items()))------------------------------------------------dict_keys([name, age])class dict_keys dict_values([Tom, 25]) class dict_values dict_items([(name, Tom), (age, 25)]) class dict_items 改
d[key] value d1.update(d2) ---将 d2 更新到 d1 中相同的 key 则更改 d1 中的 value
3.元祖的增删查改 增
因为元祖是不可变数据类型所以不能不能在原元祖新增
t (1,2,hello)t2 (2,3,world)print(id(t))t t2print(t)print(id(t))-------------------------2049302192960(1, 2, hello, 2, 3, world)2049302145920 删
del t ---不能 del t[idx]否则报错TypeError: tuple object doesnt support item deletion 查
t[idx] ---idx 不能越界否则报错IndexError: tuple index out of range 可遍历元祖 for _ in t: print(_)
t.count(value) ---返回元祖中 value 的个数value 不存在返回 0 t.index(value) ---返回元祖中首个 value 的索引value 不存在则报错ValueError: tuple.index(x): x not in tuple 改
元组是不可变的因此不能修改元组中的任何元素。
4.例举Python6种基本的数据类型并标出哪些是不可变数据类型
整形-int-不可变、浮点型-float-不可变、字符型-str-不可变、列表-list-可变、元祖-tuple-不可变、字典-dict-可变
5.请说明循环结构和异常处理中的 else 在什么情况下会执行
在 for.else 循环结构中当循环提全部循环完毕后没有 break 或者 return 的情况下会执行 else 代码段 在异常处理中try 下的代码段没有出现异常的情况下会执行 else 代码 条件分支语句用 else 来表示否则执行某件事 6.列举python函数定义中有哪些不同的参数类型
1.位置参数根据参数在函数定义中的位置来确定。 2.默认参数在函数定义中指定的参数值。 3.关键字参数在调用函数时指定参数名称和对应的值。 4.星号参数在函数定义中使用来捕获剩余的参数。 5.双星号参数在函数定义中使用* 来捕获剩余的关键字参数。
7.python中和is的区别
比较的是两个对象的值is 比较的是两个对象的内存地址。 不能用 is 替代仅当你需要判断某个对象是否是 None、False、True 时使用 is其他情况下请使用。
a [1,2,3]b [1,2,3]print(id(a))print(id(b))print(a b)print(a is b)--------------------22782856545922278285654272TrueFalse
a [1,2,3]b aprint(id(a))print(id(b))print(a b)print(a is b)---------------------20215765550722021576555072TrueTrue 额外关于赋值或者复制后 id() 是否异同的知识点结论除了赋值其余的 id() 都不一样直接举例 import copya [1,2,3]b ac a.copy()d copy.copy(a)e copy.deepcopy(a)f a[:]print(id(a))print(id(b))print(id(c))print(id(d))print(id(e))print(id(f))------------------192714345516819271434551681927140937408192714093715219271435578241927143558528
8.请描述global关键字在什么条件下必须被使用
在函数局部要重新赋值全局变量之前需要使用 global 关键字声明全局变量。
9.请说明if name main:语句的作用
在 Python 中当一个模块被执行时if name main:语句块会被执行。此语句块可以用来测试模块的代码而不会影响模块的其他功能。 如果模块被其他模块导入则name的值为该模块的名称而不是main。如果该模块是主程序则name的值为main此时该语句块会被执行。 这样的语句使得可以在模块被其他模块导入时忽略测试代码并且只在模块被独立运行时执行测试代码。
10.面向对象编程有哪三大特性请说明各个特性的意义。
封装隐藏内部状态和实现细节仅提供必要的接口给外部使用。 继承允许创建新的对象类型并基于现有的对象类型派生从而继承其行为和状态。 多态允许不同类型的对象对相同消息做出不同的响应。
11.类反射中常用的方法及含义
常用的类反射方法有
type(object)获取对象的类型返回一个 type 对象。 isinstance(object, classinfo)判断对象是否是某种类型的实例返回布尔值。 issubclass(class, classinfo)判断一个类是否是另一个类的子类返回布尔值。 getattr(object, name[, default])获取对象的属性或方法如果不存在可以返回 default 参数指定的默认值。 hasattr(object, name)判断对象是否具有某个属性或方法返回布尔值。 setattr(object, name, value)设置对象的属性值。 delattr(object, name)删除对象的属性。 使用类反射可以动态地获取和操作类的信息是动态语言的重要特性。
12.python中创建一个新线程有哪几种方式
1.使用 threading 模块通过定义一个继承自 Thread 的类并重写其 run 方法然后通过该类的实例调用 start 方法启动线程。 2.使用 multiprocessing 模块通过使用 Process 类创建新的进程。 3.使用协程通过使用生成器实现协程在协程内部通过 yield 实现非阻塞的多任务执行。 多线程编程是高并发编程的一种常见形式可以提高程序的执行效率。
13.python中GIL全局解释器锁在什么情况下会被释放
Python 中的 GIL (Global Interpreter Lock) 是一种机制它限制任意时刻仅有一个线程可以运行在 Python 解释器中。GIL 在以下情况下会被释放 解释器在执行 CPU 密集型任务时例如运算在这种情况下GIL 会每隔一定时间被释放以便其他线程有机会被调度执行。 解释器在执行 I/O 密集型任务时例如读取文件在这种情况下由于 I/O 操作需要等待外部设备所以 GIL 会在 I/O 操作期间被释放。 GIL 可能会影响多线程程序的性能因此通常不建议在 Python 中开发 CPU 密集型的多线程程序。可以使用多进程来代替多线程以提高性能。
14.描述编写装饰器的原则是什么
1.不改变原函数的内部逻辑 2.不改变原函数的调用方法
15.现在有一个Animal类有初始化方法定义如下
class Animal: def init(self, skin, legs): self.skin skin self.legs legs
如果现在想定义一个Dog类并继承于这个Animal类并想给这个Dog类增加一个nickname对象属性Dog类的初始化方法应该怎么定义才能保证 Dog 类和其父类均能初始化成功 # 两种写法第二种以Cat举例class Animal: def __init__(self, skin, legs): self.skin skin self.legs legsclass Dog(Animal): def __init__(self, skin, legs, nickname): super().__init__(skin, legs) self.nickname nicknameclass Cat(Animal): def __init__(self, skin, legs, hobby): Animal.__init__(self, skin, legs) self.hobby hobbya Animal(skinsss, legslll)d Dog(skinsss, legslll, nicknamennn)c Cat(skinsss, legslll, hobbyhhh)print(a.skin)print(d.nickname)print(c.hobby)print(c.skin)----------------------------------------------------------------------sssnnnhhhsss super 方法是 Python 中的一种特殊方法用于引用父类。它常用于多重继承当子类需要调用父类的方法时就可以使用 super 方法。这个方法可以直接调用父类的方法而无需显式命名父类名称。 16.文件zen.txt中保存着python之禅请使用python代码统计该文件中每个单词出现的次数。 file_path rC:\Users\EDZ\Desktop\zen.txtwith open(file_path, r) as f: text f.read()words text.split()word_counts {}for word in words: if word in word_counts: word_counts[word] 1 else: word_counts[word] 1print(word_counts)
17.编写一个装饰器使用该装饰器能够显示任意函数运行所需时间。 def running_time(fun): def wrapper(*args, **kwargs): start_time time.time() result fun(*args, **kwargs) end_time time.time() print(f{fun.__name__}运行花费了{end_time-start_time:.2f} 秒。) return result return wrapperrunning_timedef take_time(): time.sleep(2)take_time()----------------------------------------------------take_time运行花费了2.01 秒。
18.用两种方法合并下面列表
x [a, b]y [c, d, e]x.extend(y)# 或x y
19.计算得到列表当中长度最长的字符串words [Python, is, awesome] words [Python, is, awesome]# 我的笨方法s for _ in words: if len(_) len(s): s _print(s)# 标答给的方法 # 使用内置函数 max() 和 len() 计算在 max() 函数中使用 key 参数指定了用于比较大小的函数为 len()这样比较的就是字符串的长度而不是字典序。longest_word max(words, keylen)print(longest_word)
20.将列表中的顺序倒转 (2 种方法) words [Python, is, awesome]
words [Python, is, awesome]# 方法1列表的reverse()方法(改变原列表)words.reverse()print(words)# 方法2列表切片生成新列表原列表不变w words[::-1]print(w)
21.将字典当中的键值对位置调换
staff {Data Scientist: Mike, Django Developer: Dylan}
答 staff {Data Scientist: Mike, Django Developer: Dylan}# 我的笨方法reverse {}for k, v in staff.items(): reverse[v] kprint(reverse)# 标答给的方法字典推导式inverted_staff {v: k for k, v in staff.items()}print(inverted_staff)
22.将嵌套列表合并为一个列表
l [[1, 2, 3], [4, 5], [6], [7, 8], [9]]
答 # 针对此题目我想到的是循环遍历result []for i in l: for n in i: result.append(n)print(result)# 标答给的方法1 # 在 sum() 函数中使用的第二个参数是空列表表示从空列表开始计算和。merged_list sum(l, [])print(merged_list) # 标答给的方法2列表推导式merged_list [item for sublist in l for item in sublist]print(merged_list)# 可如上3个方法只能针对此题目一旦题目列表没这么规范比如下面的列表那么如上3个方法就无法实现l [0, [1, 2, [3]], [4, 5], [6], [7, 8], [9]]# 能够同时解决如上问题的方法是使用递归函数def flatten_list(l): flat_list [] for item in l: if type(item) list: flat_list.extend(flatten_list(item)) else: flat_list.append(item) return flat_listprint(flatten_list(l))
23.列表当中数据类型的转换 我们要将其转换成整数类型[1, 2, 3] 我们要将其转换成浮点数类型[1, 2, 3.0, 4.0, 5, 6]
答
l [1, 2, 3]l1 [int(i) for i in l]print(l1)l2 [1, 2, 3.0, 4.0, 5, 6]l3 [float(i) for i in l2]print(l3)
24.将列表转化成字典
cars [Audi, BMW, Ford, Tesla, Volvo]
答
cars [Audi, BMW, Ford, Tesla, Volvo]d dict.fromkeys(cars, 0)print(d)
25.将列表当中的重复元素去除
[a, a, b, a, c]
答
l [a, a, b, a, c]l1 list(set(l))print(l1)
26.从列表中筛选出特定元素 (2种方法)
cars [Audi, BMW, Ford, Tesla, Volvo]
答
cars [Audi, BMW, Ford, Tesla, Volvo]# 我想到的是列表推导式l [i for i in cars if i Volvo]print(l)# 标答使用filterl2 filter(lambda car: car Volvo, cars)print(list(l2))# filter 函数在 Python 中返回一个过滤器对象它是一个迭代器所以想打印值需要使用list()
27.列表中的元素排序
numbers [55, -30, 28, -36, 48, 20] cars [Ford, Tesla, BMW, Volvo, Audi]
答
numbers.sort()print(numbers)cars.sort()print(cars)
28.合并集合
set1 {1, 2, 5} set2 {4, 6, 7}
答
set1.update(set2)print(set1)
29.根据键来对字典进行排序
d {one: 1, three: 4, five: 8, six: 10, two: 2}
答
sorted_dict sorted(d.items(), keylambda x: x[0])print(sorted_dict)
30.根据键值来对字典进行排序
d {one: 1, three: 4, five: 8, six: 10, two: 2}
答
sorted_dict sorted(d.items(), keylambda x: x[1])print(sorted_dict)
31.替换字符串
s Python is a programming language. Python is awesome# 字符类型是不可变数据类型str.replace()方法不会改变原字符串会生成新值ss s.replace(P,p)print(ss)
32.计算指定字符串出现的次数
a python is a programming language. python is python.
答 # 我得笨方法d {}for _ in a: if _ not in d: d[_] 1 else: d[_] 1print(d[p])# 标答print(a.count(p))
33.将矩阵转置
a [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
答
b [list(s) for s in zip(*a)]print(b)
34.生成斐波那契数列
斐波那契数列是一个数列其中的每个数都是前两个数的和。
答 def fibonacci(n): if n 0: return [] elif n 1: return [0, ] elif n 2: return [0, 1] else: fib [0, 1] for i in range(2, n): fib.append(fib[-1] fib[-2]) return fibprint(fibonacci(10))-----------------------------------------------------[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
35.冒泡排序 def bubble(l): for i in range(len(l) - 1): for j in range(len(l) - 1 - i): if l[j] l[j 1]: l[j], l[j 1] l[j 1], l[j] return l
36.Python的解包是什么
解包是 Python 里的一种特殊赋值语句可以把可迭代对象 (列表元祖字典字符串) 一次性赋给多个值。
a, b, c (1, 2, 3)
a, b b, a numbers [1, 2, 3, 4, 5]for a, b in zip(numbers, numbers[1:]): print(a, b)---------------------------------------------------------1 22 33 44 5
注意 普通变量解包需要注意变量数量和列表中元素数量应保持一致否则报SyntaxError: cannot assign to literal 如果可迭代对象是字典则变量个数要等于字典中的键值对个数若不指定字典的取值则默认取字典的 key 值若指定字典的值为 items()则变量为字典键值对的元组形式
37.有一个key为姓名value为年龄的字典根据年龄正序排列姓名并输出姓名列表若没有年龄则放在最后
users {tom: 19, jerry: 13, jack: None, andrew: 43}
答 知识点在排序前将年龄为 None 的值变更为正无穷大 正无穷float(inf) 负无穷float(-inf) # 我想到的方法 # 先将字典中年龄为None的值变更成正无穷大def key_func(users): for key in users.keys(): if users[key] is None: users[key] float(inf)# 根据年龄进行正序排序最后以列表形式输入排序好的姓名def sort_user(user: dict): sort_item_for_v sorted(user.items(), keylambda x: x[1]) return [user[0] for user in sort_item_for_v]key_func(users)print(sort_user(users))-------------------------------------------------------------------------------[jerry, tom, andrew, jack] # 参考答案def sort_user_inf(users: dict): 接收一个key为姓名value为年龄的字典根据年龄正序排列姓名若没有年龄则放在最后 :param users: 用户名年龄字典 :return: 返回姓名列表 def key_func(username): age users[username] # 当年龄为空时返回正无穷大作为key因此就会被排到最后 return age if age is not None else float(inf) return sorted(users.keys(), keykey_func)print(sort_user_inf(users))-----------------------------------------------------------------------------[jerry, tom, andrew, jack]
38.合并字典的多种方式 方式 1update
d1 {name: Lili, score: 90}d2 {name: Tom, hobby: run}d1.update(d2)print(d1)-----------------------------{name: Tom, score: 90, hobby: run}# 这种方法会改变d1的原始值 方式 2编写一个函数 (不改变 d1 的原始值) d1 {name: Lili, score: 90}d2 {name: Tom, hobby: run}def update_dict(d1: dict, d2: dict): d d1.copy() d.update(d2) return dprint(update_dict(d1,d2))print(d1)print(d2)---------------------------------------{name: Tom, score: 90, hobby: run}{name: Lili, score: 90}{name: Tom, hobby: run} 方式 3解包
d1 {name: Lili, score: 90}d2 {name: Tom, hobby: run}print({**d1, **d2})print({**d2, **d1})print(d1)print(d2)--------------------------------------{name: Tom, score: 90, hobby: run}{name: Lili, hobby: run, score: 90}{name: Lili, score: 90}{name: Tom, hobby: run} 方式 4Python3.9 版本后可用|合并字典
d1 {name: Lili, score: 90}d2 {name: Tom, hobby: run}print(d1|d2)print(d2|d1)print(d1)print(d2)-----------------------------{name: Tom, score: 90, hobby: run}{name: Lili, hobby: run, score: 90}{name: Lili, score: 90}{name: Tom, hobby: run}
39.json和Python中的dict有什么区别 1.JSON 的类型是字符串字典的类型是 dict 2.JSON 的 key 只能是字符串字典的 key 可以是任何可 hash 对象如字符串数字元祖 3.JSON 的 key 是有序的可以重复的字典的 key 不能重复 4.JSON 的 key 有默认值 undefined字典的 key 默认没有默认值 5.JSON 的 value 可以是字符串、浮点数、布尔值、null 或者他们组成的数组或对象字典的 value 可以是任意类型的对象 6.JSON 的 value 访问方式可以是 [] 或者.字典的 value 访问方式只能是 key 值 7.JSON 的字符串强制使用双引号字典的字符串可以是单引号也可以是双引号 8.字典可以嵌套元祖JSON 只有数组 9.真假空的表示JSONtruefalsenull字典TrueFalseNone 10.JSON 的中文必须是 Unicode 编码如\u6211。
40.Python列表和字符串的相互转换
第一种类型
s 1,2,3,4,5l s.split(,)print(l)l2 [int(i) for i in l]print(l2)--------------------[1, 2, 3, 4, 5][1, 2, 3, 4, 5]
第二种类型
l1 [1,2,3]s1 ,.join(l1)print(s1)---------------1,2,3
第三种类型
l2 [1,2,3]s2 ,.join([str(i) for i in l2])print(s2)-----------------------------1,2,3行动吧在路上总比一直观望的要好未来的你肯定会感 谢现在拼搏的自己如果想学习提升找不到资料没人答疑解惑时请及时加入扣群 320231853里面有各种软件测试开发资料和技术可以一起交流学习哦。
最后感谢每一个认真阅读我文章的人礼尚往来总是要有的虽然不是什么很值钱的东西如果你用得到的话可以直接拿走
这些资料对于【软件测试】的朋友来说应该是最全面最完整的备战仓库这个仓库也陪伴上万个测试工程师们走过最艰难的路程希望也能帮助到你