<font color="#dd0000">浅红色字体</font>  # markdown的备忘录
  • 本文是学习过程中积累的python知识(欢迎补充鸭),另外可以学习《编写高质量代码:改善Python程序的91个建议》
  • 其他知识点:用trackback获取栈信息、用py自带的logging日志、熟悉py对象协议。

文章目录

1、copy 和 deepcopy 的区别是什么?

python中的对象之间的赋值是按引用传送的。
(1)copy()浅拷贝,只拷贝父对象,不会拷贝对象的内部的子对象。

(2)deepcopy()深拷贝,拷贝父对象及其子对象。

#!/usr/bin/python
## -*-f= coding:utf-8 -*-
import copy
origin=[1,2,[3,4]]
cop1=origin #引用
cop2=copy.copy(origin)#浅拷贝
cop3=copy.deepcopy(origin)#深拷贝
origin[2][0]="hey!"
origin[0]="hey!"

print("原来的值:",origin)
print("引用值:",cop1)
print("浅拷贝:",cop2)
print("深拷贝:",cop3)
print("---------------")

print("初始对象地址",id(origin[0]))
print("引用的对象地址",id(cop1[0]))
print("浅拷贝对象地址",id(cop2[0]))
print("深拷贝对象地址",id(cop3[0]))
print("---------------")

print("初始对象地址",id(origin[2][0]))
print("引用的子对象地址",id(cop1[2][0]))
print("浅拷贝子对象地址",id(cop2[2][0]))
print("深拷贝子对象地址",id(cop3[2][0]))

结果为如下:

原来的值: ['hey!', 2, ['hey!', 4]]
引用值: ['hey!', 2, ['hey!', 4]]
浅拷贝: [1, 2, ['hey!', 4]]
深拷贝: [1, 2, [3, 4]]
---------------
初始对象地址 1497843333168
引用的对象地址 1497843333168
浅拷贝对象地址 1497801451824
深拷贝对象地址 1497801451824
---------------
初始对象地址 1497843333168
引用的子对象地址 1497843333168
浅拷贝子对象地址 1497843333168
深拷贝子对象地址 1497801451888

py没有赋值,只有引用。py没有变量,平时说的变量只是标签,即引用。

不可变对象:数字 字符串 元组 ;可变对象:字典 列表 字节数组。
不可变对象包括int,float,long,str,tuple等
对于不可变类型的变量,如果要更改变量,则会创建一个新值,把变量绑定到新值上,而旧值如果没有被引用就等待垃圾回收。

2、代码中经常遇到的*args, **kwargs 含义及用法。

args表示任意位置参数,* kwargs表示任意个关键字参数
用法:def 函数名(位置参数,args,默认参数,**kwargs),记得arg在kwargs之前

#!/usr/bin/python
## -*-f= coding:utf-8 -*-
def Func(a,b,*args,**kwargs):
print (a)
print (b)
print (args)
print (kwargs)

Func(0,1,2,3,index1=11,index2=22)

输出的结果为:

0
1
(2, 3)
{'index1': 11, 'index2': 22}

注意(2,3)是因为不定的参数形式把剩下没有关键字的参数形成为一个​​tuple​​,另外后面2个是赋值关系,会变为字典。

PS:python中函数既不传值也不传引用,是传对象,如果下面的例子swap函数是传入c[0],c[1]会发现是不能交换2个值的:

#!/usr/bin/env python
def swap(c):
c[0], c[1] = c[1], c[0]

c = [1, 2]
swap(c)
#c[0], c[1] = c[1], c[0]
print(c) # 打印出[2, 1]

3、Python 中会有函数或成员变量包含单下划线前缀和结尾,和双下划线前缀结尾,区别是什么?

单下划线:

(1)变量为保护变量(只有类对象和子类对象可以访问这些变量)
(2)函数为不能直接访问的类属性,要通过类提供的接口来访问

双下划线:

(1)变量为私有成员(只有类对象自己可以访问,子类对象不能访问该成员)
(2)py里的特殊方法专用的标志符,如__ init()__表示类的构造函数

4、w、a+、wb 文件写入模式的区别

模式

作用

若文件不存在

是否覆盖

w

只写

创建


a+

可读可写

创建

否,追加写

wb

只写,以二进制写方式打开

创建


其他几个

r+

可读可写

报错


w+

可读可写

创建


a

只能写

创建

否,追加写

5、举例 sort 和 sorted 的区别

(1)sort是直接应用在list上排序

>>> lst1=[(8,'andy',20),(2,'liu',21),(5,'luo',22)]
>>> lst1.sort()
>>> lst1
[(8, 'andy', 20), (2, 'liu', 21), (5, 'luo', 22)]

(2)sorted可对所有可迭代的对象进行排序,如果对list操作则是产生一个新的列表。

>>> list1=[(8,'andy',20),(2,'liu',21),(5,'luo',22)]
>>> sorted(list1)
[(2, 'liu', 21), (5, 'luo', 22), (8, 'andy', 20)]
>>> list1
[(8, 'andy', 20), (2, 'liu', 21), (5, 'luo', 22)]

6、用python实现快速排序算法

https://www.jb51.net/article/158963.htm 这里有2种方法

#!/usr/bin/python
## -*-f= coding:utf-8 -*-
def QuickSort(lst1,i,j):#i左,j为右
if i >= j:
return lst1
pivot = lst1[i]
low = i
high = j

