Python常见基础面试题

面试题

谈谈你对面向对象的理解

面对对象是一种编程思想,以类的眼光来来看待事物的一种方式。将有共同的属性和方法的事物封装到同一个类下面。
​
封装:
    定义:将数据处理和业务实现逻辑放在某个对象内部,外界只能通过公开的接口访问该对象
    好处:隐藏对象实现细节,便于维护和提高安全性
继承:
    定义:类与类之间产生父子关系,多继承情况按照类的书写顺序查找
    好处:子类可以获取父类的属性和方法;
    实现方式:覆盖式继承、扩展式继承super()
多态:(python动态弱类型语言,Java静态强类型语言)
    定义:多态就是同一个接口,使用不同的实例而执行不同操作
    实现方式:重写、接口、抽象类和抽象方法
    多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理

解释一下Python中的继承

当一个类继承自另一个类,它就被称为一个子类/派生类,继承自父类/基类/超类。它会继承/获取所有类成员(属性和方法)。
​
继承能让我们重新使用代码,也能更容易的创建和维护应用。Python支持如下种类的继承:
​
单继承:一个类继承自单个基类
多继承:一个类继承自多个基类
多级继承:一个类继承自单个基类,后者则继承自另一个基类
分层继承:多个类继承自单个基类
混合继承:两种或多种类型继承的混合

Python垃圾回收机制是什么

python采用的是引用计数机制为主,标记-清除和分代收集(隔代回收、分代回收)两种机制为辅的策略计数机制
​
一个对象被引用时,引用计数加1,当对象被del时,引用计数减去1,为0时,对象就被清除,一般情况下用户不会去操作Python 的垃圾回收机制,但它留有API接口。

什么是python的自省

运行时能够获知对象的类型,检查某些事物以确定它是什么、它知道什么以及它能做什么。自省向程序员提供了极大的灵活性和控制力。
​
Python中比较常见的自省(introspection)机制(函数用法)有: dir(),type(), hasattr(), isinstance()
dir():返回传递给它的任何对象的属性名称经过排序的列表。如果不指定对象,则 dir() 返回当前作用域中的名称
type():确定对象是字符串还是整数,或是其它类型的对象
isinstance():确定对象是否是某个特定类型或定制类的实例

在python当中如何获取命令行参数?

import sys
sys.argv # 接收用户输入的命令行参数

类和对象在内存中是如何保存的?

类只需要在内存中保存一份即可,而类的实例即对象,实例化一次就须要在内存中保存一次,并且有一个类对象指针,指向该对象实例化的类
​
当object1执行def方法时:
1--会根据当前对象的类对象指针找到类的方法
2--如果该方法须要参数会传入类对象第一个参数self执行方法

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

__new__:生成实例
__init__:在创建类的新对象/实例时,将自动调用此方法来分配内存。所有类都有__init__方法
__del__:析构方法,当对象在内存中被释放时,自动触发执行。如当 del obj 或者应用程序运行完毕时,执行该方法里边的内容
__class__ :表示当前操作的对象的类是什么
__str__:改变对象的字符串显示 print函数
__format__:自定制格式化字符串
__get__():调用一个属性时触发
__set__():为一个属性赋值时,触发
__delete__():采用del删除属性时触发

常用模块都有那些?

自带的模块(库):
os,sys,re,math,datatime,unitttest,random,time,logging,json
​
第三方的模块(库):
requests,pymysql ,bs4,petermaterized,HTMLTestRunner,openpyxl,Django,Flask,selenium,appium-python-client 

os和sys模块的作用?

os模块负责程序与操作系统的交互,提供了访问操作系统底层的接口;
sys模块负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控python的运行时环境。

如果模块是被导入的name的值是什么,如果是被执行的name的值又是什么?

被导入的时候__name__的值是这个模块的文件名
被执行时__name__ == "__main__"

函数作用域和顺序

L:local 函数内部作用域 
E:enclosing 函数内部与内嵌函数之间(闭包)
G:global 全局作用域 
B:build-in 内置作用域
​
执行顺序由内向外

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

方法:
    无需传入实例对象
    实例方法由实例对象调用,不需要传入实例对象;
    
函数:
    需要传入实例对象
    函数由类调用,需要传入实例对象

实例方法、静态方法、类方法

1.实例方法只能被实例对象调用,第一个参数必须要默认传递实例对象,一般使用self
2.类方法(由@classmethod装饰器的方法),类或类的实例对象调用
3.静态方法(@由staticmethod装饰器的方法),类和实例对象都可以调用

什么是绑定到对象的方法、绑定到类的方法、非绑定方法

绑定到对象的方法>>实例方法
绑定到类的方法>>类方法
非绑定方法>>静态方法

*arg和**kwarg作用

*args代表位置参数,它会接收任意多个参数,并把这些参数作为元祖传递给函数
**kwargs代表的关键字参数,返回的是字典,位置参数一定要放在关键字参数前面

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

global语句是被用来声明全局变量的

说说python的小数据池

python中数字。在一定规则范围内,如果同时定义多个相同值的数字类型或字符串类型变量,他们会共用一个内存地址。可以用 is 验证。
数字:范围在 -5~256
小数据池的目的是节省内存空间

列举布尔值为False的常见值?

0、None、''、{}、[]、()、set()

