python面试题

python 基础题

1.进制间的转换

进制的转换可以采用内置函数的方式进行数据的转换,也可以使用int来转换,是将所需转换的数字按照某个进制的规则进行转换,最后转换的结果均为int类型

number = 20

# 方式一
# 二进制
print(bin(number))
# 八进制
print(oct(number))
# 十六进制
print(hex(number))
# 十进制
print(int(number))

# 方式二,只能转换为最后的int类型
# 将数字转按照八进制转换为int类型
print(int(str(number), base=8))
# 将数字转按照十六进制转换为int类型
print(int(str(number), base=16))
# 将0b二进制字符串按照二进制转换为int类型数字
print(int(str(bin(number)), base=2))

0b10100
0o24
0x14
20
16
32
20

需要注意的是,在python中,二进制、八进制、十六进制在输出显示时都会以十进制进行显示,但无需过多关注

b_number = 0b10100
print(b_number)
o_number = 0o24
print(o_number)
h_number = 0x14
print(h_number)
20
20
20

2.最大递归数

通过以下简易的函数可以看出最大递归数

def recursion(n):
    print(n)
    n += 1
    recursion(n)


recursion(1)

受python版本不同,最大递归数也存在不同

python2.7: 1000, 在第1000次调用此函数时会出现异常
python3.6: 998, 在998次调用此函数时会出现异常

可以手动设置最大递归数的数量

import sys
sys.setrecursionlimit(1200)

目前发现,当全部设置最大递归数为1200时,python2.7会在1200次报错,但python3.6会在1198次报错,相较少2次,依次可推出,默认的最大递归数应该是1000(第一次函数调用也算进去的话)。

3.and、not、or运算符优先级

对象 返回结果 优先顺序
not x if x is false,then True,else False 1
x and y if x is false,then x,else y 2
x or y if x is false,then y,else x 3
v1 = 1 or 3  # 1
v2 = 1 and 3 # 3
v3 = 0 and 2 and 1 # 0
v4 = 0 and 2 or 1 # 1
v5 = 0 and 2 or 1 or 4 # 1
v6 = 0 or False and 1 # False
1
3
0
1
1
False

需要注意的是在python中,0也是代表False

4.三元运算符,三目运算符

在python中不存在如下注释的三元运算符,但是由三目运算符代替,可以将简单的条件分支语句写成一行,适用于需要将代码简化的场景,且相比较多行分支效率快一点。

a = 10
# print(a > 2 ? a : 0)

print(a if a > 2 else 0)

5.python2与python3区别

1.python2 True、False可以作为一个变量,可以对其进行赋值及取值,python3则不可以, True、False作为关键字无法修改

True = 1
print(True)

False = 0
print(False)

python2

1
0

python3

    True = 1
    ^
SyntaxError: can't assign to keyword

2.python2默认使用ASCII编码,对中文需要手动添加文档头注释, python3则不需要

print('你好')

python2

  File "/home/ts/flask_study/interview/05python2和python3的区别.py", line 12
SyntaxError: Non-ASCII character '\xe4' in file /home/ts/flask_study/interview/05python2和python3的区别.py on line 12, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

需在py文件最上方添加如下注释

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

python3:则没有影响

你好

3.python2的range返回一个list,资源消耗较大,python3返回一个可迭代对象,资源消耗较小,可使用for循环进行结果的迭代输出,python3的range取代了xrange。

data = range(10)
print(data)
print(type(data))

from typing import Iterable, Iterator, Generator
print(isinstance(data, Iterable))
print(isinstance(data, Iterator))
print(isinstance(data, Generator))

python2

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
<type 'list'>

python3

range(0, 10)
<class 'range'>
True
False
False

4.python3引入nonlocal关键字,方便内部函数读取和修改外部函数的值,当内部函数读取和修改外部函数的值时,则外部函数和内部函数形成了闭包

def outter():
    number = 10
    def inner():
        nonlocal number
        number += 1
        print(number)
    return inner


outter()()

python2

UnboundLocalError: local variable 'number' referenced before assignment

python3

11

5.xreadlines、readlines读取文件,python2存在xreadlines,返回的是文件对象,资源消耗少,python3无xreadlines, python2、python3返回的readlines都是一个list, 建议可以直接迭代遍历open获得的对象

import os

