软件测试面试必问的Python问题

本文转载自霍格沃兹测试学院优秀学员ling_tianxia的学习笔记,原文链接:
http://qrcode.testing-studio.com/f?from=csdn2&url=https://ceshiren.com/tag/%E7%B2%BE%E5%8D%8E%E5%B8%96 转载请注明出处

- 语言特性

1.谈谈对Python和其他语言的区别
答:Python是一门语法简洁优美, 功能强大无比, 应用领域非常广泛, 具有强大完备的第三方库,它是一门强类型的可移植、可扩展、可嵌入的解释型编程语言,属于动态语言。
拿C语言和Python比:Python的第三方类库比较齐全并且使用简洁, 很少代码就能实现一些功能,如果用C去实现相同的功能可能就比较复杂。
但是对于速度来说Python的运行速度相较于C就比较慢了。所以有利的同时也有弊端,毕竟我们的学习成本降低了。

2.简述解释型和编译型编程语言
答:解释型语言是在运行程序的时候才翻译,每执行一次,要翻译一次,效率较低。 编译型就是直接编译成机型可以执行的,只翻译一次,所以效率相对来说较高。

3.Python的解释器种类以及相关特点?
答:CPythonc语言开发的,使用最广的解释器IPython基于cPython之上的一个交互式计时器,交互方式增强功能和cPython一样PyPy目标是执行效率,采用JIT技术。
对Python代码进行动态编译,提高执行效率JPython运行在Java上的解释器,直接把Python代码编译成Java字节码执行IronPython运行在微软.NET平台上的解释器,把Python编译成.NET的字节码。

4.Python3和Python2的区别?
答: 这里例举5条print在Python3中是函数必须加括号,Python2中print为class。Python2中使用xrange,Python3使用range。
Python2中默认的字符串类型默认是ASCII,Python3中默认的字符串类型是Unicode。Python2中 /(除) 的结果是整型,Python3中是浮点类型。
Python2中声明元类:_metaclass_ = MetaClass, Python3中声明元类:class newclass(metaclass=MetaClass):pass。

5.Python3和Python2中int和long区别?
答:Python2有int和long类型。int类型最大值不能超过sys.maxint,而且这个最大值是平台相关的。可以通过在数字的末尾附上一个L来定义长整型,显然,它比int类型表示的数字范围更大。
在Python3里,只有一种整数类型int,大多数情况下,和Python2中的长整型类似。

6.xrange和range的区别?
答:xrange是在Python2中的用法,Python3中只有rangexrange用法与range完全相同,所不同的是生成的不是一个list对象,而是一个生成器。

- 编码规范

7.什么是PEP8?
答:PEP8通常会听别人提到,但是具体的指什么内容呢,简单介绍下。 《PythonEnhancementProposal  # 8》(8 号 Python 增强提案)又叫 PEP8,
他针对的 Python 代码格式而编订的风格指南。

8.了解Python之禅么?
答:通过import this语句可以获取其具体的内容。它告诉大家如何写出高效整洁的代码。

9.了解DocStrings么?
答:DocStrings文档字符串是一个重要工具,用于解释文档程序,帮助你的程序文档更加简单易懂。主要是解释代码作用的。

10.了解类型注解么?
答:PEP484引入了类型提示,这使得可以对Python代码进行静态类型检查。 在使用Ide的时候可以获取到参数的类型,更方便传入参数。使用格式如下
    def foo(num:int) -> None:
        print(f"接收到的数字是:{num}")
介绍下这个简单例子,我们可以在函数的参数部分使用参数名 +:+类型,来指定参数可以接受的类型,这里的话就是num参数为int类型,然后后面->接的是返回值的类型。
这里返回值为None,然后通过fstring格式化字符串输出传入的数字。

11.例举你知道Python对象的命名规范,例如方法或者类等
答:
类:总是使用首字母大写单词串,如MyClass。内部类可以使用额外的前导下划线。
变量:小写,由下划线连接各个单词。方法名类似
常量:常量名所有字母大写等

12.Python中的注释有几种?
答:总体来说分为两种,单行注释和多行注释。单行注释在行首是# 。多行注释可以使用三个单引号或三个双引号,包括要注释的内容。