None、空字符串的区别(python没有null)

1.None的数据类型是NoneType,空字符串对应的数据类型是字符串
2.用于布尔判断是都是Flase;
3.作为dir()函数的参数是,返回的属性、方法列表不同

in操作对于list, set, tuple, dict的效率

set/dict的效率高于list/tuple

数据类型 使用 in 操作符查找的平均时间复杂度
list O(n)
tuple O(n)
set O(1)
dIct O(1)

json和字典的区别?

json() 本质是字符串 str类型,是一种按照key:value键值对格式的字符串
字典:是python语言中的一种数据类型(int str,float,bool,dict,tuple,list)

字典和列表的查找速度哪个更快?

字典更快,因为字典采用的是哈希表,而列表的查找是遍历整个列表

列表、元组、字典、集合

有序:列表、元组、字典
无序:集合
字典:key通过哈希函数决定value的存储地址,key值可以是整型、字符串、元组
​
可变数据类型:列表、字典
不可变数据类型:整型、字符串、元组
​
为什么叫做可变数据类型?
    不可变数据类型更改后地址发生改变,可变数据类型更改地址不发生改变

元组和列表的区别

列表是可变的,而元组是不可变的
定义不同

元组可以作为字典的key?

元组可以作为字典的key
​
set/dict使用hash值进行索引,要求存储的元素有可哈希,所以list和dict类型不能作为字典的key,元组、整型、字符串可以作为字典的key

字符串、列表、元组、字典常用方法

字符串常用方法

字符串为不可变类型,执行方法后生成新的字符串,不改变原字符串
​
字符串.find(查找字符,开始位置,结束位置) #返回第一个下标值(整型),没有则返回-1
字符串.replace(原字符串,新子字符串,替换次数) #返回类型为字符串
字符串.join(字符串/字符串型列表/字符串型元组/字符串型字典) #返回类型为字符串
字符串.split(分割符,num) #返回类型为列表,num缺省值为全部,分隔符缺省值为' '

列表常用方法

列表:可变数据类型,注意一些方法无返回值,且直接操作原列表
​
列表[索引] #返回索引的对应值
列表[索引] = 新数据 #修改元素值,使用不存在的索引,代码执行会报错!
列表.count(目标数据) #统计被测试值出现的次数,目标数据不存在则返回0
​
列表.insert(索引,新数据) #无返回值;不存在的索引时,默认会将数据插入列表末尾
列表.append(新增数据) #无返回值;新增数据若是一个容器类型(例如: 列表)数据,则会将数据整体作为一个元素添加至末尾
列表.extend(字符串或可迭代对象) #无返回值;字符串和可迭代对象被拆分后,追加到列表末尾
​
列表.pop(索引) #返回被删除的数据值,如果不传入索引值,默认删除列表中最后一个数据,索引不存在会抛出异常
列表.remove(目标数据) #无返回值,如果目标数据在列表中存在多个,只会删除第一个匹配的数据;如果目标数据不存在,会抛异常
列表.clear() #清空列表数据
​
列表.reverse() #无返回值;反转列表!
列表.sort() #对列表中数据进行升序
列表.sort(reverse=True) #对列表中数据进行降序

元组常用方法

元组:不可变数据类型
​
元组变量 = 数据1,数据2,数据3 #组包操作
变量1,变量2,变量3 = 元组变量 #拆包操作
元组.count('要统计的对象') #返回要统计的对象的个数

字典常用方法

字典:可变数据类型,一些方法是对原字典进行操作
​
典['键'] = 值 #如果键不存在,则增加键值对; 如果键存在,则修改键对应的值
[print(key) for key in info.keys()] #打印所有key值
[print(value) for value in info.values()] #打印所有value值
[print(key,value) for key,valu in info.items()] #打印所有key和value值
​
字典.pop(键) #返回键对应的值,参数为空或不存在会抛出异常
字典[键] #返回键对应的值,参数为空或不存在会抛出异常
字典.get(键) #返回键对应的值,参数为空抛异常,键不存在则返回None
​
字典.clear() #返回{}

字符串的拼接可以使用+和join完成,两者有什么区别?

字符串属于不可变数据类型,每执行一次+都会申请一块新的内存地址,因此用+号连接的时候,会有多次的内存申请和复制;
​
而使用join在连接字符串的时候,会先计算需要多大的内存存放结果,然后一次性的申请所需呀的内存,字符串拼接的时候建议使用join

文件操作

模式 可做操作 若文件不存在 是否覆盖
r 只能读 报错 -
r+ 可读可写 报错
w 只能写 创建
w+ 可读可写 创建
a 只能写 创建 否,追加写
a+ 可读可写 创建 否,追加写
1.以 r+、w、w+、a、a+ 模式打开文件,则都可以写入;
2.以 w 或 w+ 模式打开文件时,程序会立即清空文件的内容;
3.以 r,r+,w,w+模式打开文件时,文件指针位于文件开头处;
4.以 a,a+模式打开文件时,文件指针位于文件结尾处;

with

with语句的使用,可以简化了代码,有效避免资源泄露的发生
​
打开文件在进行读写的时候,可能会出现一些异常状况,如果按照常规的f.open写法,我们需要try,except,finally,做异常判断,并且文件最终不管遇到什么情况,都要执行finally f.close()关闭文件,with方法帮我们实现了finally中f.close()

