测试工程师面试题-Python基础面试题

Q:pytest失败重试

@pytest.mark.flaky(reruns=1)
pytest test_se.py --reruns 2  --reruns-delay=2
#失败重跑2次,在每次开跑前会等待2s

Q:pytest并发

pytest-xdist支持并发执行

Q:flask原理

在run.py文件中,定义了项目启动的入口函数,启动端口,Flask使用的底层WSGI库,进行路由分发
在Flask中,浏览器发送一个请求的流程后,WGSI服务器接收浏览器的HTTP请求、向浏览器发送HTTP应答,然后通过调用WSGI应用程序,针对HTTP请求的具体处理逻辑由哪个业务逻辑函数来处理,然后在函数中进行操作,取得所需的数据。再将取得的数据传给相应的模板文件中,由Jinja2负责渲染得到HTTP响应内容,即HTTP响应的HTML文件,然后由WGSI服务器返回响应内容

Q:logging模块-等级

FATAL:致命错误
CRITICAL:特别糟糕的事情,如内存耗尽、磁盘空间为空,一般很少使用
ERROR:发生错误时,如IO操作失败或者连接问题
WARNING:发生很重要的事件,但是并不是错误时,如用户登录密码错误
INFO:处理请求或者状态变化等日常事务
DEBUG:调试过程中使用DEBUG等级,如算法中每个循环的中间状态

Q:pytest参数化

通过装饰器@pytest.mark.parametrize来实现

Q:json.dumps()和dump()、json.loads()和load()的区别

主要区别:
1、dump(),load() 处理的是json文件
2、dumps(),loads() 处理的是字符串

Q:正则表达式中-贪婪模式和非贪婪模式的区别

贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配. ‘.
而非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配。 ‘.
?’

Q:readline和readlines区别

read()方法:
1、读取整个文件,将文件内容放到一个字符串变量中
2、如果文件大于可用内存,不可能使用这种处理
readline()方法:
1、readline()每次读取一行,比readlines()慢得多
2、readline()返回的是一个字符串对象,保存当前行的内容
readlines()方法:
1、一次性读取整个文件
2、自动将文件内容分析成一个行的列表

Q:Python ⾥ is 和 == 的区别?

https://www.cnblogs.com/wangkun122/p/9082088.html
Python中对象包含的三个基本要素,分别是:id(身份标识)、type(数据类型)和value(值)。
is== 都是对对象进行比较判断作用的,但对对象比较判断的内容并不相同。

下面来看看具体区别:
is 被叫做同一性运算符,这个运算符比较判断的是对象间的唯一身份标识,也就是id是否相同
== 是python标准操作符中的比较操作符,用来比较判断两个对象的value(值)是否相等

Q:python中列表和元组的区别

相同点:
List 与 tuple 都是序列类型的容器对象,可以存放任何类型的数据、支持切片、迭代等操作
不同点:
1、最重要的一点是tuple是不可变类型,大小固定,而 list 是可变类型、数据可以动态变化。
2、tuple比列表操作速度快
3、tuple对数据"写保护"
4、tuple可用于字符串格式化中
5、tuple可作为字典的key

Dict底层使用的哈希表,为了支持快速查找使用了哈希表作为底层结构,哈希表平均查找时间复杂度为O(1)。

Q:python中遍历list和dict哪个速度更快?

遍历dict会更快,这种效率的差异是由于二者的存储结构不同.
list查找时,需要遍历,这与其线性的存储结构有关,因此数据量大时,就显得慢了.且处于list中越靠后,查询越慢;不在list中,更需遍历所有元素,速度最慢.
而dict默认采用hash_map存储,即使数据量很大,查找也非常快速.

Q:args和*kwargs区别

*args是可变参数,args接收的是一个tuple;
定义:可变参数就是传入的参数个数是可变的,可以是0个,1个,2个,……很多个。