# 划分枢轴
while i < j:
while i < j and lst1[j] >= pivot:
j -= 1
lst1[i]=lst1[j]
while i < j and lst1[i] <=pivot:
i += 1
lst1[j]=lst1[i]
lst1[j] = pivot

QuickSort(lst1,low,i-1)
QuickSort(lst1,i+1,high)
return lst1

if __name__=="__main__":
lst1=[30,24,5,58,18,36,12,42,39]
print("排序前的序列为:")
for i in lst1:
print(i,end =" ")
print("\n排序后的序列为:")
for i in QuickSort(lst1,0,len(lst1)-1):
print(i,end=" ")

注意函数名为驼峰命令,单词开头大写;
注意命名规范:对于局部变量情况,list列表前缀为lst,tuple前缀为t,字典的前缀为d,其他按照开头第一个小写字母,如整型i、浮点型f、字符串s、布尔型b。
输出结果为

排序前的序列为:
30 24 5 58 18 36 12 42 39
排序后的序列为:
5 12 18 24 30 36 39 42 58

7、isinstance 作用以及应用场景?

格式为isinstance(p,类型),即判断p是否为对应类型。

#!/usr/bin/python
## -*-f= coding:utf-8 -*-
p='123'
print(isinstance(p,str))#判断p是否为字符串类型

8、什么是断言?应用场景?

断言由assert方法实现,只有成功了程序才继续执行,否则报错。
格式为【assert 表达式,返回数据】,当表达式为false时触发异常,返回数据。

#!/usr/bin/python
## -*-f= coding:utf-8 -*-
try:
n=input("请输入一个数字:")
assert n.isdigit(),"只能输入数字"
print("你输入的是:",n)
except Exception as ex:
print("发现错误:",ex)

结果为:

请输入一个数字:4你输入的是: 4
>>>

9、Python 中的异常处理,写一个简单的应用场景

#!/usr/bin/python
## -*-f= coding:utf-8 -*-
try:
a=open("testfile","r+")
a.write("该为测试异常的文件")
except IOErrror:
print("Error:没有找到文件或读取文件失败")
else:
print("内容写入文件成功")
a.close()

如果一开始没有testfile文件则会输出:Error:没有找到文件或读取文件失败。

异常处理https://www.runoob.com/python/python-exceptions.html

10、Python 中递归的最大次数,那如何突破呢?

默认最大次数为1000次,但可以用sys的​​setrecursionlimit​​突破:

#!/usr/bin/python
## -*-f= coding:utf-8 -*-
import sys
sys.setrecursionlimit(1500)
def Recursion(n):
if(n<=0):
return
print(n)
Recursion(n-1)
if __name__ =="__main__":
Recursion(1000000)

11.py2和py3的区别

(1)py2中对2个整数做除法默认是整除(向下取整)
(2)print从语句变为函数,原 print 1,2+3改为print(1,2+3)

range(0,4)结果是列表[0,1,2,3]改为list(range(0,4))
字符串以8bit字符串存储改为字符串以16bit unicode字符串存储
py2中的utf-8和gbk转换才要2次

py2同时支持ASCII和Unicode字符串,默认情况下是ASCII编码;
py3,默认类型为ASCII编码,而字符串现在称为bytes(bytes数据结构包含字节值,且它不应该再被视为一个字符串,因为它是一个包含数据的不可变字符数组)

注意:考虑兼容性,尽可能用unicode:py2定义字符串:string = u"abc",单py3则默认为unicode了。

12.gbk和utf-8编码

GBK编码方式的编码是以中国国情而创造的,在国际上的兼容性不好,这也是为什么大多数的网页是使用UTF-8编码而不是GBK。
py3中默认编码是unicode,而py2中默认编码是ASCII

GBK转码:​​javascript:void(0)​

13.python数据序列化json,marshal

序列化:将某种编程语言的数据类型或对象转换为可通过网络传输或可以存储到本地磁盘的数据格式(如XML、JSON或特定格式的字节串)的过程。
json模块常用语编写web接口,将Python数据转换为通用的json格式传递给其它系统或客户端;也可以用于将Python数据保存到本地文件中,缺点是明文保存,保密性差。
pickle和shelve模块序列化后的数据只能被python识别。

一般用法:

  • 需要与外部系统交互时用json模块;
  • 需要将少量、简单Python数据持久化到本地磁盘文件时可以考虑用pickle模块;
  • 需要将大量Python数据持久化到本地磁盘文件或需要一些简单的类似数据库的增删改查功能时,可以考虑用shelve模块。

下面以shelve为例,只提供open方法,用key来访问(和字典类似)

import shelve
f = shelve.open('test1')
f['key'] = {'a':1, 'b':2, 'c':'sss'} #直接对文件句柄操作,就可以存入数据
f['key2'] = {'d':3, 'e':4, 'f':'ddd'}
f.close()

f1 = shelve.open('test1')
dic1 = f1['key'] #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
dic2 = f1['key2']
f1.close()
print(dic1)
print(dic2)

Python的marshal模块,负责在Python数值与二进制字节对象之间进行转换的。
操作二进制文件。