file_path = os.path.join(os.path.dirname(__file__), "01进制转换.py")
print(file_path)
with open(str(file_path), mode="r") as f:
    print(f)
    print(type(f))
    # print(isinstance(f, Iterable))
    for line in f:
        print(line)
    # lines = f.xreadlines()
    lines = f.readlines()
    print(lines)
    print(type(lines))

更多待更新中

6.布尔值为False的值

print(bool(0))
print(bool(None))
print(bool([]))
print(bool({}))
print(bool(""))
print(bool(0j))

7.字符串、列表、元组、字典每个常用的5个方法?

字符串

str_data = 'adminasdasd asdasd'
# 计算字符串中的元素出现次数
print(str_data.count('a'))
# 全部转为大写
print(str_data.upper())
# 以什么开头,可以指定开始的位置
print(str_data.startswith('a'))
# 截取字符串,使用较多
print(str_data.split('a'))
# 只在字符串首部将首字母大写
print(str_data.capitalize())
# 在字符串中的每个单词首字母大写
print(str_data.title())
# 字符串居中 前后补空格
print(str_data.center(22))
# 字符串前面补0
print(str_data.zfill(22))
5
ADMINASDASD ASDASD
True
['', 'dmin', 'sd', 'sd ', 'sd', 'sd']
Adminasdasd asdasd
Adminasdasd Asdasd
  adminasdasd asdasd  
0000adminasdasd asdasd

列表

list_data = [1,2,3,4, [5,6]]
# 添加元素
list_data.append(11)
print(list_data)
# 浅拷贝列表数据, 当修改其中的可变对象时,原有对象会发生改变
copy_list_data = list_data.copy()
print(copy_list_data)
copy_list_data[4].append(4)
print(list_data)
print(copy_list_data)
# 删除对应值的元素
list_data.remove(3)
print(list_data)
# 统计某个元素出现的次数
print(list_data.count(1))
# 两个列表合并
list_data.extend(copy_list_data)
print(list_data)
# 列表排序,元素需要是同类型, 默认是升序
# list_data.sort()
print(list_data)
# 在指定下标插入元素
list_data.insert(0, -1)
print(list_data)
# 删除对应下标的元素
list_data.pop(4)
print(list_data)
[1, 2, 3, 4, [5, 6], 11]
[1, 2, 3, 4, [5, 6], 11]
[1, 2, 3, 4, [5, 6, 4], 11]
[1, 2, 3, 4, [5, 6, 4], 11]
[1, 2, 4, [5, 6, 4], 11]
1
[1, 2, 4, [5, 6, 4], 11, 1, 2, 3, 4, [5, 6, 4], 11]
[1, 2, 4, [5, 6, 4], 11, 1, 2, 3, 4, [5, 6, 4], 11]
[-1, 1, 2, 4, [5, 6, 4], 11, 1, 2, 3, 4, [5, 6, 4], 11]
[-1, 1, 2, 4, 11, 1, 2, 3, 4, [5, 6, 4], 11]

元组

tuple_data = (1,2,3,4,5,1,5)
# 统计元素出现的次数
print(tuple_data.count(1))
# 获取某个下标的元素
print(tuple_data.index(1))
2
0

字典

dict_data = {"name":"tom", "age":10, "gender":"man"}
dict_data2 = {"city":"nanjing"}
# 获取字典的所有keys
print(dict_data.keys())
# 获取字典的所有values
print(dict_data.values())
# 获取字典的所有键值对,元组形式展示
print(dict_data.items())
# 合并两个字典
dict_data.update(dict_data2)
print(dict_data)
# 获取字典中的元素,可以设置默认值
print(dict_data.get('name', None))
# 删除字典中的元素
dict_data.pop('age')
print(dict_data)
# 生成新字典,取出字典的key, 设置默认的value值,默认value为None
print(dict_data.fromkeys(dict_data.copy(), "no data"))
# 删除字典中的元素,默认删除最后一个元素
dict_data.popitem()
print(dict_data)
# 获取字典中元素的值,当对应key不存在时会主动设置对应的key及返回设置的值, 当key存在时,此函数与get使用一致
print(dict_data.setdefault('age', 10))
print(dict_data)
# 清空字典
dict_data.clear()
print(dict_data)
dict_keys(['name', 'age', 'gender'])
dict_values(['tom', 10, 'man'])
dict_items([('name', 'tom'), ('age', 10), ('gender', 'man')])
{'name': 'tom', 'age': 10, 'gender': 'man', 'city': 'nanjing'}
tom
{'name': 'tom', 'gender': 'man', 'city': 'nanjing'}
{'name': 'no data', 'gender': 'no data', 'city': 'no data'}
{'name': 'tom', 'gender': 'man'}
10
{'name': 'tom', 'gender': 'man', 'age': 10}
{}