打开文件

方式一:
    文件变量 = open('文件名字','访问模式')
    文件操作
    文件变量.close()
方式二:
    with open('文件名字','访问模式') as f:
    
1.文件名字,访问模式都是字符串类型
2.如果操作文本文件,encoding='utf-8'为指定utf-8编码,防止不同平台中文乱码
    - 访问模式不是二进制('w','r'),打开文件建议指定编码
    - 访问模式如果是二进制方式('wb','rb'),一定不能指定encoding
3.访问模式
'w': 只写方式打开文件,文件不存在创建,文件存在,清空文件内容
'r': 缺省值,只读方式打开文件,如果文件不存在,报错
'a' open for writing,appending to the end of the file if it exists
'x' create a new file and open it for writing
'b' binary mode

读文件

with open('文件名字','r',encoding='utf-8') as f:
	data = f.read(读取的长度) #如果read的长度不指定,默认读取全部
    print(data)
with open('文件名字','r',encoding='utf-8') as f:
    while True
        data = f.readline()
        if data: # 判断有内容
            print(data)
        elif not data:  # 判断无内容
            break # 结束循环       

写操作

with open('文件名字','w',encoding='utf-8')) as f:
    f.write('xxx')  

seek(offset[, whence])

移动文件读取指针到指定位置,index从0开始 offset -- 开始的偏移量 whence:0代表从文件开头开始算起,1代表从当前位置开始算起,2代表从文件末尾算起

test.txt内容:
0123456
​
with open('test.txt','a+') as f:
    f.write('abc')
    f.seek(2)
    print(f.read()) #2345abc

truncate([ size ])

truncate([ size ])
指定长度的话,就从文件开始位置,截断指定长度,其余内容删除;
不指定长度的话,删除读取指针位置之后的所有内容;
test.txt内容:
0123456
​
with open('test.txt','a+') as f:
    f.truncate(2)
    
    f.seek(0)
    print(f.read()) #01
​
with open('test.txt','a+') as f:
    f.seek(0)
    f.truncate()
    
    f.seek(0)
    print(f.read()) #清空
    
with open('test.txt','a+') as f:
    f.seek(2)
    f.truncate()
    
    f.seek(0)
    print(f.read()) #01

文件操作中f = open(filename, mode, code),执行写入f.write('hello world'),请问hello world 是写进了文件还是只是存在内存当中?如何使写的内容主动存储到文件中

f.write是将内容写到计算机的内存中
存储到文件:
    f.close()# 文件关闭,会自动将内容从内存存储到文件中
    f.flush()# 主动将内容从内存存储到文件中
flush() 方法是用来刷新缓冲区的,即将缓冲区中的数据立刻写入文件,同时清空缓冲区,不需要是被动的等待输出缓冲区写入。
一般情况下,文件关闭后会自动刷新缓冲区,但有时你需要在关闭前刷新它,这时就可以使用 flush() 方法。

如何操作数据库?

#导入pymysql
    import pymysql
#建立连接
    conn = pymysql.connect(host='211.103.136.244',port=7061,
 user='student',password='iHRM_student_2021',
 database='ihrm',charset='utf8')
#获取游标
    cursor = conn.cursor()
    
#执行查询语句
    cursor.execute('select version();') #返回受影响行数
#查看查询结果
    resp = cursor.fetchall()
    resp = cursor.fetchone()
    resp = cursor.fetchmany(6)
#关闭游标和连接对象
    cursor.close()
    conn.close()
​
#执行dml语句
try:
    n = cursor.execute('delete from table where id = '1';')
except Exception as e:
    # 有异常,回滚事务
    logging.info(e)
    conn.rollback()
else:
    # 没有异常,提交事务
    conn.commit()
finally:
    # 关闭游标和连接对象
    cursor.close()
    conn.close()

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

logging 
模块定义的函数和类为应用程序和库的开发实现了一个灵活的事件日志系统
作用:
    可以了解程序运行情况,是否正常
    在程序的出现故障快速定位出错地方及故障分析

break、continue 、pass、exit() 区分

break:跳出循环,不再执行
​
break语句用在while和for循环中
​
如果使用嵌套循环,break语句将停止执行最深层的循环,继续执行外部循环;
continue:跳出本次循环,执行下一次
​
continue语句用在while和for循环中
pass:只为了保持程序结构的完整性,不做任何事情,只起到占位的作用
sys.exit(n)
    退出程序引发SystemExit异常,可以捕获异常执行清理工作
    n默认值为0,表示正常退出,其他都是非正常退出
    用于在主线程中退出
​
os._exit(n)
    直接退出不抛异常,不执行相关清理工作
    常用在子进程的退出
​
exit()/quit()
    抛出SystemExit异常
    exit(1) 表示发生了错误
    exit(0) 则表示程序是正常退出的

异常处理、万能异常、抛出异常

try:
    pass
except 异常1:
    pass
except Exception:
    pass #万能异常
else:
    没有发生异常,except不满足执行else
finally:
    不管有没有异常,最终都要执行
主动抛出异常
raise [Exception [,args [,traceback]]]

isinstance作用以及应用场景?

isinstance(对象,类) 判断这个对象是不是这个类,或者这个类的子类的实例化

id()、is、==、=