import marshal  #导入模块
x1=30 #待序列化的对象
x2=5.0
x3=[1,2,3]
x4=(4,5,6)
x5={'a':1,'b':2,'c':3}
x6={7,8,9}
x=[eval('x'+str(i)) for i in range(1,7)] #把需要序列化的对象放在一个列表中
print(x)
# [30, 5.0, [1, 2, 3], (4, 5, 6), {'c': 3, 'b': 2, 'a': 1}, {8, 9, 7}]
with open('test.dat','wb')as fp: #创建二进制文件
marshal.dump(len(x),fp) #先写入对象个数
for item in x:
marshal.dump(item,fp) #把2列表中的对象依次序列化并写入文件呢
with open('test.dat','rb')as fp:
n=marshal.load(fp) #获取对象个数
for i in range(n):
print(marshal.load(fp)) #反序列化,输出结果
# 30
# 5.0
# [1, 2, 3]
# (4, 5, 6)
# {'c': 3, 'b': 2, 'a': 1}
# {8, 9, 7}

14.python垃圾回收

py垃圾回收主要以引用计数为主,缺点:不能解决对象的“循环引用”、需要额外空间维护引用计数

以下四种情况,对象的引用计数+1:
对象被创建(a=11)、对象被引用(b=a)、对象被作为参数传到函数中 func(a)、对象作为一个元素存储在容器中(如lst1=[a,a])

以下四种情况,对象的引用计数-1:
对象的别名被显式销毁 del a、对象的别名被赋予新的对象 a=66、一个对象离开其作用域(如fun函数执行完,fun里的局部变量,注意全局变量不会),对象所在的容器被销毁或从容器中删除对象

#!/usr/bin/python
## -*- coding: utf-8 -*-
import sys
def func(c):
print ('in func function',sys.getrefcount(c)-1)

print ('init',sys.getrefcount(11)-1)
a=11
print ('after a=11----',sys.getrefcount(11)-1)
b=a
print ('after b=a----',sys.getrefcount(11)-1)
func(11) #调用函数中是+2:另一个引用是函数栈保存了入参对形参的引用
print ('after func(11)----',sys.getrefcount(11)-1)
lst1=[a,12,14]
print ('after lst1=[a,12,14]----',sys.getrefcount(11)-1)
a=666
print ('after a=666----',sys.getrefcount(11)-1)
del a
print ('after del a----',sys.getrefcount(11)-1)
del b
print ('after del b----',sys.getrefcount(11)-1)
del lst1
print ('after del lst1----',sys.getrefcount(11)-1)

结果为

init 50
after a=11---- 51
after b=a---- 52
in func function 54
after func(11)---- 52
after lst1=[a,12,14]---- 53
after a=666---- 52
after del a---- 52
after del b---- 51
after del lst1---- 50

15.py2,3字符编码和gbk,utf-8相互转换

py2中默认编码是ASCII,py中则是unicode
(1)在python2中:

#!/usr/bin/python
## -*- coding:utf-8 -*-

#情况一:字符非unicode
s="五一放假"
#utf-8编码转成unicode
sToUnicode=s.decode("utf-8")
print(sUnicode)

#然后unicode再编码成gbk
sToGbk=sToUnicode.encode("gbk")
print(sToGbk)

#情况二:字符已经是unicode
s=u'五一放假'
print(s)
sToGbk=s.encode("gbk")
print(sToGbk)

打印输出四个五一放假。注意文件头要指定字符编码,上面是utf-8,打印中文能打出,但是如果不指定而默认函使用系统编码,如ASCII则会报错(ASCII不能存中文字符)。

(2)在python3中:默认是unicode,所以一开始的字符编码之间的转换直接encode

#!/usr/bin/python
## -*- coding: utf-8 -*-
s='五一放假'
# 字符串s已经是unicode编码,不用decode
sToGbk=s.encode("gbk")
print(sToGbk)

#将gbk先转成unicode,再编码成utf-8
sToUtf=sToGbk.decode("gbk").encode("utf-8")
print(sToUtf)

py3中encode编码会将string类型转成bytes类型。
不管是否在py3的文件开头申明字符编码,只能表示该py文件是该字符编码,文件中的字符串还是unicode。

-8 , 字符串编码是 unicode
       以utf-8 或者 gbk等编码的代码,加载到内存,会自动转为unicode正常显示。

 python2  文件默认编码是ascii , 字符串编码也是 ascii , 如果文件头声明了是gbk,那字符串编码就是gbk。
       以utf-8 或者 gbk等编码的代码,加载到内存,并不会转为unicode,编码仍然是utf-8或者gbk等编码。

16.python的作用域

一、命名空间有三种:
(1)内置名称:内置函数名ans、char,异常名称BaseException即所有异常的基类,Exception为常规错误的基类
(2)全局名称:模块的变量、函数、类等
(3)局部名称:函数的参数变量等,类同理

命名空间的查找顺序为:局部-》全局-》内置
相同的对象名称可以存在于多个命名空间中

作用域:直接访问一个变量会从内到外访问所有的作用域直到找到。分为4种。

【Python】基础知识整理_爬虫


二、作用域

  • E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。

(1)global全局
如果下面的global漏了则会报错(UnboundLocalError: local variable ‘num’ referenced before assignment),因为第一个打印num时的num是局部(未定义,无值)

#!/usr/bin/python
## -*- coding: utf-8 -*-
num=1
def fun1():
global num #需要使用global
print(num)
num=123
print(num)
fun1()
print(num)

(2)修改嵌套作用域(enclosing作用域,外层非全局作用域)中的变量——nonlocal