**kw是关键字参数,kw接收的是一个dict。
定义:关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。在调用函数时,可以只传入必选参数。

Q:深拷⻉浅拷⻉的区别是什么?

浅拷贝会创建一个新的对象,但是,对于对象中的元素,浅拷贝就只会使用原始元素的引用(内存地址);
深拷贝也会创建一个新的对象,但是,对于对象中的元素,深拷贝都会重新生成一份,而不是简单的使用原始元素的引用(内存地址)

  • Python中对象的赋值都是进行对象引用(内存地址)传递
  • 使用copy.copy(),可以进行对象的浅拷贝,它复制了对象,但对于对象中的元素,依然使用原始的引用.
  • 如果需要复制一个容器对象,以及它里面的所有元素(包含元素的子元素),可以使用copy.deepcopy()进行深拷贝
  • 对于非容器类型(如数字、字符串、和其他’原子’类型的对象)没有被拷贝一说
  • 如果元祖变量只包含原子类型对象,则不能深拷贝,看下面的例子

Q:@classmethod 和 @staticmethod 的区别,以及分别运⽤在哪些使用场景?

https://blog.csdn.net/kaever/article/details/105808768
声明时:
@classmethod 的第一个参数为类本身,正如实例方法的第一个参数为对象本身(self)
@staticmethod 的第一个参数不需要传入self,故在@staticmethod无法访问类和对象的数据的。
调用时:都可以使用类名直接调用,也可以用实例对象调用。

总结
1.使用@staticmethod目的之一是为了增加可读性,不需要参数self的方法都可以加上@staticmethod增加可读性,因为,这个方法是类级别的,在调用时要使用类名。
2.使用@classmethod是为了处理一些init处理不了的赋值问题(一般是参数不对应),你可以当成有第二,第三个init方法,当然它要通过类名显示调用。

Q:lambda 函数怎么⽤?

https://www.cnblogs.com/huangbiquan/p/8030298.html
lambda语句构建的其实是一个函数对象。匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。
lambda优点:
1、使用Python写一些执行脚本时,使用lambda可以省去定义函数的过程,让代码更加精简。
2、对于一些抽象的,不会别的地方再复用的函数,使用lambda不需要考虑命名的问题。
3、使用lambda在某些时候让代码更容易理解。

f=lambda x,n:x ** n

Q:什么是可迭代对象?可迭代对象的原理是什么?

Python中可迭代对象(Iterable)并不是指某种具体的数据类型,它是指存储了元素的一个容器对象,且容器中的元素可以通过iter( )方法或getitem( )方法访问。

iter方法的作用是让对象可以用for … in循环遍历,getitem( )方法是让对象可以通过“实例名[index]”的方式访问实例中的元素。老猿认为这两个方法的目的是Python实现一个通用的外部可以访问可迭代对象内部数据的接口。
一个可迭代对象是不能独立进行迭代的,Python中,迭代是通过for … in来完成的。凡是可迭代对象都可以直接用for… in…循环访问,这个语句其实做了两件事:第一件事是调用iter()获得一个可迭代器,第二件事是循环调用next()。

常见的可迭代对象包括:
a) 集合数据类型,如list、tuple、dict、set、str等;
b) 生成器(generator),包括生成器和带yield的生成器函数(generator function).

如何判断一个对象是可迭代对象呢?可以通过collections模块的Iterable类型判断,具体判断方法如下:

from collections import Iterable #导入Iterable 模块
isinstance(变量, Iterable) #判断一个变量是否为可迭代对象返回True表明是可迭代对象

Q:在Python中使用过什么代码检查工具?

1)PyFlakes:静态检查Python代码逻辑错误的工具。
2)Pep8: 静态检查PEP8编码风格的工具。
3)NedBatchelder’s McCabe script:静态分析Python代码复杂度的工具。
Python代码分析工具:PyChecker、Pylint

Q:newinit的区别

