首页 > 编程开发 > Python基础教程 >
-
python基础教程之Python知识点
试听地址 https://www.xin3721.com/eschool/pythonxin3721/
1.解释器锁(GIL)
一个进程在运行时假如有多个线程,同一时间只能有一个线程处于运行状态,霸占python解释器(即加了一把全局解释器锁,GIL),当遇到耗时操作,会释放GIL运行其他线程。所以多线程中线程的运行也是有先后顺序,并不是同时进行。多进程中每个进程都会有各自的一把锁,可以实现多个进程同时运行,程序的运行效率会加快,缺点是系统开销大。
2.内建数据类型
- 数字类型(包括整数型和浮点类型)
- 字符串
- 布尔值
- 列表(list)
- 元组(tuple)
- 字典(dict)
- 集合(set)
3.数据结构
- 列表(list)
- 元组(tuple)
- 字典(dict)
- 集合(set)
4.__new__和__init__方法的区别
- __init__是构建函数,比较常用;__new__是实例化方法,不太常用
- __init__实例级别的函数,__new__类级别的函数
- __new__是创建一个新的实例,__init__构建一些实例的属性,__new__在__init__之前执行
- __new__必须要有一个参数(cls)代表当前类,且必须有返回值,表示生成的实例,可以是父类__new__出来的实例,也可以是Object__new__出来的实例;__init__必须要有一个参数(self)表示当前实例,不需要有返回值
5.with方法打开文件做了什么
如果按照正常的f.open()方法打开文件可能会出现一些异常,此时要写try、except、finally做异常判断,且无论如何都要在finally中关闭文件,即f.close(),with帮我们实现了finally中的f.close()
6.列表[1,2,3,4,5],请使用map()函数输出[1,4,9,16,25],并使用列表推导式提取出大于10的数,最终输出[16,25]
def test(num): # 幂运算 return num ** 2 l = [1,2,3,4,5] m = map(test,l) l2 = [i for i in m if i > 10] print(l2)
7.python中生成随机整数、随机小数、0—1之间小数方法
import random # 生成0-1之前的随机小数 print(random.random()) # 生成指定范围内的随机整数 print(random.randint(0,100)) # 生成随机小数 # 导入numpy库 import numpy # 生成5个随机小数 print(numpy.random.randn(5))
8.<div class="nam">中国</div>,用正则匹配出标签里面的内容(“中国”),其中class的类名是不确定的
import re str = '<div class="nam">中国</div>' t = re.findall(r'<div class=".*">(.*?)</div>',str) print(t)
9.python2和python3区别?列举5个
- python2中print函数可以用小括号包括要打印的内容,也可以用空格隔开;python3只能用小括号
- python2中unicode表示字符串序列,str表示字节序列;python3中str表示字符串序列,byte表示字节序列
- python中用raw_input()函数,python3使用input()
- python2为正常显示中文,需要引入coding;python3不需要
- python2使用ascii编码;python3使用utf-8编码
- python2中ranage(1,10)返回是一个数字列表;python3返回是一个迭代器,节约内存
10.列出python中可变数据类型和不可变数据类型,并简述原理
可变对象:列表list、字典dict
对这些数据类型进行操作时,只是修改变量的值,变量在内存中引用的地址还是同一个不会改变。
不可变对象:数值、字符串、元组tuple
相同值的对象在内存中只有一个地址,修改值即新建了一个对象,变量在内存中引用的地址会改变。
11. s = “ajldjlajfdljfddd”,去重并从小到大排序输出”adfjl”
s = "ajldjlajfdljfddd" se = set(s) l = [] for i in se: l.append(i) l.sort() # 这里注意:因为字符串是不可变数据类型, # 所以要先转换成列表排序,最后拼接成字符串 str1 = '' for i in l: str1 += i print(str1)
12.字典根据键从小到大排序
d={"name":"zs","age":18,"city":"深圳","tel":"1362626627"} d1 = {i:d[i] for i in sorted(d)} print(d1)
13.利用collections库的Counter方法统计字符串每个单词出现的次数”kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h”
from collections import Counter str1 = 'kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h' c = Counter(str1) print(c)
14.字符串a = “not 404 found 张三 99 深圳”,每个词中间是空格,用正则过滤掉英文和数字,最终输出”张三 深圳”
import re a = "not 404 found 张三 99 深圳" l = a.split(' ') num_str = re.findall(r'\d+|[a-z]+',a) for i in num_str: if i in l: l.remove(i) new_str = "".join(l) print(new_str)
15.正则re.complie作用
把正则表达式编译成一个对象,方便重复使用。
16.数据库优化查询方法
# 定义异常类,继承Exception基类 class MyException(Exception): # def __init__(self,*args,**kwargs): # self.args = args # self.kwargs = kwargs pass def test(num1,num2): try: total = num1 * num2 if total % 2 == 0: raise MyException('我自闭了!') else: print(total) except Exception as e: print(e) test(5,3)
19.正则表达式匹配中,(.)和(.?)匹配区别?
(.*):贪婪匹配,会把符合正则的尽可能多的往后匹配
(.*?):非贪婪匹配,尽可能少匹配
20.简述Django的orm
ORM,意为对象-关系映射,只需要简单的配置就可以变更数据库,不需要修改代码,只需要面向对象编程;ORM可以根据数据库引擎,翻译出对应的SQL语句,所以使用Django框架的项目可以不用关心底层使用的是什么数据库,如果数据库迁移,只用变更数据库引擎即可。
21.举例说明zip()函数用法
# 把两个可迭代的内容组合在一起生成一个tuple类型组成的内容 l1 = ['a','b','c'] l2 = [1,2,3] for i in zip(l1,l2): print(i)
22.提高python运行效率的方法
- 使用生成器,可以节约大量内存
- 多线程、多进程、协程
- 循环代码优化,避免过多重复代码执行
- 核心代码使用Cpython、PyPy等
- 多个if,elif条件判断,可以把最有可能发生的写在前面,可以减少程序判断的次数,提高效率
23.简述mysql和redis区别
Mysql:关系型数据库,数据存储在硬盘中,读写会有IO操作,速度相对较慢
Redis:内存型非关系数据库,数据保存在内存中,读写速度快
24.遇到bug如何处理
- 首先根据报错信息,定位大概出错的地方
- 一般细节上的错误,用print()打印分段检测程序的问题,如果能正常执行到print(),说明上面代码没问题;js可以用alert()或者console.log()
- 对于BUG的管理和归类总结,一般测试人员将测试出来的BUG提交到BUG管理工具上,我会根据提交的BUG一条一条的修改,修改的过程也是理解项目业务逻辑和提高编程逻辑缜密性的方法,最后我会对修改过的BUG做收藏和笔记记录
25.正则匹配,匹配日期2018-03-20
url=’https://sycm.taobao.com/bda/tradinganaly/overview/get_summary.json?dateRange=2018-03-20%7C2018-03-20&dateType=recent1&device=1&token=ff25b109b&_=1521595613462‘
url='https://sycm.taobao.com/bda/tradinganaly/overview/get_summary.json?dateRange=2018-03-20%7C2018-03-20&dateType=recent1&device=1&token=ff25b109b&_=1521595613462' import re re_com = re.compile(r'dateRange=(.*?)%7C(.*?)&') find_str = re_com.findall(url) print(find_str)
26.list=[2,3,5,4,9,6],从小到大排序,不许用sort,输出[2,3,4,5,6,9]
# 思路:获取列表中的最小值添加到新列表,然后删除老列表中最小元素,重复操作 l=[2,3,5,4,9,6] l2 = [] def get_min(l): min_value = min(l) l2.append(min_value) l.remove(min_value) for i in range(len(l)): get_min(l) print(l2)
27.写一个单例模式
单例模式:简单来说就是无论实例化多少次,都只有一个对象;比如,ORM模型关系映射时,只需要生成一个对象和数据库对接
class single(): # 声明一个类变量用来存放生成对象方法的引用 # 如果该值为空,说明没有生成过对象;反之,直接返回该对象的引用 _instance = None def __new__(cls,name,age): if not cls._instance: cls._instance = object.__new__(cls) return cls._instance s1 = single('张三',18) s2 = single('李四',19) s1.sex = 1 print(s1.sex) print(s2.sex) print(id(s1)) print(id(s2))
28.保留两位小数,题目本身只有a=”%.03f”%1.3335,让计算a的结果,为了扩充保留小数的思路,提供round方法(数值,保留位数)
a="%.03f"%1.3335 print(a,type(a)) print(float(a),type(float(a))) print(round(float(a),2))
29.列出常见的状态码和意义
- 200 OK:请求成功
- 400 Bad Request:客户端请求有语法错误,不能被服务器所理解
- 401 Unauthorized:请求未经授权
- 403 Forbidden:服务端收到请求,但拒绝提供服务
- 404 Not Found:请求资源不存在
- 500 Internal Server Eroor:服务端发生不可预估的错误
- 501 Server Unavailable:服务器不能处理当前客户端的请求,一段时间后可能恢复正常
30.分别从前端、后端、数据库阐述web项目的性能优化
前端:
- 尽量减少HTTP请求
- 将HTML和CSS放在页面上部,JS放在页面下部;因为JS加载比HTML和CSS慢,所以要优先加载HTML和CSS,以防页面加载不全,性能差,影响用户体验
后端:
- 缓存存储读写次数高,变化少的数据;应用程序读取数据时,先从缓存中读取,如果数据不存在或已失效,再读取磁盘数据库,并将数据再放入缓存
- 如果程序有耗时操作,采用异步
- 代码方面,尽量减少循环和if条件判断,有多个if else时,优先判断最有可能发生的情况
- 将动态页面换成html,用nginx访问
数据库:
- 选用合适的数据库,如果有条件可以将数据存放在redis,读写速度快
- 添加外键,索引等
31.使用pop和del删除字典中的”name”字段,dic={“name”:”zs”,”age”:18}
dic={'name':'zs','age':18} #del dic['name] dic.pop('name) print(dic)
32.列出常见MYSQL数据存储引擎
- cookie存在客户端(浏览器),session运行在服务器端
- cookie的安全性比session差
- session的运行依赖sessionID,sessionID存放在cookie中,如果浏览器禁用了cookie,session就会失效;存储session时,session的键是cookie中的sessionID,值为开发人员添加的键值对,进行了base64编码,失效时间由开发人员设置
35.简述多线程、多进程
进程:
- 操作系统进行资源分配和调度的基本单位,多个进程之前相互独立
- 稳定性好,如果一个进程崩溃,不影响其他进程,但是进程消耗资源大,开启的进程数量有限制
线程:
- CPU进行资源分配和调度的基本单位,线程是进程的一部分,是比进程更小的能独立运行的基本单位,一个进程下的多个线程可以共享该进程下的所有资源
- 如果IO密集型,可以用多线程,缺点是如果一个线程崩溃,都会造成一个进程的崩溃
应用:
IO密集型用多线程,CPU密集型用多进程
36.简述any()和all()方法
any:迭代器中只要有一个元素为真(不为空或0),则返回True;否则,返回False,空迭代器也返回False
all:迭代器中全部元素为真(不为空或0),返回True;否则,返回False,空迭代器也返回True
37.IOError、AttributeError、ImportError、IndentationError、IndexError、KeyError、SyntaxError、NameError分别代表什么异常
- 复制不可变数据类型(元组、字符串、数值等):浅拷贝和深拷贝都和赋值 “=” 一样,id地址和值都跟被复制对象相同
-
复制可变数据类型(列表、字典):
-
浅拷贝分为两种情况:
- 拷贝对象无复杂子元素:修改拷贝对象元素,或者修改浅拷贝后的对象的元素,都对对方没有影响,但id地址不同
- 拷贝对象有复杂子元素:修改拷贝对象子元素,或者修改浅拷贝后的对象的子元素,都会影响对方的值,id地址不同
- 深拷贝是完全独立的复制,无论有无复杂子元素,修改拷贝对象元素或者修改深拷贝后对象的元素,都对对方没有影响,id地址不同
-
浅拷贝分为两种情况:
39.列出几种魔法方法并简要介绍用途
- __init__:构造函数,实例化对象时自动调用
- __new__:创建对象执行的方法,单例模式使用
- __str__:当对象被当做字符串使用时调用,最常用的就是print输出对象,会输入__str__方法中return的内容
- __del__:删除对象时执行的方法(删除对象:如果对象赋值了多个变量,删除其中一个变量对对象的引用并不会直接删除对象,必须删除所有对对象引用的变量才会删除对象)
40.请将[i for i in range(3)]改成生成器
将中括号换成小括号即可
# 列表生成式、推导式 a = [i for i in range(3)] print(type(a)) print(a) print("========================================") # 列表生成器 b = (i for i in range(3)) print(type(b)) print(b) for i in b: print(i)
41.使用lambda函数对list排序foo = [-5,8,0,4,9,-4,-20,-2,8,2,-4],输出结果为[0,2,4,8,8,9,-2,-4,-4,-5,-20],正数从小到大,负数从大到小
foo = [-5,8,0,4,9,-4,-20,-2,8,2,-4] # 方法一:列表拼接 print(sorted(filter(lambda num:num>=0,foo))+sorted(filter(lambda num:num<0,foo),reverse=True)) # 方法二: # 这里注意[::-1]和[:-1]的区别: # [::-1]表示可迭代对象元素的反转,比如a='python',a[::-1]输出'nohtyp',a[::-2]输出'nhy' # [:-1]表示可迭代对象最后一位之前的所有元素,比如b='java',b[:-1]输出'jav' print(sorted(filter(lambda num:num>=0,foo))+sorted(filter(lambda num:num<0,foo))[::-1]) # 方法三:根据sorted()方法的key参数,如果元素小于0则取绝对值排序 print(sorted(foo,key=lambda num:(num<0,abs(num))))
42.列表嵌套字典的排序,分别根据年龄和姓名排序
l = [{'name':'张三','age':18},{'name':'李四','age':20},{'name':'王五','age':6}] print(sorted(l,key=lambda k:k['name'],reverse=True))
43.列表嵌套元组,分别按字母和数字排序
l = [('a',4),('b',3),('c',1)] print(sorted(l,key=lambda x:x[1]))
44.列表嵌套列表排序,年龄数字相同怎么办?
l = [['d',39],['aaa',66],['bbb',39],['ccc',18]] # 添加参数,如果第一个参数的值相同,则按照第二个参数的值进行排序 print(sorted(l,key=lambda num:(num[1],num[0])))
45.根据键对字典排序
d = {'name':'wawaw','sex':'1','age':18} # d.items()生成的是一个列表嵌套的元组,每个元组里包含键值对 s = sorted(d.items(),key=lambda x:x[0]) # 字典生成式 print({i[0]:i[1] for i in s})
46.举例说明SQL注入和解决办法
当以字符串格式化书写方式的时候,如果用户输入的有“;SQL语句”,后面的SQL语句会执行,比如下面例子中的demo数据库会被删除
input_name = 'master' sql = 'select * from t_user where name="%s"' % input_name print("这是正常的SQL语句"+sql) input_name = 'master;drop database demo' sql = 'select * from t_user where name="%s"' % input_name print("这是SQL注入的语句"+sql)
解决方式:通过传参数方式解决SQL注入
input_name = 'master' # 通过参数化的方式解决 params = [input_name] # cs1为数据库的游标,execute()方法提供参数化的方式解决SQL注入 sql = cs1.execute('select * from t_user where name="%s"',params)
47.s=”info:xiaoZhang 33 shandong”,用正则切分字符串输出[‘info’, ‘xiaoZhang’, ‘33’, ‘shandong’]
import re s = " info:xiaoZhang 33 shandong" # |表示或 print(re.split(':| ',s))
48.正则匹配以163.com结尾的邮箱
import re email = ['a123@qq.com.qq