#!/usr/bin/python3
## -*- coding:utf-8 -*-
def outer():
num=10
def inner():
nonlocal num # num作用域则扩大到外层了
num=100
print(num)
inner()
print(num)
outer()

17.链接字符串

链接字符串有限用join而不是+,时间复杂度更低,如

>>> seq1 = ['hello','good','boy','doiido']
>>> print ' '.join(seq1)

str和repr都是将对象转为字符串。

18.is和==不同

is判断的是存储位置是否相等,==判断值是否相等

另外:i+=1不等于++i,python中别使用​​i++​​​,因为Python的模型规定,数值对象是不可改变的。 ​​i = i + 1​​ 相当于重新创建了一个变量 i ,而不是改变了 i 中的数值。

19.append和extend区别:

用append:

x = [1, 2, 3]
x.append([4, 5])
print (x) #[1, 2, 3, [4, 5]]

用extend:

x = [1, 2, 3]
x.extend([4, 5])
print (x) # [1, 2, 3, 4, 5]

20.enumerate用法

>>>seq = ['one', 'two', 'three']
>>> for i, element in enumerate(seq):
... print i, element
...
0 one
1 two
2

21.弱引用&强引用

弱引用是避免循环引用的一种方法,弱引用不记录引用计数。当一个对象只有弱引用时可能被垃圾回收器回收。

weakref.ref(obj,[callable])用于建立一个指向obj的弱引用,当对象被回收前callable可选参数指定的函数将被执行以进行清理工作。

更多资料:
(1)​​​https://yuerblog.cc/2018/08/28/python-weakref-real-usage/​​​ (2)​​javascript:void(0)​

22.lambda表达式

lambda用来创建匿名函数,函数体比def简单很多。Python 之中,类似能用到 lambda 表达式的「高级」函数还有 reduce、filter 等等。
lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。

将一个 list 里的每个元素都平方,啰嗦写法:

def sq(x):
return x*x
a = map(sq, [y for y in range(10)])
# map类型的参数需要用list()方法来转换
print(list(a))
# 输出[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

用lambda后:

b = map(lambda x:x*x, [y for y in range(10)])
print(list(b))
# 输出和上面相同
map(function, iterable, ...) # map用法:以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
map( lambda x : x + 1, [1, 2, 3] ) # 另外的例子:结果为 [2, 3, 4]

更多详细:​​javascript:void(0)​

23.闭包

在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。

一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。
外函数返回了内函数的引用:

#闭包函数的实例
# outer是外部函数 a和b都是外函数的临时变量
def outer(a):
b = 10
# inner是内函数
def inner():
#在内函数中 用到了外函数的临时变量
print(a+b)
# 外函数的返回值是内函数的引用
return inner

if __name__ == '__main__':
# 在这里我们调用外函数传入参数5
#此时外函数两个临时变量 a是5 b是10 ,并创建了内函数,然后把内函数的引用返回存给了demo
# 外函数结束的时候发现内部函数将会用到自己的临时变量,这两个临时变量就不会释放,会绑定给这个内部函数
demo = outer(5)
# 我们调用内部函数,看一看内部函数是不是能使用外部函数的临时变量
# demo存了外函数的返回值,也就是inner函数的引用,这里相当于执行inner函数
demo() # 15

demo2 = outer(7)
demo2()#17

24.super调用父类方法

super() 函数是用于调用父类(超类)的一个方法。
super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。

super(type[, object-or-type])
type -- 类。
object-or-type --

python3的用法:

class A:
def add(self, x):
y = x+1
print(y)
class B(A):
def add(self, x):
super().add(x)
b = B()
b.add(2) # 3

python2的用法:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

class A(object): # Python2.x 记得继承 object
def add(self, x):
y = x+1
print(y)
class B(A):
def add(self, x):
super(B, self).add(x)
b = B()
b.add(2) # 3

详细学习:​​javascript:void(0)​

25.If/else三元表达式

if X:
A = Y
else:
A =

等价于下面写法:

A = Y if X else

26.nonlocal非局部声明

非局部声明变量指代的已有标识符是最近外面函数的已声明变量,但是不包括全局变量。
这个是很重要的,因为绑定的默认行为是首先搜索本地命名空间。
nonlocal声明的变量只对局部起作用,离开封装函数,那么该变量就无效。

非局部声明不像全局声明,我们必须在封装函数前面事先声明该变量

count = 1

def a():
count = 'a函数里面'   #如果不事先声明,那么函数b中的nonlocal就会报错
def b():
nonlocal count
print(count)
count = 2
b()
print(count)

if __name__ == '__main__':
a()
print(count)

nonlocal只能在封装函数中使用,在外部函数先进行声明,在内部函数进行nonlocal声明,这样在b()函数中的count与a()中的count是同一个变量。

27.向下整除// and 精准除/

‘//’: 除法结果向下取整
‘/’: 除法结果为浮点数

28.装饰器property和setter

【Python】基础知识整理_字符串_02


​https://blog.nowcoder.net/n/c42dcd79e85b45a8a9ac7853c1115870​

29.迭代器和可迭代对象的区别

迭代器处理大容量数据

30.列表的负数索引

对Python来说,负数索引表示从右边往左数,最右边的元素的索引为-1,倒数第二个元素为-2.

list = ["a", "b", "c", "d", "e"]
print(list[-1])

31.list和tuple区别