8.lambda使用方法及使用场景

def sum(m,n):
    return m+n

print(sum(1,2))
sum2 = lambda m,n:m+n
print(sum2(1,2))

lambda主要是针对于函数进行简化代码操作,但只能进行简单代码的简化,复杂代码不建议使用lambda,

使用场景

1.map、reduce、filter等进行序列处理时使用
l = list(range(1, 10))
data = map(lambda n:n*n, l)
print(list(data))

from functools import reduce
data = reduce(lambda m,n:m*n, l)
print(data)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
362880
2.lambda与list相结合, 注意lambda只会记录最后一次的状态,不会记录中间过程的状态
l2 = [lambda:i for i in range(10)]
print(l2[0]())
print(l2[3]())
9
9

9.pass的作用

pass主要就是在代码实现过程中,暂时没有想好怎么实现的时候,一般在函数、方法中使用较多,避免因为函数或方法中没有内容导致报错

10.*arg和**kwarg作用

在函数或方法中, *args会将元素转换为元组, **kwargs会将x=y类似的元素转换为字典

def run(*args, **kwargs):
    print(args)
    print(kwargs)

run(1,2,a=1,b=2)
(1, 2)
{'a': 1, 'b': 2}

2. *作为解包

l1 = [1,2,3]
l2 = [4,5,6]

l = list(zip(l1, l2))
print(l)
print(*l)
print(list(zip(*l)))
[(1, 4), (2, 5), (3, 6)]
(1, 4) (2, 5) (3, 6)
[(1, 2, 3), (4, 5, 6)]

11. is和==的区别

is 不仅比较值也比较内存地址, == 只比较值

a = 1
b = 1
print(id(a))
print(id(b))
print(a == b)
print(a is b)

c = {"name":"mike", "age":13}
d = {"name":"mike", "age":13}
print(id(c))
print(id(d))
print(c == d)
print(c is d)
10914496
10914496
True
True
140187512042624
140187511976800
True
False

12.深拷贝与浅拷贝

浅拷贝:复制的是对象的引用

对于不可变类型(字符串、布尔值、元组、数值类型等)来说,修改复制后的数据不会影响到原始数据,对于可变类型(列表、字典、集合)来说,修改复制后的数据会影响到原有数据。
浅拷贝除了使用copy中的copy方法外,一般不可变类型都会自己携带copy方法。

import copy

data = [1, 2, 3, [4, 5, 6], {"name": "tom", "gender": "man"}]

copy_data = copy.copy(data)