id 查看内存地址,is是比较内存地址是不是相同,=是赋值,==比较的是变量的值
​
id() 返回对象的内存地址
is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同,内存地址相等则为True
== 比较的是两个对象的内容是否相等,即内存地址可以不一样,内容一样就可以了,默认会调用对象的__eq__()方法
【如果内存地址相同,那么值肯定相同,但是如果值相同,内存地址不一定相同】

序列化和反序列化

json数据类型和python数据类型对应关系表

Json类型 Python类型
{} dict
[] list
"string" str
520.13 int或float
true/false True/False
null None

json和pickle模块

json和pickle模块,两个都是用于序列化和反序列化的模块
​
• json模块,用于字符串与python数据类型之间的转换
​
• pickle模块,用于python特有类型与python数据类型之间的转换,Python特有
​
两个模块,都提供了dumps,dump,loads,load 4个功能
序列化:转为str,dumps/dump
反序列化:转为dict,loads/load
import json
struct_data = {'name': 'json', 'age': 23, 'sex': 'male'}
​
data = json.dumps(struct_data)
data = json.loads(data)
​
with open('Json序列化对象.json', 'w') as fw:
    json.dump(struct_data, fw)
​
with open('Json序列化对象.json') as fr:
    data = json.load(fr)
import pickle
​
struct_data = {'name': 'json', 'age': 23, 'sex': 'male'
data = pickle.dumps(struct_data)
res = pickle.loads(data)
​
# 序列化(注意:pickle模块需要使用二进制存储,即'wb'模式存储)
with open('Pickle序列化对象.pkl', 'wb') as fw:
    pickle.dump(struct_data, fw)
​
# 反序列化
with open('Pickle序列化对象.pkl', 'rb') as fr:
    pickle = pickle.load(fr)

dumps/dump/load/loads的区别

dumps 将dict转化为str,序列化
loads 将str转化为dict,反序列化
​
dump和load的操作对象为文件

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

在序列化时,中文汉字总是被转换为unicode码,在dumps函数中添加参数ensure_ascii=False即可解决。
​
dict_temp = {'a': 1, 'b': 2}
str_result = json.dumps(dict_temp,ensure_ascii=False)

re的match/search/findall的区别

什么是正则的贪婪匹配?

(.*)贪婪模式,匹配一个字符串没有节制,能匹配多少就去匹配多少,直到没有匹配的为止
​
(.*?)非贪婪模式,会尽可能少的匹配

lambda表达式格式以及应用场景?

匿名函数:为了解决那些功能很简单的需求而设计的一句话函数
应用场景: 函数作为参数传递,经常与一些内置函数相结合使用,比如说map(),filter(),sorted(),reduce()等
​
函数名 = lambda 参数:返回值
#参数可以有多个,用逗号隔开
#匿名函数不管逻辑多复杂,只能写一行,且逻辑执行结束后的内容就是返回值
#返回值和正常的函数一样可以是任意数据类型
​
lambda 表达式
temp = lambda x,y:x+y
print(temp(4,10))   # 14
​
可替代:
def foo(x,y):
    return x+y
print(foo(4,10))    # 14

python的闭包

1.存在嵌套函数
2.外部函数的返回值是内嵌函数
3.内嵌函数可以访问外部函数的变量,但无法修改变量
def func(num):
    print('进入func')
    def func_in():
        print('进入func_in')
        print(2*num)
    print('结束func')
    return func_in
​
temp = func(2)
temp()
​
#
进入func
结束func
进入func_in
4

装饰器的写法以及应用场景

含义:装饰器本质就是函数,函数装饰器通过装饰器函数,在不修改原函数的前提下,来对函数的功能进行合理的扩充,是闭包函数的一种应用。
​
被“@函数”修饰的函数不再是原来的函数,而是被替换成一个新的东西(取决于装饰器的返回值),即如果装饰器函数的返回值为普通变量,那么被修饰的函数名就变成了变量名;同样,如果装饰器返回的是一个函数的名称,那么被修饰的函数名依然表示一个函数。
​
原则:
不修改被修饰函数的代码
不修改被修饰函数的调用方式
​
应用场景:
-flask路由系统
-flask before_request
-csrf
-django内置认证
-django缓存
-无参装饰器在用户登录认证中常见
-有参装饰器在flask的路由系统中见到过

什么是递归函数?在递归函数的使用中要注意什么地方?

递归函数就是自己调用自己。
注意:
1. 递归函数需要明确的有一个结束的条件。否则就会无限递归,从而超出python最大的递归深度。(sys 模块可修改递归深度,默认是1000)
2. 每次进入一层递归,问题的规模都应该比上一层有所减小。
3. 递归效率不高。 只用于特别的地方。

python递归的最大层数?

一般计算机默认的最大递归深度在1000左右,python最大递归深度一般在4000左右,跟计算
机的性能有关系,这个数不是一个定数,可通过一下方式测试
​
import sys
print(sys.getrecursionlimit())
print(sys.setrecursionlimit(10000))

赋值、浅拷贝和深拷贝

赋值:没有新建任何对象,就是原对象的一个别名,对象 id 和对象元素的 id 都是一样的;
浅拷贝:会分配一块新的内存用于创建新的拷贝对象,但拷贝对象中的元素依旧是原对象(被拷贝对象)中元素,即拷贝对象与原对象的 id 不同,但两者中的元素具有相同的 id;
深拷贝:会分配一块新的内存用于创建新的拷贝对象,拷贝对象中的元素是通过递归的方式将原对象中的元素一一复制过来的(可变元素除外,可变元素会创建一个新的对象,然后用原来对象的相应元素赋值之后指向新对象的元素),即对象与对象中的元素都是不同的 id,两者完全独立分离
​
1.拷贝的对象里的元素只有值,没有引用,那浅拷贝和深拷贝没有差别
2.拷贝的对象包含引用,修改引用的元素,浅拷贝(不拷贝引用)时会有影响,深拷贝(拷贝引用)时无影响
​
浅拷贝将一个对象的引用拷贝到另一个对象上,对象的修改相互影响,使用copy.copy(被拷贝对象)
深拷贝使用copy.deepcopy(被拷贝对象),将一个对象拷贝到另一个对象中,两个对象互不影响

简述 yield和yield from关键字(yield和return的区别)

python中yield的用法很像return,都是提供一个返回值,但是yield和return的最大区别在于,return一旦返回,则代码段执行结束,但是yield在返回值以后,会交出CUP的使用权,代码段并没有直接结束,而是在此处中断,当调用send()或者next()方法之后,yield可以从之前中断的地方继续执行
在一个函数中,使用yield关键字,则当前的函数会变成生成器,可以使用next()方便遍历生成器对象
yield from应用于多个生成器的嵌套

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

迭代器:
含有__iter__和__next__方法 (包含__next__方法的可迭代对象就是迭代器)
​
生成器:
包括含有yield这个关键字,生成器也是迭代器,调动next把函数变成迭代器
​
可迭代对象:列表、字典、元组
一个类内部实现__iter__方法且返回一个迭代器

迭代器和生成器

迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。
字符串,列表或元组对象都可用于创建迭代器:
使用了yield的函数被称为生成器
生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值,并在下一次执行 next() 方法时从当前位置继续运行

多线程

多线程优点

1.使用线程可以把占据长时间的程序中的任务放到后台去处理。 
2.用户界面可以更加吸引人,比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度。 
3.程序的运行速度可能加快。 
4.在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。

线程分类

内核线程:由操作系统内核创建和撤销。 
用户线程:不需要内核支持而在用户程序中实现的线程。

线程模块

Python3 通过两个标准库 _thread(废弃)和 threading(推荐)提供对线程的支持

Python常见基础面试题_第1张图片

线程同步

如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。 使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间

Python常见基础面试题_第2张图片

线程优先级队列( Queue)

Python 的 Queue 模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列 PriorityQueue。
这些队列都实现了锁原语,能够在多线程中直接使用,可以使用队列来实现线程间的同步。

什么是Flask?

Flask是Python编写的一款轻量级Web应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2。Flask使用 BSD 授权。其中两个环境依赖是Werkzeug和jinja2,这意味着它不需要依赖外部库。正因如此,我们将其称为轻量级框架。

Flask会话使用签名cookie让用户查看和修改会话内容。它会记录从一个请求到另一个请求的信息。不过,要想修改会话,用户必须有密钥Flask.secret_key。

有没有一个工具可以帮助查找python的bug和进行静态的代码分析?

PyChecker是一个python代码的静态分析工具,它可以帮助查找python代码的bug,会对代码的复杂度和格式提出警告

Pylint是另外一个工具可以进行codingstandard检查

编程题

进制转换

十进制为桥梁,先用int(值,进制位)转为十进制,再转换其他进制
​
# 二进制转换成十进制
print(int('0b1100011',2))
​
# 八进制转换成十进制
print(int('0o143',8))
​
# 十六进制转换成十进制
print(int('0x63',16))
​
# 十进制转换成二进制
print(bin(99))
​
# 十进制转换成八进制
print(oct(99))
​
# 十进制转换成十六进制
print(hex(99))
​
# 二进制转十六进制
print(hex(int('0b1100011',2)))

类型转换

int()-将任何数据类型转换为整数类型
float()-将任何数据类型转换为float类型
ord()-将字符转换为整数
hex()-将整数转换为十六进制
oct()-将整数转换为八进制
tuple()- 此函数用于转换为元组。
set()- 此函数在转换为set后返回类型。
list()- 此函数用于将任何数据类型转换为列表类型。
dict()- 此函数用于将顺序元组(键,值)转换为字典。
str()- 用于将整数转换为字符串。
complex(r eal,imag)-此函数将实数转换为复数(实数,图像)数。

生成随机数

生成一个随机浮点数:0到1之间的浮点数
    random.random()
    
生成一个指定范围的随机浮点数:范围[a,b]
    random.uniform(a,b) #如果a=b,则生成浮点数a
​
生成一个指定范围内的整数:范围[a,b]
    random.randint(a,b) 
    
不包含结束的随机数:start缺省值为0,step缺省值为1,范围[start,stop)
    random.randrange([start],stop,[step]) 
    
将一个列表中的元素打乱
    random.shuffle(list)
​
从序列中获取一个随机元素:序列包括list、tuple、字符串等
    random.choice(sequence)
    
从指定序列中随机获取n个元素作为一个片段返回:
    random.choices(sequence,k=n)
​
从指定序列中随机获取k个元素作为一个片段返回,sample函数不会修改原有序列
    random.sample(sequence,k)

常见的内置函数及其应用

数学相关

abs(a):求取绝对值。abs(-1)  
max(iterable):求取list最大值。max([1,2,3])
min(iterable):求取list最小值。min([1,2,3]) 
sum(iterable):求取list元素的和。 sum([1,2,3]) #6
sorted(iterable):排序,返回排序后的iterable。
len(iterable):list长度,len([1,2,3])
divmod(a,b): 获取商和余数。 divmod(5,2) #(2,1)
pow(a,b):获取乘方数。pow(2,3) #8
​
round(a,b):获取指定位数的小数。a代表浮点数,b代表要保留的位数。round(3.1415926,2) #3.14
range(a[,b]):生成一个a到b的数组,左闭右开。 range(1,10) #[1,2,3,4,5,6,7,8,9]

类型转换

int(str):转换为int型
    int('1') #1
float(int/str):将int型或字符型转换为浮点型
    float('1') #1.0
str(int):转换为字符型
    str(1) #'1'
bool(int):转换为布尔类型
    bool(0) #False 
    bool(None) #False
bytes(str,code):接收一个字符串,与所要编码的格式,返回一个字节流类型
    bytes('abc','utf-8') #b'abc' 
    bytes(u'爬虫','utf-8') #b'\xe7\x88\xac\xe8\x99\xab'
​
list(iterable):转换为list
    list((1,2,3)) #[1,2,3]
dict(iterable):转换为dict
    dict([('a',1),('b',2),('c',3)]) #{'a':1,'b':2,'c':3}
tuple(iterable):转换为tuple
    tuple([1,2,3]) #(1,2,3)
set(iterable):转换为set
    set([1,4,2,4,3,5]) #{1,2,3,4,5} set({1:'a',2:'b',3:'c'}) #{1,2,3}
​
iter(iterable):返回一个可迭代的对象
    iter([1,2,3]) #
enumerate(iterable):返回一个枚举对象
​
hex(int):转换为16进制
    hex(1024) #'0x400'
oct(int):转换为8进制
    oct(1024) #'0o2000'
bin(int):转换为2进制
    bin(1024) #'0b10000000000'
​
chr(int):转换数字为相应ASCI码字符
    chr(65) #'A'
ord(str):转换ASCI字符为相应的数字
    ord('A') #65

功能相关

reduce(func,sequence,initial):首先把序列的前两个元素传给函数,再把函数得到的结果和第三个元素,作为参数传给函数;
    reduce(lambda x,y: x + y,range(0,101)) #实现0到100求和 5050;
    
filter(func,iterable):通过判断函数fun,筛选符合条件的元素,返回列表迭代器
    list(filter(lambda x: x > 3,[3,4,1])) #[4]
​
map(func,*iterable):将一个或多个迭代器的每一个元素作为函数func的传参,返回一个list迭代器
    list(map(lambda a,b: a+b,[1,2,3,4],[5,6,7])) #[6,8,10]
​
zip(*iterable):一个或多个迭代器合并,返回列表嵌套元组型迭代器。
    list(zip([1,2,3],[4,5,6])) #[(1,4),(2,5),(3,6)]
    dict(zip([1,2,3],[4,5,6])) #{1:4,2:5,3:6}
​
reversed(sequence):生成一个反转序列的迭代器。 
    list(reversed('abc')) #['c','b','a']
​
type():返回一个对象的类型。
id(): 返回一个对象的唯一标识值。
hash(object):返回一个对象的hash值,具有相同值的object具有相同的hash值。 
    hash('python') #7070808359261009780
​
isinstance():判断一个对象是否为该类的一个实例。
issubclass():判断一个类是否为另一个类的子类。
eval():执行一个表达式,或字符串作为运算。 eval('1+1') #2
exec():执行python语句。 exec('print("Python")') #Python
help():调用系统内置的帮助系统。
globals():返回当前全局变量的字典。
next(iterator[,default]):接收一个迭代器,返回迭代器中的数值,如果设置了default,则当迭代器中的元素遍历后,输出default内容。

判断闰年

def func(yearNum):
    if yearNum % 400 == 0 or (yearNum % 4 == 0 and yearNum % 100 != 0):
        print(f'{yearNum}是闰年')
    else:
        print(f'{yearNum}年不是闰年')

将一个列表的每个元素乘方,返回新的序列

list_1=[1,2,3,4,5,6]
list(map(lambda x:x*x,list_1)) #[1,4,9,16,25,36]

按照首字母大写,后续字母小写的规则,规范英文名字的list

list_1=['adam','LISA','barT']
list(map(lambda x:x[0].upper()+x[1:].lower(),list_1))   # ['Adam','Lisa','Bart']

如何将一个数字四舍五入到小数点后三位

round(value,decimal_places)

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

f'{a}'
'%s%d%f' % ('a',1,0.1)
'{a}'.format('a')

斐波那契数列

x,y = 0,1
while x < 100:
    print(x)
    x,y = y,x + y
def fib(n):
    index,a,b = 0,0,1
​
    while index < n:
        yield b
        a,b = b,a+b
        index += 1
​
print(list(fib(5)))

九九乘法表

for i in range(1,10):
    for x in range(1,i + 1):
        print(f'{x}*{i}={x * i}',end=' ')
    print()
lis = ['%s%s=%s'%(i,j,ij) for i in range(1,10) for j in range(i,10)]

用一行代码实现数值交换

a = 1 
b = 2
​
a,b = b,a

利用切片操作,实现一个trim()函数,去除字符串首尾的空格(存在多个空格)

def trim(str):
    if str[0] == ' ':
        return trim(str[1:])
    elif str[-1:] == ' ':
        return trim(str[:-1])
    else:
        return str

请使用迭代查找一个list中最小和最大值,并返回一个tuple

def findMaxMin(list_temp):
    min,max = list_temp[0],list_temp[0]
    for x in list_temp:
        if x > max:
            max = x
        elif x < min:
            min = x
    return (min,max)

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

[i*i for i in range(1,11)]
​
print(list(map(lambda x: pow(x,2),range(1,11))))

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

list(set([1,2,3,4,45,1,2,343,2,2]))

计算一个文件中的大写字母数量

with open('文件名') as f:
    count=0
    for i in f.read():
        if i.isupper():
            count+=1
print(count)

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

import os
file = r'D:\test.txt'
if os.path.exists(file):
    os.remove(file)
    print('delete success')
else:
    print('no such file:%s' % file)

如何生成一个随机数?

import random
 
print(random.random())          # 用于生成一个0到1的随机符点数: 0 <= n < 1.0
print(random.randint(1,1000))  # 用于生成一个指定范围内的整数

利用random模块,写一个6位的随机验证码,验证码内包含字母、数字(随机出现)

import random
s = ''
for i in range(6):
    num = random.randint(0,9)
    alpha1 = chr(random.randint(65,90))     #A-Z
    alpha2 = chr(random.randint(97,122))    #a-z
    ret = random.choice([num,alpha1,alpha2])
    s += str(ret)
print(s)

请编写一个函数实现将IP地址转换成一个整数

10.3.9.12 转换规则为:
10           00001010
3            00000011
9            00001001
12           00001100

再将以上二进制拼接起来计算十进制结果:00001010 00000011 00001001 00001100 = ?
def func(x):
    lis = x.strip().split('.')
    li = [bin(int(i)) for i in lis]
    li2 = [i.replace('0b',(10-len(i))*'0') for i in li]
    return int(''.join(li2),2)
ret = func('10.3.9.12')
print(ret)

元组拆包和组包

def func_01(a,*args):
    print('a=',a)  # a= 1
    print('args=',args)  # args= (2,3,4)
    print('拆包 *args = ',*args)  # 拆包 *args =  2 3 4
​
    func_02(args)
    func_03(args)
​
def func_02(*args):
    print('func02 args=',args)  # func02 args= ((2,3,4),)
    print('func02 *args = ',*args)  # func02 *args =  (2,3,4)
​
def func_03(args):
    print('func03 args=',args)  # func03 args= (2,3,4)
    print('func03 *args=',*args)  # func03 *args= 2 3 4
​
func_01(1,2,3,4)

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

print('1,2,3'.split(','))

如何实现‘123’变成['1','2','3']

print(list(map(str,'123'))
print(list('123'))

如何实现[‘1’,’2’,’3’]变成[1,2,3]

print([int(x) for x in ['1','2','3']])

如何实现‘123’变成[1,2,3]

print(list(map(int,'123')))

列表套字典排序

user_list = [
    {'name': '张三','age': 22,'title': '测试工程师'},
    {'name': '李四','age': 24,'title': '开发工程师'},
    {'name': '王五','age': 21,'title': '测试工程师'}
]
​
user_list.sort(key=lambda x: x['age'])  # 升序
user_list.sort(key=lambda x: x['age'],reverse=True)  # 降序
print(user_list)

找到第一个只出现一次的字符,并返回它的位置

def findchar(temp):
    for i in temp:
        if temp.count(i)==1:
            return i, temp.index(i)
            
temp = 'hellobaby'
m,n=findchar(temp)
print('第一个出现一次的字符是{},位置是{}'.format(m,n))

数组中有一个数字出现的次数,超过数组长度的一半

def func(temp):
    for i in temp:
        if temp.count(i) > len(temp)/2:
            return i

给出一个32位的有符号整数,倒转这个整数

-123 > -321

123 > 321

12300 > 321

def func(val):
    if val > 0:
        temp = str(val)[-1::-1]
        print(int(temp))
    else:
        temp = int(str(val)[-1:0:-1])
        print(-temp)

已知成绩登记划分为:{"A":'90-100',"B":'80-89',"C":'60-79',"D":'0-59'}

(1)随机生成20个整数,范围0-100

(2)按等级归类,输出格式:{'A':[90,99,91],'B':[80,81,89],'C':[70,79,60],'D':[0,58,59]}

import random
​
res_dict = {}
list_a = []
list_b = []
list_c = []
list_d = []
​
for i in range(20):
    n = random.randint(0, 100)
    if 90 <= n <= 100:
        list_a.append(n)
    elif 80 <= n <= 89:
        list_b.append(n)
    elif 60 <= n <= 79:
        list_c.append(n)
    else:
        list_d.append(n)
    
res_dict["A"] = list_a
res_dict["B"] = list_b
res_dict["C"] = list_c
res_dict["D"] = list_d
print(res_dict)

将一个字符串中的空格替换成“%20”

str_data = 'wex cws asda asdw we'
​
# 方式一
res = str_data.replace(' ', '%20')
print(res)
​
#方式二
list_data = list(str_data)
for i in range(len(list_data)):
    if list_data[i] == ' ':
        list_data[i] = '%20'
​
res = ''.join(list_data)
print(res)

一行代码实现1-100的求和,一行代码实现1-100奇数求和,一行代码实现1-100偶数求和

sum(range(1, 101))
sum(range(1, 101, 2))
sum(range(2, 101, 2))

一行代码实现1-100偶数求和,至少5种方式

from functools import reduce
​
print(reduce(lambda x,y : x + y , range(2,101,2)))
print(sum(range(2,101,2)))

请用递归函数实现10的阶乘:10987....1

def factorial(num):
    if num <= 1:
        return 1
    return num * factorial(num-1)

在不改变列表中数据排列结构的前提下,找出以下列表中最接近最大值和最小值的平均值 的数 li = [-100,1,3,2,7,6,120,121,140,23,411,99,243,33,85,56]

li = [-100, 1, 3, 2, 7, 6, 120, 121, 140, 23, 411, 99, 243, 33, 85, 56]
mid = (max(li) + min(li)) / 2
res = abs(li[0] - mid)
​
result = None
for i in li:
    curr_min = abs(i - mid)
    if curr_min < res:
        res = curr_min
        result = i
print(result)

一年的第几天

'''
功能:输入某年某月某日,判断这是一年中的第几天
版本:4.0
'''
from datetime import datetime
​
def is_leap_year(year):
    '''
    判断year是否是闰年
    是:返回true
    否:返回false
    '''
    is_leap = False
    if (year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0)):
        is_leap = True
        return is_leap
 
def main():
 
    input_date_str = input('请输入日期(yyyymmdd)')
    input_date = datetime.strptime(input_date_str ,'%Y%m%d')
    year = input_date.year
    month = input_date.month
    day = input_date.day
 
    # #包含30天的月份集合
    # _30_days_month_set = {4,6,9,11}
    # _31_days_month_set = {1,3,5,7,8,10,12}
 
    #创建字典
    month_day_dict = {1:31,2:28,3:31,4:30,5:31,6:30,7:31,8:31,9:30,10:31,11:30,12:31}
 
    days = 0
    days += day
    for i in range(1,month):  #起始值从1开始
        days += month_day_dict [i]
 
    if month > 2 and is_leap_year(year) :
        days += 1
    print('这是{}年的第{}天。'.format(year,days))
 
 
if __name__=='__main__':
    main()

冒泡排序

list = [7,2,1,6,5,3,8,4]
​
for x in range(0,len(list)):
    for y in range(0,len(list)):
        if list[x] < list[y]:
            list[x],list[y] = list[y],list[x]
print(list)

二分查找

# 返回 x 在 arr 中的索引,如果不存在返回 -1
def binarySearch(arr, l, r, x):
    if r >= l:
        mid = int(l + (r - l) / 2)
        # 元素整好的中间位置
        if arr[mid] == x:
            return mid
            # 元素小于中间位置的元素,只需要再比较左边的元素
        elif arr[mid] > x:
            return binarySearch(arr, l, mid - 1, x)
            # 元素大于中间位置的元素,只需要再比较右边的元素
        else:
            return binarySearch(arr, mid + 1, r, x)
    else:
        # 不存在
        return -1
​
# 测试数组
arr = [2, 3, 4, 10, 40]
x = 10
result = binarySearch(arr, 0, len(arr) - 1, x)
if result != -1:
    print("元素在数组中的索引为 %d" % result)
else:
    print("元素不在数组中")

快速排序

def partition(arr,low,high): 
    i = ( low-1 )         # 最小元素索引
    pivot = arr[high]     
  
    for j in range(low , high): 
        # 当前元素小于或等于 pivot 
        if   arr[j] <= pivot: 
            i = i+1 
            arr[i],arr[j] = arr[j],arr[i]
    arr[i+1],arr[high] = arr[high],arr[i+1] 
    return ( i+1 ) 
  
# arr[] --> 排序数组
# low  --> 起始索引
# high  --> 结束索引
​
# 快速排序函数
def quickSort(arr,low,high): 
    if low < high:
        pi = partition(arr,low,high) 
        quickSort(arr, low, pi-1) 
        quickSort(arr, pi+1, high) 
​
arr = [10, 7, 8, 9, 1, 5] 
n = len(arr) 
quickSort(arr,0,n-1) 
print ("排序后的数组:") 
for i in range(n): 
    print ("%d" %arr[i])

求结果

def multipliers():
    return [lambda x:i*x for i in range(4)]
print([m(2) for m in multipliers()])     #[6,6,6,6]
print([ i % 2 for i in range(10) ])  # [0,1,0,1,0,1,0,1,0,1]
print([ i  for i in range(10) ])     # [0,1,2,3,4,5,6,7,8,9]
print([ 10 % 2])   # [0]
1 or 2      #1
1 and 2     #2
1 < (2==2)  #False
1 < 2 == 2  #True
print(int('111', 2))  #7
num = 5
def func():
    num = 10
    print('func', num)
​
def func2():
    print('func2', num)
func()    # 10
func2()    # 5

你可能感兴趣的:(Python,python)