在list集合中可以实现元素的添加、修改、插入、以及删除,由下面的例子可看出并没有要求​​list​​里的每个元素必须是相同的数据类型。

list = [1, 'abc']
print(list) # 输出[1, 'abc']

在tuple集合中,一旦元素被存储,以后就不能修改,删除了,这比list集合安全许多,所以能用tuple就用tuple。

回顾:不可变对象:数字 字符串 元组tuple ;可变对象:字典 列表list 字节数组。

32.三种括号

python语言最常见的括号有三种,分别是:小括号( )、中括号[ ]和大括号也叫做花括号{ },分别用来代表不同的python基本内置数据类型。
1、python中的小括号( ):代表tuple元组数据类型,元组是一种不可变序列。
2、python中的中括号[ ],代表list列表数据类型:
3、python大括号{ }花括号:代表dict字典数据类型,字典是由键对值组组成。冒号’:‘分开键和值,逗号’,'隔开组。用大括号创建的方法如下:

dict = {'andy': 'boy','liu': 'girl'}
print(dict['andy']) # 打印输出boy

33.少用for循环

当队不同的数据执行同样的一个或一批指令,或者说把指令应用于一个数组or向量上时,尽量使用向量化的数值计算,少用for循环。

#!/usr/bin/python
## -*- coding:uft-8 -*-
import torch as t
def for_loop_add(x, y):
result = []
# zip能打包成元组的列表
for i, j in zip(x, y):
result.append(i + j)
return t.Tensor(result)

x = t.zeros(100)
y = t.ones(100)
%timeit -n 10 for_loop_add(x, y)
%timeit -n 10 x +

查看两组程序的运行时间,显然第二组更快:

The slowest run took 9.68 times longer than the fastest. This could mean that an intermediate result is being cached.
956 µs ± 1.23 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
The slowest run took 31.72 times longer than the fastest. This could mean that an intermediate result is being cached.
12.1 µs ± 22.7 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

34.为工程生成requirements.txt

1、freeze方式:直接使用以下命令

pip freeze > requirements.txt

将当前Python环境中所有的类库包,其它包括那些你没有在当前项目中使用的类库,保存至​​requirements.txt​​​ 。至此,​​requirements.txt​​​文件会出现在相应的工程中
如果要安装​​​requirements.txt​​​中的类库内容,那么你可以执行​​pip install -r requirements.txt​​。

2、​​pipreqs​​​方式
作用:将当前项目使用的类库导出生成为 ​​​requirements.txt​​​;
使用方法:安装pipreqs: ​​​pip install pipreqs​​​ 执行:​​pipreqs ./​​ 最后在当前路径下会多出一个​​requirements.txt​​文件。

35.对字典按照value进行sorted

sorted还能对字典按照value值进行排序,这里结合了​​lambda​​​表达式,其中​​key = lambda kv:(kv[1], kv[0])​​​的意思是先按照​​kv[1]​​​对应的值进行排序(默认从小到大),然后按照​​kv[0]​​对应的值进行排序(默认从小到大)。

def dictionairy():  

# 声明字典
key_value ={}

# 初始化
key_value[2] = 56
key_value[1] = 2
key_value[5] = 12
key_value[4] = 24
key_value[6] = 18
key_value[3] = 323


print ("按值(value)排序:")
print(sorted(key_value.items(), key = lambda kv:(kv[1], kv[0])))

def main():
dictionairy()

if __name__=="__main__":
main()

结果为:

按值(value)排序:
[(1, 2), (5, 12), (6, 18), (4, 24), (2, 56), (3, 323)]

36.int(str(abs(x))[::-1])

这句可以输出 x 的无符号的字符串的反转,然后转回为​​int​​类型。

37.正则表达式

(1)​​re模块 findall()详解​​​ (2)
(3)​​​python正则表达式,菜鸟教程​

38.tuple(zip(*edge_list))

分别把源节点和目标节点分开,分为两个元组。
​​​*edge_list​​​可理解解压,这里的解压结果是​​(1, 0) (2, 0)​​。

edge_list = [(1, 0), (2, 0)]
src, dst = tuple(zip(*edge_list))

"""
src = (1, 2)
dst = (0, 0)
"""

其中​​zip​​是将对象中的元组打包成一个个元组:

>>>a = [1,2,3]
>>> b = [4,5,6]
>>> c = [4,5,6,7,8]
>>> zipped = zip(a,b) # 打包为元组的列表
[(1, 4), (2, 5), (3, 6)]

39.问:0的布尔值是什么?[]和{}的布尔值呢?

0的布尔值是false。

print(0 == False)
print([] == 0)
print([] == 1)
print({} == None)
print('=' * 20)

print({} == False)
print({} == True)
print({} == None)

结果为:

True
False
False
False
====================
False
False
False

40.单例模式

对于程序:

class A(object):
pass
a = A()

可以通过重写以下方法实现类​​A​​​的单例模式:​​__new__​​​、​​__init__​​。

41.Python内存管理机制

42.__call__方法的作用

(1)使实例对象变为可调用对象

​__call__​​​类似在类中重载​​()​​​运算符,使得类实例对象可以像调用普通函数一样,即使用​​对象名()​​:

class Pig:
# 定义__call__方法
def __call__(self,name,add):
print("调用__call__()方法",name,add)

pig = Pig()
pig("你是猪吗?","不是哦")
# 调用__call__()方法 你是猪吗? 不是哦