copy_data.append(7)
print(data)
print(copy_data)
copy_data[3].append(8)
print(data)
print(copy_data)
copy_data[4]["city"] = "nanjing"
print(data)
print(copy_data)
[1, 2, 3, [4, 5, 6], {'name': 'tom', 'gender': 'man'}]
[1, 2, 3, [4, 5, 6], {'name': 'tom', 'gender': 'man'}, 7]
[1, 2, 3, [4, 5, 6, 8], {'name': 'tom', 'gender': 'man'}]
[1, 2, 3, [4, 5, 6, 8], {'name': 'tom', 'gender': 'man'}, 7]
[1, 2, 3, [4, 5, 6, 8], {'name': 'tom', 'gender': 'man', 'city': 'nanjing'}]
[1, 2, 3, [4, 5, 6, 8], {'name': 'tom', 'gender': 'man', 'city': 'nanjing'},

深拷贝:生成一个新对象,将原始数据的值重新拷贝一份

对于不可变类型数据或者可变类型数据,修改复制后的数据均不会影响到原始数据

import copy


data = [1, 2, 3, [4, 5, 6], {"name": "tom", "gender": "man"}]

copy_data = copy.deepcopy(data)

copy_data.append(7)
print(data)
print(copy_data)
copy_data[3].append(8)
print(data)
print(copy_data)
copy_data[4]["city"] = "nanjing"
print(data)
print(copy_data)

使用场景

1.在某些情况下,我们需要复制某个列表或者字典的数据时,就需要使用深拷贝,防止对原始数据造成影响

13.可变类型和不可变类型

在python中数据类型分为可变和不可变类型,下面就简单介绍一下 id()是查看内存地址的函数:

可变类型:当数据的值发生改变时,内存地址不会发生改变

例如列表、集合、字典等

list_data = [1, 2, 4]
print(id(list_data))
list_data.append(5)
print(id(list_data))

dict_data = {"name": "tome", "gender": "man"}
print(id(dict_data))
dict_data.setdefault("city", "nanjing")
print(id(dict_data))

set_data = {1, 2, 4}
print(id(set_data))
set_data.add(3)
print(id(set_data))
2275116072896
2275116072896
2275115992448
2275115992448
2275116213728
2275116213728

不可变类型:当数据的值发生改变时,内存地址会发生改变

例如字符串、布尔值、整型、浮点型、元组等

str_data = 1
print(id(str_data))
str_data = 2
print(id(str_data))

str_data = "a"
print(id(str_data))
str_data = "b"
print(id(str_data))

str_data = 1.0
print(id(str_data))
str_data = 2.0
print(id(str_data))

tuple_data = (1, 2, 3)
print(id(tuple_data))
tuple_data = (1, 2, 4)
print(id(tuple_data))
2109049864432
2109049864464
2109051267184
2109051030000
2109050903248
2109050903024
2109051248000
2109051248256

14.Python垃圾回收机制?

15.求以下代码的结果

t = []
v = dict.fromkeys(["k1", "k2"], t)
print(v)
v["k1"].append(666)
print(v)
v["k1"] = 777
print(v)

由以下结果可以看出,在fromkeys生成字典的时候,设置的默认值指向的是同一个元素,相当于是浅拷贝了默认值

{'k1': [], 'k2': []}
{'k1': [666], 'k2': [666]}
{'k1': 777, 'k2': [666]}
def num():
    return [lambda x: i * x for i in range(4)]


print(num())
print([m(2) for m in num()])

由以下结果可以看出,lambda,不会记录中间的状态,只会记录最后的状态

[<function num.<locals>.<listcomp>.<lambda> at 0x0000026926836170>, <function num.<locals>.<listcomp>.<lambda> at 0x0000026926836200>, <function num.<locals>.<listcomp>.<lambda> at 0x0000026926836290>, <function num.<locals>.<listcomp>.<lambda> at 0x0000026926836320>]
[6, 6, 6, 6]

16.常见的内置函数及作用

map:将函数批量作用一个序列中

from typing import Iterator


list_data = [1, 2, 3]
data = map(lambda n: n * 2, list_data)
print(data)
print(type(data))
print(isinstance(data, Iterator))
for item in data:
    print(item)

由此可见,map对象是一个迭代器,可以被for循环或者next进行元素遍历或者迭代

<map object at 0x0000026C4B6EBD90>
<class 'map'>
True
2
4
6

reduce:依次对序列进行函数处理并进行累计处理

from functools import reduce


list_data = [1, 2, 3]
data = reduce(lambda m, n: m * n, list_data)
print(data)

由此可见,返回的元素由函数最终的函数结果决定

6

filter:依据函数对序列进行过滤,返回符合条件的filter对象

from typing import Iterable


list_data = [1, 2, 3]
data = filter(lambda n: n > 2, list_data)
print(data)
print(type(data))
print(isinstance(data, Iterable))
for item in data:
    print(item)

由此可见,filter对象也是一个迭代器

<filter object at 0x000002045EA3BD90>
<class 'filter'>
True
3

sorted:自定义排序

sorted(Iterable, key, reverse=False)
key为需要进行排关键字
reverse默认为False、升序;反之则降序

dict_data = {"a": 1, "c": 3, "b": 2}
print(tuple(dict_data.items()))
# 按照字典的key排序
data = sorted(dict_data.items(), key=lambda x: x[0])
print(dict(data))
# 按照字典的value排序
data = sorted(dict_data.items(), key=lambda x: x[1], reverse=True)
print(dict(data))
(('a', 1), ('c', 3), ('b', 2))
{'a': 1, 'b': 2, 'c': 3}
{'c': 3, 'b': 2, 'a': 1}

17.一行代码实现9 * 9乘法表

18.python如何安装第三方模块

pip 查找模块

由于pip search module已经被python官方禁用,需要使用pip_search去搜索相应模块,需要安装pip-search模块,直接安装即可,命令如下

pip install pip-search

搜索模块,会显示所有包含关键字的模块

pip_search module

pip 安装模块

基本安装方法
pip install module
一般国内默认的源较慢,可以指定安装的源, 例如清华源、豆瓣源等,可以上网查询
pip install module -r https://pypi.tuna.tsinghua.edu.cn/simple

使用上述命令可以使用安装模块速度的加快,但是每次都需要额外添加源较为繁琐,因此可以采用下面配置文件的方式,方便后续安装模块。
1.在window的文件管理器输入%APPDATA%进入默认的用户目录,一般为C:\Users\xxx\AppData\Roaming, xxx为用户名
2.在此文件夹下新建一个名为pip的文件夹
3.在新建的pip文件夹下创建一个名为pip.ini的文件,此处使用的是清华源,也有一些其他的国内源,自行修改即可
内容如下:

[global]
timeout = 6000
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
trusted-host = pypi.tuna.tsinghua.edu.cn

Linux与Windows类似,不同是路径、文件不一致,打开文件后直接将上述文件写入即可

mkdir ~/.pip
cd ~/.pip
touch pip.conf
vim pip.conf

内容输入完后保存即可,下载pip安装的时候便会使用你设置的国内源,加快下载速度

有时候我们需要指定某个某个模块的版本

pip install module==1.0.1

导出项目中使用的模块,方便移植

pip freeze > requirements.txt

既然有导出,肯定有导入

pip install -r requirements.txt

19.使用过的第三方模块,常用的模块?

第三方模块:即需要pip install安装的模块
下面罗列一些可能会经常使用到的模块

  • os:操作文件、文件夹路径、系统分隔符等:详细介绍:os相关操作
  • shutils:批量新建文件、文件夹、压缩文件等,详细介绍:shutils相关操作
  • request:请求操作,例如get、post等
    需要注意的是可能会出现get返回的数据为空的情况,是因为大部分网站都做了反扒处理,需要添加headers
    如下是requests的简单使用
import requests

url = "https://movie.douban.com/"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) \
        AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36"
}
response = requests.get(url, headers=headers)
result = pathlib.Path(__file__).parent.joinpath("douban.html")
with open(result, mode="w", encoding="utf8") as f:
    print(response.text)
    f.write(response.text)
    print(response)
  • virtualenv:创建虚拟环境
  • winreg:Windows注册表相关
  • psutil:系统cpu、内存、线程相关
  • fire:添加命令行相关参数(main create ...)
  • flask:flas web框架
  • pyinstaller:将py文件打包成exe文件
  • configparser:操作ini文件。详细介绍:ini文件操作
  • PyYAML:操作yaml文件。详细介绍:yaml文件操作
  • 操作excel文件:excel文件操作
  • 操作xml、html的模块,lxml:详细介绍: lxml相关操作
  • 持续更新中