创建一个新实例时调用new,初始化一个实例时用init,这是它们最本质的区别。
new方法会返回所构造的对象,init则不会.new函数必须以cls作为第一个参数,而init则以self作为其第一个参数.

Q:函数装饰器的作用

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。有了装饰器,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用

Q:如何捕获异常,常用的异常机制

如果我们没有对异常进行任何预防,那么在程序执行的过程中发生异常,就会中断程序,调用python默认的异常处理器,并在终端输出异常信息。

Try…except…finally语句:当try语句执行时发生异常,回到try语句层,寻找后面是否有except语句。找到except语句后,会调用这个自定义的异常处理器。except将异常处理完毕后,程序继续往下执行。finally语句表示,无论异常发生与否,finally中的语句都要执行。

Assert语句:判断assert后面紧跟的语句是True还是False,如果是True则继续执行print,如果是False则中断程序,调用默认的异常处理器,同时输出assert语句逗号后面的提示信息。

With语句:如果with语句或语句块中发生异常,会调用默认的异常处理器处理,但文件还是会正常关闭。

Q:Python的作用域以及Python搜索变量的顺序

Python作用域简单说就是一个变量的命名空间,代码中变量被赋值的位置,就决定了哪些范围的对象可以访问这个变量,这个范围就是变量的作用域。
在python中,只有模块,类,函数才会引入新的作用域。
Python的变量名解析机制也称为LEGB法则:本地作用域->全局/模块作用域->内置作用域

Q:Python 变量的创建与消亡过程,垃圾回收机制。

https://blog.csdn.net/reasonyuanrobot/article/details/83793511
python内部使用引用计数,来保持追踪内存中的对象。
python内部记录了对象有多少引用,即引用计数,当对象被创建时就创建了一个引用计数,当对象不在需要时,这个对象的引用计数为0时,它被垃圾回收,然后清除其在内存的空间。当然除了引用计数为0的会被清除,还有一种情况也会被垃圾收集器清掉:当两个对象相互引用时,他们本身其他的引用已经为0了.
垃圾回收机制还有一个 循环垃圾回收器 ,确保释放循环引用对象。
在python中,许多时候申请的内存都是小块的内存,这些小块内存在申请后,很快又会被释放,由于这些内存的申请并不是为了创建对象,所以并没有对象一级的内存池机制。
这就意味着python在运行期间会大量的执行malloc(动态内存分配)和free(释放内存)的操作,频繁的在用户态和核心态之间进行切换,这将严重影响python的执行效率。为了加速python的执行效率,python引入一个内存池机制,用于管理对小块内存的申请和释放。

Q:Python如何进行内存管理

1)对象的引用计数机制
Python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数。
引用计数增加的情况:
一个对象分配一个新名称
将其放入一个容器中(如列表、元组或字典)
引用计数减少的情况:
使用del语句对对象别名显示的销毁
引用超出作用域或被重新赋值
2)垃圾回收
当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。
3)内存池机制
Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。
Pymalloc机制:为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。
对于Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。

Q:为什么会出现死锁?

所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。

产生死锁的原因可归结为如下两点:

  • a. 竞争资源
  • b. 进程间推进顺序非法

Q:多线程的实现方式?线程和进程的区别?

线程是指进程内的一个执行单元,也是进程内的可调度实体.
进程是资源分配的最小单位,线程是程序执行的最小单位.
与进程的区别:
(1) 地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间;
(2) 资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
(3) 线程是处理器调度的基本单位,但进程不是
(4) 二者均可并发执行

python主要是通过thread和threading这两个模块来实现多线程支持。python的thread模块是比较底层的模块,python的threading模块是对thread做了一些封装,可以更加方便的被使用。

threading.Thread(Target=executable Method)

Q:如何结束一个进程?

(1)调用terminate方法。
(2)使用subProcess模块的Popen方法。

Q:什么是虚拟内存?

虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。与没有使用虚拟内存技术的系统相比,使用这种技术的系统使得大型程序的编写变得更容易,对真正的物理内存(例如RAM)的使用也更有效率。

Q:多态怎么体现的

多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。综上可以说,多态性是 : 一个接口,多种实现

多态性的好处:
增加了程序的灵活性,以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(obj)
增加了程序额可扩展性,通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(obj)去调用

Q:面向对象里面重写和重载的区别

多态:允许不同类的对象对同一消息做出响应。即同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。这也意味着一个对象有着多重特征,可以在特定的情况下,表现不同的状态,从而对应着不同的属性和方法。
多态的实现方式:接口实现,继承父类进行方法重写,同一个类中进行方法重载。
方法重载(Overloading):一个类中有多个方法(函数),它们具有相同的名字,但方法传递的参数或参数的个数不同,返回类型可以相同。
方法重写(Override): 子类对父类的方法做一定的修改,返回值和形参都不能改变。又称方法覆盖。

虚拟内存有以下两个优点:
1.虚拟内存地址空间是连续的,没有碎片
2.虚拟内存的最大空间就是cup的最大寻址空间,不受内存大小的限制,能提供比内存更大的地址空间

Q:找到100亿个URL中重复的URL?

由于数据量很大,16*100亿B = 1600亿Byte,约等于160G。10亿Byte约等于1G大小。这种题目都是有数据资源限制的。如果说机器内存只有16G,那我们可以通过Hash算法,把原始大文件,hash分成10个小文件。或者hash成更多更小的文件,以满足机器资源限制。因为通过hash,我们可以保证相同的URL一定可以被分配到相同的小文件上。然后从每个文件里统计计算每个URL出现就可以了,可以使用hashMap存放统计结果。

Q:python第三方的库有哪些

Faker: 创建伪数据
Pandas: Python数据分析高层次应用库
Pytest: 单元测试框架
Flask: web微框架
PyYAML:解析yaml文件
Simplejson:解析json文件
Requests:Apache2 Licensed开源协议的HTTP库
Beautiful Soup: HTML和XML的解析库
Re: 正则表达式解析和处理功能库

Q:HashMap和HashTable,以及ConCurrentHashMap,区别原理?

HashTable
底层数组+链表实现,无论key还是value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低,ConcurrentHashMap做了相关优化
初始size为11,扩容:newsize = olesize2+1
计算index的方法:index = (hash & 0x7FFFFFFF) % tab.length
HashMap
底层数组+链表实现,可以存储null键和null值,线程不安全
初始size为16,扩容:newsize = oldsize
2,size一定为2的n次幂
扩容针对整个Map,每次扩容时,原来数组中的元素依次重新计算存放位置,并重新插入.
插入元素后才判断该不该扩容,有可能无效扩容(插入后如果扩容,如果没有再次插入,就会产生无效扩容)
当Map中元素总数超过Entry数组的75%,触发扩容操作,为了减少链表长度,元素分配更均匀
计算index方法:index = hash & (tab.length – 1)
ConcurrentHashMap
底层采用分段的数组+链表实现,线程安全
通过把整个Map分为N个Segment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。(读操作不加锁,由于HashEntry的value变量是 volatile的,也能保证读取到最新的值。)
Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术
有些方法需要跨段,比如size()和containsValue(),它们可能需要锁定整个表而而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁
扩容:段内扩容(段内元素超过该段对应Entry数组长度的75%触发扩容,不会对整个Map进行扩容),插入前检测需不需要扩容,有效避免无效扩容

ConcurrentHashMap提供了与Hashtable和SynchronizedMap不同的锁机制。Hashtable中采用的锁机制是一次锁住整个hash表,从而在同一时刻只能由一个线程对其进行操作;而ConcurrentHashMap中则是一次锁住一个桶。
ConcurrentHashMap默认将hash表分为16个桶,诸如get、put、remove等常用操作只锁住当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容