通过在​​Pig​​​类中实现​​__call__​​​方法,使得实例对象​​pig​​​变为可调用对象。对于可调用对象,​​名称()​​​等价于​​名称.__call__​​​。即上面的代码等价于为​​pig.__call__("你是猪吗?", "不是哦")​​。

  • python中的可调用对象:
  • 自定义函数
  • python内置函数
  • 上面的类实例对象
(2)弥补hasattr()函数短板

​hasattr(当前对象, 属性)​​函数能够判断当前对象是否包含对应的属性 or 方法,但是不能判断同名情况,是指类属性 还是 类方法。

类实例对象包含的方法,也是可调用对象(有​​__call__()​​​方法),但是类属性不是可调用对象。所以如下栗子的​​say​​​类方法是可调用对象,拥有​​__call__()​​方法。

class CLanguage:
def __init__ (self):
self.name = "language"
self.add = "english"
def say(self):
print("hello world!")
clangs = CLanguage()
if hasattr(clangs,"name"):
print(hasattr(clangs.name,"__call__"))
print("**********")
if hasattr(clangs,"say"):
print(hasattr(clangs.say,"__call__"))
(3)再来一个栗子
class Entity:
'''调用实体来改变实体的位置。'''
def __init__(self, x):
self.x = x

def __call__(self):
'''改变实体的位置'''
print('self.x:', self.x)

entity = Entity(1)
entity()

================================
output:
self.x: 1

43.生成器yield用法

一个打印斐波那契数列的栗子:

def fab(max): 
n, a, b = 0, 0, 1
while n < max:
yield b # 使用 yield
# print b
a, b = b, a + b
n = n + 1

for n in fab(5):
print (n)
  • ​yield​​​ 的作用就是把一个函数变成一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 ​​iterable​​ 对象!
  • 在 for 循环执行时,每次循环都会执行​​fab​​ 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。
  • 也可以手动调用 fab(5) 的 next() 方法(因为 fab(5) 是一个 generator 对象,该对象具有 next() 方法):
>>>f = fab(5) 
>>> f.next()
1
>>> f.next()
1
>>> f.next()
2
>>> f.next()
3
>>> f.next()
5
>>> f.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>

44.@staticmethod作用及用法

​staticmethod​​用于修饰类中的方法,使其可以在不创建类实例的情况下调用方法,这样做的好处是执行效率比较高。也可以像一般的方法一样用实例调用该方法。该方法一般被称为静态方法。静态方法不可以引用类中的属性或方法,其参数列表也不需要约定的默认参数self。

class Time():
def __init__(self,sec):
self.sec = sec
#声明一个静态方法
@staticmethod
def sec_minutes(s1,s2):
#返回两个时间差
return abs(s1-s2)

t = Time(10)
#分别使用类名调用和使用实例调用静态方法
print(Time.sec_minutes(10,5),t.sec_minutes(t.sec,5))
#结果为5 5

reference

常见面试题​​https://www.zhangjunbk.com/article/23397​​​ 静态方法​​javascript:void(0)​​ python进阶教程https://eastlakeside.gitbook.io/interpy-zh/decorators/your_first_decorator/logging
​https://www.freesion.com/article/1776337295/​python重点内容
英文python超棒教程​​https://pymotw.com/3/​​​​Python yield 使用浅析​

附:Python面试题

这是一份最常见Python面试题合集,既有基本的Python面试题,也有高阶版试题。

第一部分:Python基础

文件操作

1.有一个jsonline格式的文件fifile.txt大小约为10K, 之前处理文件的代码如下所示 。现在要处理一个大小为 10G 的文件,但是内存只有 4G,如果在只修改 get_lines 函数而其他代码保持不变的情况下,应该如何实现?需要考虑的问题都有哪些?

def get_lines():
l = []
with open(‘file.txt’,‘rb’) as f:
for eachline in f:
l.append(eachline)
return l
if name == ‘main’:
for e in get_lines():
process(e) #处理每一行数据
read、readline和readlines的区别?
模块与包

3.输入日期, 判断这一天是这一年的第几天?

4.如何打乱一个排好序的list对象alist?

数据类型

5.现有字典 d= {‘a’:24,‘g’:52,‘i’:12,‘k’:33}请按value值进行排序?

6.字典推导式

7.请反转字符串 “aStr”?

8.将字符串 “k:1 |k1:2|k2:3|k3:4”,处理成字典 {k:1,k1:2,…}

9.请按alist中元素的age由大到小排序

10.下面代码的输出结果将是什么?

11.写一个列表生成式,产生一个公差为11的等差数列

12.给定两个列表,怎么找出他们相同的元素和不同的元素?

13.请写出一段python代码实现删除list里面的重复元素?

14.给定两个list A,B ,请您找出A,B中相同与不同的元素

15.python新式类和经典类的区别?

16.python中内置的数据结构有几种?

17.python如何实现单例模式?请写出两种实现方式?

18.反转一个整数,例如-123 --> -321

19.设计实现遍历目录与子目录,抓取.pyc文件

20.一行代码实现1-100之和

21.Python-遍历列表时删除元素的正确做法

22.字符串的操作题目

23.可变类型和不可变类型

24.is和==有什么区别?

25.求出列表所有奇数并构造新列表

26.用一行python代码写出1+2+3+10248

27.Python中变量的作用域?(变量查找顺序)

28.字符串 “123” 转换成 123 ,不使用内置api,例如 int()