20.re的match和search区别?

21.什么是正则的贪婪匹配?

22.求结果

print([i % 2 for i in range(10)]) 
# 生成的是一个列表:[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
print((i % 2 for i in range(10)))
# 生成的是一个生成器,需要手动next或者for循环遍历
print(1 or 2)  # 1
print(1 and 2)  # 2
print(1 < (2 == 2))  # False
print(1 < 2 == 2) # True

or: 第一个元素为True则输出第一个元素, 反之
and: 第一个元素为Flase输出第一个元素,反之
优先级问题: 数字除了0为False其余均为True

23.def func(a,b=[]) 这种写法有什么坑?

def func(a, b=[]):
    b.append(a)
    print(b)


for i in range(10):
    func(i)
[0]
[0, 1]
[0, 1, 2]
[0, 1, 2, 3]      
[0, 1, 2, 3, 4]   
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4, 5, 6]
[0, 1, 2, 3, 4, 5, 6, 7]
[0, 1, 2, 3, 4, 5, 6, 7, 8]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

从上述结果发现,每次输出都是叠加的,由此可见,b指向了[]的内存引用,类似于可变对象一样,因此在函数或者方法中存在着一条规定:

默认参数必须要指向不可变对象

此处可以修改如下:

def func(a, b=None):
    if b is None:
        b = []
    b.append(a)
    print(b)


for i in range(10):
    func(i)

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

24.如何实现 “1,2,3” 变成 [‘1’,’2’,’3’] \ [‘1’,’2’,’3’]变成[1,2,3] ??