13.如何优雅的给一个函数加注释?
答:可以使用docstring配合类型注解

14.如何给变量加注释?
答:可以通过变量名:类型的方式如下
    a: str = "this is string type"

15.Python代码缩进中是否支持Tab键和空格混用。
答:不允许tab键和空格键混用,这种现象在使用sublime的时候尤为明显。一般推荐使用4个空格替代tab键。

16.是否可以在一句import 中导入多个库?
答:可以是可以,但是不推荐。因为一次导入多个模块可读性不是很好,所以一行导入一个模块会比较好。同样的尽量少用
from modulename import *,因为判断某个函数或者属性的来源有些困难,不方便调试,可读性也降低了。

17.在给Py文件命名的时候需要注意什么?
答:给文件命名的时候不要和标准库库的一些模块重复,比如abc。 另外要名字要有意义,不建议数字开头或者中文命名。

18.例举几个规范Python代码风格的工具
答:pylint和flake8

- 数据类型 - 字符串

19.列举Python中的基本数据类型?
答: Python3中有六个标准的数据类型:字符串(String)、数字(Digit)、列表(List)、元组(Tuple)、集合(Sets)、字典(Dictionary)。

20.如何区别可变数据类型和不可变数据类型
答: 从对象内存地址方向来说
可变数据类型:在内存地址不变的情况下,值可改变(列表和字典是可变类型,但是字典中的key值必须是不可变类型)
不可变数据类型:内存改变,值也跟着改变。(数字,字符串,布尔类型,都是不可变类型)可以通过id()方法进行内存地址的检测。

21.将"hello world"转换为首字母大写"Hello World"
答: 这个得看清题目是要求两个单词首字母都要大写,如果只是第一个单词首字母大小的话,只使用capitalize即可,但是这里是两个单词,所以用下面的方法。
    arr = "hello world".split(" ")
    new_str = f"{arr[0].capitalize()} {arr[1].capitalize()}"
    print(new_str)
后来评论中有朋友提到了下面的方法,这里感谢这位朋友提醒。方案如下
    "hello world".title()
非常简单一句话搞定。

22.如何检测字符串中只含有数字?
答:可以通过isdigit方法,例子如下
    s1 = "12223".isdigit()
    print(s1)
    s2 = "12223a".isdigit()
    print(s2)
    # 结果如下:
    # True
    # False

23.将字符串"ilovechina"进行反转
答:
    s1 = "ilovechina"[::-1]
    print(s1)

24.Python中的字符串格式化方式你知道哪些?
答: % s,format,fstring(Python3.6开始才支持,现在推荐的写法)

25.有一个字符串开头和末尾都有空格,比如“ adabdw ”,要求写一个函数把这个字符串的前后空格都去掉。
答:因为题目要是写一个函数所以我们不能直接使用strip,不过我们可以把它封装到函数啊
    def strip_function(s1):
        return s1.strip()
    s1 = " adabdw "
    print(strip_function(s1))

26.获取字符串”123456“最后的两个字符。
答:切片使用的考察,最后两个即开始索引是 - 2,代码如下
    a = "123456"
    print(a[-2::])

27.一个编码为GBK的字符串S,要将其转成UTF - 8编码的字符串,应如何操作?
答:
    a = "S".encode("gbk").decode("utf-8", 'ignore')
    print(a)

28.(1)s = "info:xiaoZhang 33 shandong",用正则切分字符串输出['info', 'xiaoZhang', '33', 'shandong']。(2)a = "你好 中国 ",去除多余空格只留一个空格。
答:
(1)我们需要根据冒号或者空格切分
    import re
    s = "info:xiaoZhang 33 shandong"
    res = re.split(r":| ", s)
    print(res)
(2)s = "你好 中国 "
    print(" ".join(s.split()))

29.(1)怎样将字符串转换为小写。 (2)单引号、双引号、三引号的区别?
答:
(1)使用字符串的lower()方法。

(2)单独使用单引号和双引号没什么区别,但是如果引号里面还需要使用引号的时候,就需要这两个配合使用了,
然后说三引号,同样的三引号也分为三单引号和三双引号,两个都可以声名长的字符串时候使用,如果使用docstring就需要使用三双引号。