29.Given an array of integers

30.python代码实现删除一个list里面的重复元素

31.统计一个文本中单词频次最高的10个单词?

32.请写出一个函数满足以下条件

33.使用单一的列表生成式来产生一个新的列表

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

35.输入某年某月某日,判断这一天是这一年的第几天?

36.两个有序列表,l1,l2,对这两个列表进行合并不可使用extend

37.给定一个任意长度数组,实现一个函数

38.写一个函数找出一个整数数组中,第二大的数

39.阅读一下代码他们的输出结果是什么?

40.统计一段字符串中字符出现的次数

41.super函数的具体用法和场景

第二部分:Python高级

元类

42.Python中类方法、类实例方法、静态方法有何区别?

43.遍历一个object的所有属性,并print每一个属性名?

44.写一个类,并让它尽可能多的支持操作符?

45.介绍Cython,Pypy Cpython Numba各有什么缺点

46.请描述抽象类和接口类的区别和联系

47.Python中如何动态获取和设置对象的属性?

内存管理与垃圾回收机制

48.哪些操作会导致Python内存溢出,怎么处理?

49.关于Python内存管理,下列说法错误的是

50.Python的内存管理机制及调优手段?

51.内存泄露是什么?如何避免?

函数

52.python常见的列表推导式?

53.简述read、readline、readlines的区别?

54.什么是Hash(散列函数)?

55.python函数重载机制?

56.写一个函数找出一个整数数组中,第二大的数

57.手写一个判断时间的装饰器

58.使用Python内置的fifilter()方法来过滤?

59.编写函数的4个原则

60.函数调用参数的传递方式是值传递还是引用传递?

61.如何在function里面设置一个全局变量

62.对缺省参数的理解 ?

63.Mysql怎么限制IP访问?

64.带参数的装饰器?

65.为什么函数名字可以当做参数用?

66.Python中pass语句的作用是什么?

67.有这样一段代码,print c会输出什么,为什么?

68.交换两个变量的值?

69.map函数和reduce函数?

70.回调函数,如何通信的?

71.Python主要的内置数据类型都有哪些? print dir( ‘a ’) 的输出?

72.map(lambda x:xx,[y for y in range(3)])的输出?

73.hasattr() getattr() setattr() 函数使用详解?

74.一句话解决阶乘函数?

75.什么是lambda函数? 有什么好处?

76.递归函数停止的条件?

77.下面这段代码的输出结果将是什么?请解释。

78.什么是lambda函数?它有什么好处?写一个匿名函数求两个数的和

设计模式

79.对设计模式的理解,简述你了解的设计模式?

80.请手写一个单例

81.单例模式的应用场景有那些?

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

83.对装饰器的理解,并写出一个计时器记录方法执行性能的装饰器?

84.解释以下什么是闭包?

85.函数装饰器有什么作用?

86.生成器,迭代器的区别?

87.X是什么类型?

88.请用一行代码 实现将1-N 的整数列表以3为单位分组89.Python中yield的用法?

面向对象

90.Python中的可变对象和不可变对象?

91.Python的魔法方法

92.面向对象中怎么实现只读属性?

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

正则表达式

94.请写出一段代码用正则匹配出ip?

95.a = “abbbccc”,用正则匹配为abccc,不管有多少b,就出现一次?

96.Python字符串查找和替换?

97.用Python匹配HTML g tag的时候,<.> 和 <.*?> 有什么区别

98.正则表达式贪婪与非贪婪模式的区别?

99.写出开头匹配字母和下划线,末尾是数字的正则表达式?

100.正则表达式操作

101.请匹配出变量A 中的json字符串。

102.怎么过滤评论中的表情?

103.简述Python里面search和match的区别

104.请写出匹配ip的Python正则表达式

105.Python里match与search的区别?

系统编程

106.进程总结

107.谈谈你对多进程,多线程,以及协程的理解,项目是否用?

108.Python异常使用场景有那些?

109.多线程共同操作同一个数据互斥锁同步?

110.什么是多线程竞争?

111.请介绍一下Python的线程同步?

112.解释以下什么是锁,有哪几种锁?

113.什么是死锁?

114.多线程交互访问数据,如果访问到了就不访问了?

115.什么是线程安全,什么是互斥锁?

116.说说下面几个概念:同步,异步,阻塞,非阻塞?

117.什么是僵尸进程和孤儿进程?怎么避免僵尸进程?

118.python中进程与线程的使用场景?

119.线程是并发还是并行,进程是并发还是并行?

120.并行(parallel)和并发(concurrency)?

121.IO密集型和CPU密集型区别?

122.python asyncio的原理?

第三部分:网络编程

123.怎么实现强行关闭客户端和服务器之间的连接?

124.简述TCP和UDP的区别以及优缺点?

125.简述浏览器通过WSGI请求动态资源的过程?

126.描述用浏览器访问www.baidu.com的过程

127.Post和Get请求的区别?

128.cookie 和session 的区别?

129.列出你知道的HTTP协议的状态码,说出表示什么意思?

130.请简单说一下三次握手和四次挥手?

131.说一下什么是tcp的2MSL?

132.为什么客户端在TIME-WAIT状态必须等待2MSL的时间?

133.说说HTTP和HTTPS区别?

134.谈一下HTTP协议以及协议头部中表示数据类型的字段?