data = "1,2,3"
print(data.split(','))

data = ["1", "2", "3"]
print([int(n) for n in data])
print(list(map(lambda n: int(n), data)))

25.比较: a = [1,2,3] 和 b = [(1),(2),(3) ] 以及 b = [(1,),(2,),(3,) ] 的区别?

a = [1, 2, 3]
b = [(1), (2), (3)]
c = [(1,), (2,), (3,)]


print(type(a))
print(type(a[0]))
print(type(b))
print(type(b[0]))
print(type(c))
print(type(c[0]))
<class 'list'>
<class 'int'>  
<class 'list'> 
<class 'int'>  
<class 'list'> 
<class 'tuple'>

由此可见,a、b、c都是列表,不过其中的元素有所不同,a、b的元素都是int类型,c中的为元组

26.如何用一行代码生成[1,4,9,16,25,36,49,64,81,100] ?

使用map函数即可,map函数是对于序列中的元素进行批量操作

print(list(map(lambda n: n * n, range(1, 11))))

27.一行代码实现删除列表中重复的值 ?

可以使用三种方式操作,如下

list_data = [1, 3, 4, 5, 6, 7, 2, 5, 1, 3, 8]

# 第一种方法,使用set, 默认会自动排序,顺序可能会发生改变
print(list(set(list_data)))
# 第二种方法,遍历列表元素去重


def remove_repeat(data):
    result_list = []
    for item in data:
        if list_data.count(item) == 1 or (
            list_data.count(item) > 1 and result_list.count(item) == 0
        ):
            result_list.append(item)
    return result_list

# 此方法使用yield 返回生成器的方式,节省消耗
def remove_repeat2(data):
    for item in data[-1:]:
        if list_data.count(item) == 1:
            yield item
        else:
            data.remove(item)


print(remove_repeat(list_data))
print(list(remove_repeat2(list_data)))

# 第三种方法,使用Counter
from collections import Counter

print(list(Counter(list_data)))

28.如何在函数中设置一个全局变量 ?

一般在python中有两种全局变量,一种是函数中的全局变量,还有一种是全局的变量

全局变量

此处函数中通过global获取到全局变量

count = 0


def run():
    global count
    count += 1


run()
print(count)
# 1

函数中的全局变量

nonlocal是python3出现的,方便内部函数调用外部函数变量, 如果不使用nonlocal,只能获取外部函数的变量值

def outter():
    number = 1

    def inner():
        nonlocal number
        number += 1
        print(number)
    return inner


outter()()
# 2

29.logging模块的作用?以及应用场景?

logging是python自带的日志模块,可以很方便的进行日志的输出及输出到文件等
主要分为如下几个等级。

日志等级 描述
INFO 无异常时输出的日志,主要是确认程序是否正常按照预期进行的
DEBUG 一般在开发阶段使用,用于问题的诊断与定位
WARNING 当出现一些异常信息(例如磁盘空间不足)时,但是不会影响程序的正常执行
ERROR 当出现问题时导致程序无法正常运行时
CRITICAL 当出现严重问题时导致程序无法继续运行时
import logging


logging.info("info")
logging.warning("warning")
logging.debug("debug")
logging.error("error")
logging.critical("critical")

通常情况下,我们在项目中会定义一个日志类,方便将日志输出的文件中:详细介绍:日志记录类

30.请用代码简答实现stack

31.常用字符串格式化哪几种?

已知三种, %\ f\ format

print("%d %s" % (1, "test"))

timeout = 1
print(f"{timeout}")
print("{}".format("test"))

32.简述 生成器、迭代器、可迭代对象 以及应用场景?

详细介绍:迭代器、生成器

33.用Python实现一个二分查找的函数。

二分查找

也称折半查找,意思是从有序的序列(n个元素)中找到一个元素,默认从中间(n/2)开始找, 在找的过程中会出现以下三种情况:

  • 需要找的元素大于中间元素,则到n/2右边的序列中继续进行二分查找
  • 需要找的元素小于中间元素,则到n/2左边的序列中继续进行二分查找
  • 需要找的元素刚好就是中间元素,查找结束
target = 9
list_data = [1, 2, 4, 2, 9, 43, 2]
list_len = len(list_data)
index = 0
middle = int(list_len / 2) - 1
while True:
    if target == list_data[middle]:
        index = middle
        break
    elif target > list_data[middle]:
        middle = middle + int((list_len - middle) / 2) - 1
    else:
        middle = int(middle / 2) - 1