数据类型 - 列表

30.已知AList = [1, 2, 3, 1, 2],对AList列表元素去重,写出具体过程。
答:list(set(AList))

31.如何实现"1,2,3"变成["1", "2", "3"]
答:
    s = "1,2,3"
    print(s.split(","))

32.给定两个list,A和B,找出相同元素和不同元素
答:
A、B中相同元素:
    print(set(A) & set(B))
A、B中不同元素:
    print(set(A) ^ set(B))

33.[[1, 2], [3, 4], [5, 6]]一行代码展开该列表,得出[1, 2, 3, 4, 5, 6]

答:
    l = [[1, 2], [3, 4], [5, 6]]
    x = [j for i in l for j in i]
    print(x)

34.合并列表[1, 5, 7, 9]和[2, 2, 6, 8]
答:使用extend和 + 都可以。
    a = [1, 5, 7, 9]
    b = [2, 2, 6, 8]
    a.extend(b)
    print(a)

35.如何打乱一个列表的元素?
答:
import random
    a = [1, 2, 3, 4, 5]
    random.shuffle(a)
    print(a)

- 数据类型 - 字典

36.字典操作中del 和pop有什么区别
答:del 可以根据索引(元素所在位置)来删除的,没有返回值。 pop可以根据索引弹出一个值,然后可以接收它的返回值。

37.按照字典的内的年龄排序
    d1 = [
        {'name':'alice', 'age':38},
        {'name':'bob', 'age':18},
        {'name':'Carl', 'age':28},
    ]
答:
    print(sorted(d1, key=lambda x:x["age"]))

38.请合并下面两个字典a = {"A":1, "B":2}, b = {"C":3, "D":4}

答: 合并字典方法很多,可以使用
        a.update(b)
    或者下面字典解包的方式
        a = {"A":1, "B":2}
        b = {"C":3, "D":4}
        print({**a, **b})

39.如何使用生成式的方式生成一个字典,写一段功能代码。
答:# 需求 3: 把字典的 key 和 value 值调换;
    d = {'a':'1', 'b':'2'}
    print({v:k for k, v in d.items()})

40.如何把元组("a", "b")和元组(1, 2),变为字典{"a":1, "b":2}
答: zip的使用,但是最后记得把zip对象再转换为字典。
    a = ("a", "b")
    b = (1, 2)
    print(dict(zip(a, b)))

- 数据类型 - 综合

41.下列字典对象键类型不正确的是?
    A:{1:0, 2:0, 3:0}
    B:{"a":0, "b":0, "c":0}
    C:{(1, 2):0, (2, 3):0}
    D:{[1, 2]:0, [2, 3]:0}
答:D因为只有可hash的对象才能做字典的键,列表是可变类型不是可hash对象,所以不能用列表做为字典的键。

42.如何交换字典{"A":1, "B":2}的键和值
答:s = {"A":1, "B":2}
# 方法一:
    dict_new = {value: key for key,value in s.items()}
# 方法二:
    new_s = dict(zip(s.values(),s.keys()))
43.Python里面如何实现tuple和list的转换?
答: Python中的类型转换,一般通过类型强转即可完成
tuple转list是list()方法
list转tuple使用tuple()方法

44.我们知道对于列表可以使用切片操作进行部分元素的选择,那么如何对生成器类型的对象实现相同的功能呢?
答:这个题目考察了Python标准库的itertools模快的掌握情况,该模块提供了操作生成器的一些方法。 对于生成器类型我们使用islice方法来实现切片的功能。例子如下
    from itertools import islice
    gen = iter(range(10))  # iter()函数用来生成迭代器
    # 第一个参数是迭代器,第二个参数起始索引,第三个参数结束索引,不支持负数索引
    for i in islice(gen, 0, 4):
    print(i)

45.请将[i for i in range(3)] 改成生成器
答:通过把列表生产式的中括号,改为小括号我们就实现了生产器的功能即,
    (i for i in range(3))