135.HTTP请求方法都有什么?136.使用Socket套接字需要传入哪些参数 ?

137.HTTP常见请求头?

138.七层模型?

139.url的形式?

第四部分:Web

Flask

140.对Flask蓝图(Blueprint)的理解?

141.Flask 和 Django 路由映射的区别?

Django

142.什么是wsgi,uwsgi,uWSGI?

143.Django、Flask、Tornado的对比?

144.CORS 和 CSRF的区别?

145.Session,Cookie,JWT的理解

146.简述Django请求生命周期

147.用的restframework完成api发送时间时区

148.nginx,tomcat,apach到底是什么?

149.请给出你熟悉关系数据库范式有哪些,有什么作用?

150.简述QQ登陆过程

151.post 和 get的区别?

152.项目中日志的作用

153.django中间件的使用?

154.谈一下你对uWSGI和nginx的理解?

155.Python中三大框架各自的应用场景?

156.Django中哪里用到了线程?哪里用到了协程?哪里用到了进程?

157.有用过Django REST framework吗?

158.对cookies与session的了解?他们能单独用吗?

爬虫

159.试列出至少三种目前流行的大型数据库

160.列举您使用过的Python网络爬虫所用到的网络数据包?

161.爬取数据后使用哪个数据库存储数据的,为什么?

162.你用过的爬虫框架或者模块有哪些?优缺点?

163.写爬虫是用多进程好?还是多线程好?

164.常见的反爬虫和应对方法?

165.解析网页的解析器使用最多的是哪几个?

166.需要登录的网页,如何解决同时限制ip,cookie,session

167.验证码的解决?

168.使用最多的数据库,对他们的理解?

169.编写过哪些爬虫中间件?

170.“极验”滑动验证码如何破解?

171.爬虫多久爬一次,爬下来的数据是怎么存储?

172.cookie过期的处理问题?

173.动态加载又对及时性要求很高怎么处理?

174.HTTPS有什么优点和缺点?

175.HTTPS是如何实现安全传输数据的?

176.TTL,MSL,RTT各是什么?

177.谈一谈你对Selenium和PhantomJS了解

178.平常怎么使用代理的 ?

179.存放在数据库(redis、mysql等)。

180.怎么监控爬虫的状态?

181.描述下scrapy框架运行的机制?

182.谈谈你对Scrapy的理解?183.怎么样让 scrapy 框架发送一个 post 请求(具体写出来)

184.怎么监控爬虫的状态 ?

185.怎么判断网站是否更新?

186.图片、视频爬取怎么绕过防盗连接

187.你爬出来的数据量大概有多大?大概多长时间爬一次?

188.用什么数据库存爬下来的数据?部署是你做的吗?怎么部署?

189.增量爬取

190.爬取下来的数据如何去重,说一下scrapy的具体的算法依据。

191.Scrapy的优缺点?

192.怎么设置爬取深度?

193.scrapy和scrapy-redis有什么区别?为什么选择redis数据库?

194.分布式爬虫主要解决什么问题?

195.什么是分布式存储?

196.你所知道的分布式爬虫方案有哪些?

197.scrapy-redis,有做过其他的分布式爬虫吗?

数据库

MySQL

198.主键 超键 候选键 外键

199.视图的作用,视图可以更改么?

200.drop,delete与truncate的区别

201.索引的工作原理及其种类

202.连接的种类

203.数据库优化的思路

204.存储过程与触发器的区别

205.悲观锁和乐观锁是什么?

206.你常用的mysql引擎有哪些?各引擎间有什么区别?

Redis

207.Redis宕机怎么解决?

208.redis和mecached的区别,以及使用场景

209.Redis集群方案该怎么做?都有哪些方案?

210.Redis回收进程是如何工作的

MongoDB

211.MongoDB中对多条记录做更新操作命令是什么?

212.MongoDB如何才会拓展到多个shard里?

测试

213.编写测试计划的目的是

214.对关键词触发模块进行测试

215.其他常用笔试题目网址汇总

216.测试人员在软件开发过程中的任务是什么

217.一条软件Bug记录都包含了哪些内容?

218.简述黑盒测试和白盒测试的优缺点

219.请列出你所知道的软件测试种类,至少5项

220.Alpha测试与Beta测试的区别是什么?

221.举例说明什么是Bug?一个bug report应包含什么关键字?

数据结构

222.数组中出现次数超过一半的数字-Python版

223.求100以内的质数

224.无重复字符的最长子串-Python实现

225.通过2个5/6升的水壶从池塘得到3升水

226.什么是MD5加密,有什么特点?227.什么是对称加密和非对称加密

228.冒泡排序的思想?

229.快速排序的思想?

230.如何判断单向链表中是否有环?

231.你知道哪些排序算法(一般是通过问题考算法)

232.斐波那契数列

233.如何翻转一个单链表?

234.青蛙跳台阶问题:一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。

235.两数之和 Two Sum

236.搜索旋转排序数组 Search in Rotated Sorted Array

237.Python实现一个Stack的数据结构

238.写一个二分查找

239.set 用 in 时间复杂度是多少,为什么?

240.列表中有n个正整数范围在[0,1000],进行排序;

241.面向对象编程中有组合和继承的方法实现新的类

大数据

242.找出1G的文件中高频词

243.一个大约有一万行的文本文件统计高频词

244.怎么在海量数据中找出重复次数最多的一个?

245.判断数据是否在大量数据中

Reference