print(index)

34.谈谈你对闭包的理解?

闭包理解

35.os和sys模块的作用?

os和sys都属于系统层级的模块
os:通常用于文件、文件夹的相关操作(新建、删除、重命名等),也可用于路径的获取与切换;执行命令等
sys:通常用于命令行参数的获取、系统平台的获取、系统执行路径等

36.如何生成一个随机数?

import random


rand = random.Random()
# 随机生成0-1内的浮点类型数据
print(rand.random())
# 生成0-1符合 贝塔分布
print(rand.betavariate(0.1, 0.5))
tu = (1, 2, 3, 4, 78, 12, 98)
# 从一个非空序列中选择一个元素
print(rand.choice(tu))
# 从列表中随机选取多个值,返回的是一个列表
print(rand.choices(tu, k=2))
# 返回一个区间内的数字
print(rand.randint(1, 100))
# 返回一个区间的数字,不过可以指定step步长
print(rand.randrange(1, 100, 2))

37.如何使用python删除一个文件?

使用os中的删除文件或者文件夹,不过无法删除里面包含文件夹或者文件的文件夹,需要递归进行操作

import os
import time


os.mkdir("test")
time.sleep(4)
os.rmdir("test")

with open("1.txt", mode="w", encoding="utf8") as f:
    f.write("test" * 10)
time.sleep(4)
os.remove("1.txt")

os.makedirs("test2/test3")
time.sleep(4)
os.removedirs("test2/test3")

使用shutil可以递归操作文件夹

import shutil

# 相当于mv
shutil.move()
# 拷贝整个文件夹,里面可以包含子文件或者子文件夹
shutil.copytree()
# 与上述类似,可以删除整个文件夹,哪怕存在子文件夹
shutil.rmtree()

38.谈谈你对面向对象的理解?

详细介绍: 面向对象理解

39.Python面向对象中的继承有什么特点?

详细介绍: 面向对象理解

40.面向对象深度优先和广度优先是什么?

详细介绍: 面向对象理解

41.面向对象中super的作用?

详细介绍: 面向对象理解

42.是否使用过functools中的函数?其作用是什么?

reduce:对序列进行叠加操作

from functools import reduce


li = [1, 2, 3, 4]
print(reduce(lambda m, n: m + n, li))

wraps:装饰器中的改变函数注释及函数名称的

from functools import wraps


def decorator(func):
    @wraps(func)
    def inner(*args, **kwargs):
        func(*args, **kwargs)

    return inner

partial:偏函数,用于生成新函数,可以指定某些固定的参数

from functools import partial


def fun(x, y, z):
    return x + y + z


fun2 = partial(fun, 1)
print(fun2(2, 4))

43.列举面向对象中带爽下划线的特殊方法

详细可以查看常见魔法函数

44.如何判断是函数还是方法?

广义来说,在类中的绑定了实例变量的实例方法叫方法,非类中的叫函数
python有自带的可以区分是函数还是方法的函数。

from abc import abstractmethod
import inspect


def fun():
    pass


print(inspect.isfunction(fun))
print(inspect.ismethod(fun))
print(type(fun))


class Test:
    def __init__(self) -> None:
        pass

    def fun():
        pass

    def fun2(self):
        pass

    @staticmethod
    def fun3():
        pass

    @classmethod
    def fun4(cls):
        pass

    @abstractmethod
    def fun5():
        pass


fun2 = Test().fun2
print(inspect.isfunction(fun2))
print(inspect.ismethod(fun2))
print(type(fun2))

fun = Test().fun
print(inspect.isfunction(fun))
print(inspect.ismethod(fun))
print(type(fun))

fun3 = Test().fun3
print(inspect.isfunction(fun3))
print(inspect.ismethod(fun3))
print(type(fun3))

fun4 = Test().fun4
print(inspect.isfunction(fun4))
print(inspect.ismethod(fun4))
print(type(fun4))

fun5 = Test().fun5
print(inspect.isfunction(fun5))
print(inspect.ismethod(fun5))
print(type(fun5))

True
False
<class 'function'>
False
True
<class 'method'>
False
True
<class 'method'>
True
False
<class 'function'>
False
True
<class 'method'>
False
True
<class 'method'>