46.a = "hello"和b = "你好"编码成bytes类型
答: 这个题目一共三种方式,第一种是在字符串的前面加一个b,第二种可以使用bytes方法,第三种使用字符串encode方法。具体代码如下,
abc代表三种情况
    a = b"hello"
    b = bytes("你好", "utf-8")
    c = "你好".encode("utf-8")
    print(a, b, c)

47.下面的代码输出结果是什么?
    a = (1, 2, 3, [4, 5, 6, 7], 8)
    a[2] = 2
答: 我们知道元组里的元素是不能改变的所以这个题目的答案是出现异常。

48.下面的代码输出的结果是什么?
    a = (1, 2, 3, [4, 5, 6, 7], 8)
    a[3][0] = 2
答:前面我说了元组的里元素是不能改变的,这句话严格来说是不准确的,如果元组里面元素本身就是可变类型,比如列表,那么在操作这个元素里的对象时,其内存地址也是不变的。
a[3]对应的元素是列表,然后对列表第一个元素赋值,所以最后的结果是: (1, 2, 3, [2, 5, 6, 7], 8)

- 操作类题目

49.Python交换两个变量的值
答:在Python中交换两个对象的值通过下面的方式即可
    a, b = b, a
但是需要强调的是这并不是元组解包,通过dis模块可以发现,这是交换操作的字节码是ROT_TWO,意思是在栈的顶端做两个值的互换操作。

50.在读文件操作的时候会使用read、readline或者readlines,简述它们各自的作用
答:
read()每次读取整个文件,它通常用于将文件内容放到一个字符串变量中。如果希望一行一行的输出那么就可以使用readline(),
该方法会把文件的内容加载到内存,所以对于对于大文件的读取操作来说非常的消耗内存资源,此时就可以通过readlines方法,将文件的句柄生成一个生产器,然后去读就可以了。

51.json序列化时,可以处理的数据类型有哪些?如何定制支持datetime类型?
答: 可以处理的数据类型是str、int、list、tuple、dict、bool、None, 因为datetime类不支持json序列化,所以我们对它进行拓展。
    # 自定义时间序列化
    import json
    from datetime import datetime, date

    # JSONEncoder 不知道怎么去把这个数据转换成 json 字符串的时候
    # ,它就会去调 default()函数,所以都是重写这个函数来处理它本身不支持的数据类型,
    # default()函数默#认是直接抛异常的。
    class DateToJson(json.JSONEncoder):
        def default(self, obj):
            if isinstance(obj, datetime):
                return obj.strftime('%Y-%m-%d %H:%M:%S')
            elif isinstance(obj, date):
                return obj.strftime('%Y-%m-%d')
            else :
                return json.JSONEncoder.default(self, obj)
            d = {'name': 'cxa', 'data': datetime.now()}
            print(json.dumps(d, cls=DateToJson))

52.json序列化时,默认遇到中文会转换成unicode,如果想要保留中文怎么办?

答:可以通过json.dumps的ensure_ascii参数解决,代码示例如下:
    import json
    a = json.dumps({"name":"张三"}, ensure_ascii = False)
    print(a)

53.有两个磁盘文件A和B,各存放一行字母,要求把这两个文件中的信息合并(按字母顺序排列),输出到一个新文件C中。
答:
    # 文件 A.txt 内容为 ASDCF
    # 文件 B.txt 内容为 EFGGTG
    with open("A.txt") as f1:
        f1_txt = f1.readline()
    with open("B.txt") as f2:
        f2_txt = f2.readline()
    f3_txt = f1_txt + f2_txt
    f3_list = sorted(f3_txt)
    with open("C.txt", "a+") as f:
        f.write("".join(f3_list))
    # 输出的文件C的内容为ACDEFFGGGST

54.如果当前的日期为20190530,要求写一个函数输出N天后的日期,(比如 N 为 2,则输出 20190601)。
答:这个题目考察的是datetime里的timedelta方法的使用,参数可选、默认值都为0:
datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
通过这个参数可以指定不同的日期类型进行加减操作,这里我们需要改的是days,代码如下
    import datetime

    def datetime_operate(n:int):
        now = datetime.datetime.now()  # 获取当前时间
        _new_date = now + datetime.timedelta(days=n)  # 获取指定天数后的新日期
        new_date = _new_date.strftime("%Y%m%d")  # 转换为指定的输出格式
        return new_date

    if __name__ == '__main__':
        print(datetime_operate(4))

55.写一个函数,接收整数参数n,返回一个函数,函数的功能是把函数的参数和n相乘并把结果返回。
答:这个题目考查了闭包的使用代码示例如下,返回函数之类型是函数对象。
    def mul_operate(num):
        def g(val):
            return num * val
        return g
    m = mul_operate(8)
    print(m(5))

56.下面代码会存在什么问题,如何改进?
    def strappend(num):
        str = 'first'
        for i in range(num):
        str += str(i)
        return str
答: 首先不应该使用Python的内置类似str作为变量名这里我把它改为了s, 另外在Python, str是个不可变对象,每次迭代都会生成新的存储空间,
num越大,创建的str对象就会越多,内存消耗越大。使用yield 改成生成器即可, 还有一点就是命名规范的位置,函数名改为_分割比较好,完整的代码如下:
    def str_append(num):
        s = 'first'
        for i in range(num):
            s += str(i)
            yield s

    if __name__ == '__main__':
        for i in str_append(3):
            print(i)

57.一行代码输出1 - 100之间的所有偶数。
答:可以通过列表生成式,然后使用与操作如果如1与之后结果为0则表明为偶数,等于1则为奇数。
    # 方法1
        print([i for i in range(1, 101) if i & 0x1 == 0])
    # 方法2:测试发现方法二效率更高
        print(list(range(2, 101, 2)))

58.with 语句的作用,写一段代码?
with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。
其他的内容看下面我之前写的代码。
    # 一般访问文件资源时我们会这样处理:
        f = open(
            'c:\test.txt', 'r')
        data = f.read()
        f.close()
    # 这样写没有错,但是容易犯两个毛病:
    # 1. 如果在读写时出现异常而忘了异常处理。
    # 2. 忘了关闭文件句柄
    # 以下的加强版本的写法:
        f = open('c:\test.txt', 'r')
        try:
            data = f.read()
        finally:
            f.close()
    # 以上的写法就可以避免因读取文件时异常的发生而没有关闭问题的处理了。代码长了一些。
    # 但使用 with 有更优雅的写法:
        with open(r'c:\test.txt', 'r') as f:
            data = f.read()
    # with 的实现
        class Test:
            def __enter__(self):
                print('__enter__() is call!')
                return self
            def dosomething(self):
                print('dosomethong!')
            def __exit__(self, exc_type, exc_value, traceback):
                print('__exit__() is call!')
                print(f'type:{exc_type}')
                print(f'value:{exc_value}')
                print(f'trace:{traceback}')
                print('__exit()__ is call!')
        with Test() as sample:
            pass
    # 当对象被实例化时,就会主动调用__enter__()方法,任务执行完成后就会调用__exit__()方法,
    # 另外,注意到,__exit__()方法是带有三个参数的(exc_type, exc_value, traceback),
    # 依据上面的官方说明:如果上下文运行时没有异常发生,那么三个参数都将置为 None,
    # 这里三个参数由于没有发生异常,的确是置为了 None, 与预期一致.
    # 修改后不出异常了
        class Test:
            def __enter__(self):
                print('__enter__() is call!')
                return self
            def dosomething(self):
                x = 1 / 0
                print('dosomethong!')

            def __exit__(self, exc_type, exc_value, traceback):
                print('__exit__() is call!')
                print(f'type:{exc_type}')
                print(f'value:{exc_value}')
                print(f'trace:{traceback}')
                print('__exit()__ is call!')
                return True
        with Test() as sample:
            pass