由上述可见,类中的处理静态方法是函数,其他的都是方法,非类中的都是函数。

45.静态方法和类方法区别?

区别 静态方法 类方法
修饰的方法 staticmethod classmethod
方法类型 函数 方法
是否获取实例对象 不可以 不可以
传入参数 可以传入参数 必须要传入cls后才能再传入参数
调用方式 类调用,类对象调用都可以 类调用、类对象调用都可以
class Test:
    def __init__(self) -> None:
        self.name = "mike"
    
    @staticmethod
    def static_method(a, b):
        print(a + b)
        print("static_method")

    @classmethod
    def class_method(cls, a, b):
        print(a + b)
        print("class_method")


t = Test()
t.static_method(1, 2)
Test.static_method(2, 3)
t.class_method(1, 2)
Test.class_method(2, 3)

46.列举面向对象中的特殊成员以及应用场景

常见的魔法函数

47.什么是反射?以及应用场景?

详细介绍:python 反射

48.metaclass作用?以及应用场景?

type与metaclass

49.用尽量多的方法实现单例模式。

50.装饰器的写法及应用场景?

详细介绍:装饰器

51.异常处理写法以及如何主动跑出异常(应用场景)

异常处理

52.什么是面向对象的mro

MRO的全称是Method Resolution Order(方法解析顺序),它指的是一棵类继承树,当调用最底层类对象的所对应的实例方法时, python解释器在类继承树上的搜索方法的顺序。对于一棵类继承树可以通过最底层方法mro()或是__mro__的属性获得他的MRO。

class D:
    def run(self):
        print("d run")


class C(D):
    def run(self):
        print("C run")


class B(D):
    def run3(self):
        print("B run")


class A(B, C):
    def run2(self):
        print("A run")


A().run()
print(A.mro())

使用mro()可以得到一个类的继承顺序,一般在python3中默认时广度优先。

53.isinstance作用以及应用场景?

官方说法:
如果 object 参数是 classinfo 参数的实例,或其(直接、间接或 virtual )子类的实例,则返回 True。 如果 object 不是给定类型的对象,则总是返回 False。如果 classinfo 是类型对象的元组(或由该类元组递归生成)或多个类型的 union 类型,那么当 object 是其中任一类型的实例时就会返回 True。如果 classinfo 不是某个类型或类型元组,将会触发 TypeError 异常。
通俗点说,判断某个对象是否是某个类型。

print(isinstance("1", str))
print(isinstance("1", int))

print(isinstance(1, int))
print(isinstance(1, str))

print(isinstance([1, 2], list))
print(isinstance([1, 2], tuple))

54,给定一个整数数组,返回两个数字的索引,使它们相加到一个特定的目标。您可以假设每个输入都会只有一个解决方案,您可能不会两次使用相同的元素。

例如

Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,

return [0, 1]
nums = [2, 7, 11, 15, 34, 1, 23, 11]
target = 25


def fun(data, target):
    for index, item in enumerate(nums):
        if item > target:
            continue
        if data.count(target - item) > 0:
            return [index, data.index(target - item)]
    return False


print(fun(nums, target))

55.json序列化时,可以处理的数据类型有哪些?如何定制支持datetime类型?

56.有用过with statement吗?它的好处是什么?

57.使用代码实现查看列举目录下的所有文件。

# 使用代码实现查看列举目录下的所有文件。
import os
import pathlib


dir_path = "D:\python_study"
# 文件夹名称 文件夹下的文件夹,以列表形式呈现 文件夹下的文件,以列表形式呈现
for dirpath, dir_list, file_list in os.walk(dir_path):
    print(f"dirpath:{dirpath}")
    print(f"dirnames:{dir_list}")
    print(f"filenames:{file_list}")


# 只能显示当前层级的文件夹,以列表形式呈现
print(os.listdir(dir_path))

# 只能显示当前层级的文件夹,以生成式+路径对象形式呈现
print(list(pathlib.Path(dir_path).iterdir()))
print(list(pathlib.Path(dir_path).glob("*")))

# 显示所有的文件及文件夹 路径对象,以生成器+路径对象形式呈现
print(list(pathlib.Path(dir_path).rglob("*")))

58.简述 yield和yield from关键字。

参考

作者:武沛齐
出处:http://www.cnblogs.com/wupeiqi/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

posted @ 2022-07-27 20:58  形同陌路love  阅读(490)  评论(0编辑  收藏  举报