59.Python字典和json字符串相互转化方法
答:在Python中使用dumps方法将dict对象转为Json对象,使用loads方法可以将Json对象转为dict对象。
    dic = {'a': 123, 'b': "456", 'c': "liming"}
    json_str = json.dumps(dic)
    print(json_str)
    dic2 = json.loads(json_str)
    print(dic2)

    # '{"a": 123, "b": "456", "c": "liming"}'
    # {'a': 123, 'b': '456', 'c': 'liming'}

    我们再来看一个特殊的例子
        import json
        dic = {'a': 123, 'b': "456", 'c': "liming"}
        dic_str = json.loads(str(dic).replace("'", "\""))
        print(dic_str)
    下面我解释下上面代码是测试什么:
    首先json.loads(jsonstr)这里面的参数只能是jsonstr格式的字符串.当我们使用str将字典dic转化为字符串以后,
    得到的结果为: "{'a': 123, 'b': '456', 'c': 'liming'}"。如果直接使用json.loads(str(dic))你会发现出现错误,
    原因就是,单引号的字符串不符合Json的标准格式所以再次使用了replace("'", "\"")。得到字典
    其实这个例子主要目的是告诉大家Json的标准格式是不支持单引号型字符串的,否则会出现以下错误。
    json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column2(char1)

60.请写一个Python逻辑,计算一个文件中的大写字母数量
答:
    with open('A.txt') as fs:
        count = 0
        for i in fs.read():
        if i.isupper():
        count += 1
        print(count)

61.请写一段Python连接Mongo数据库,然后的查询代码。
答:
    # -*- coding: utf-8 -*-
    import pymongo
    db_configs = {
        'type': 'mongo',
        'host': '地址',
        'port': '端口',
        'user': 'spider_data',
        'passwd': '密码',
        'db_name': 'spider_data'
    }
    class Mongo():
        def __init__(self, db=db_configs["db_name"], username=db_configs["user"],
                     password=db_configs["passwd"]):
            self.client = pymongo.MongoClient(f'mongodb://{db_configs["host"]}:db_configs["port"]')
            self.username = username
            self.password = password
            if self.username and self.password:
                self.db1 = self.client[db].authenticate(self.username, self.password)
            self.db1 = self.client[db]

        def find_data(self):
            # 获取状态为0的数据
            data = self.db1.test.find({"status": 0})
            gen = (item for item in data)
            return gen

    if __name__ == '__main__':
        m = Mongo()
        print(m.find_data())

62.说一说Redis的基本类型
答: Redis支持五种数据类型: string(字符串) 、 hash(哈希)、list(列表) 、 set(集合) 及zset(sortedset: 有序集合)。

63.请写一段Python连接Redis数据库的代码。
答:
    from redis import StrictRedis, ConnectionPool
    redis_url = "redis://:[email protected]:6379/15"
    pool = ConnectionPool.from_url(redis_url, decode_responses=True)
    r = StrictRedis(connection_pool=pool)

64.请写一段Python连接Mysql数据库的代码。
答:
    conn = pymysql.connect(host='localhost',
                           port=3306, user='root',
                           passwd='1234', db='user', charset='utf8mb4')  # 声明mysql连接对象
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 查询结果以字典的形式
    cursor.execute('sql语句字符串')  # 执行sql语句
    conn.close()  # 关闭链接

65.了解Redis的事务么
答: 简单理解,可以认为redis事务是一些列redis命令的集合,并且有如下两个特点:
    1.事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
    2.事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。 一般来说,事务有四个性质称为ACID,分别是原子性,一致性,隔离性和持久性。一个事务从开始到执行会经历以下三个阶段:
    开始事务\命令入队\执行事务
    代码示例:
        import redis
        import sys
        def run():
            try:
                conn = redis.StrictRedis('192.168.80.41')
                # Python中redis事务是通过pipeline的封装实现的
                pipe = conn.pipeline()
                pipe.sadd('s001', 'a')
                sys.exit()
                # 在事务还没有提交前退出,所以事务不会被执行。
                pipe.sadd('s001', 'b')
                pipe.execute()
                pass
            except Exception as err:
                print(err)
                pass
        if __name__ == "__main__":
            run()

本文转载自霍格沃兹测试学院优秀学员ling_tianxia的学习笔记,原文链接:
http://qrcode.testing-studio.com/f?from=csdn2&url=https://ceshiren.com/tag/%E7%B2%BE%E5%8D%8E%E5%B8%96 转载请注明出处

你可能感兴趣的:(软件测试,测试工程师,python)