HOME
ABOUT
ARCHIVES
Search …
2019-07-2
/
PYTHON
Python面试
Chapter1 20道
试题:NO.01
1.python下多线程的限制以及多进程中传递参数的方式?
python多线程有个全局解释器锁(global interpreter lock),这个锁的意思是任一时间只能有一个线程使用解释器,跟单cpu跑多个程序一个意思,大家都是轮着用的,这叫“并发”,不是“并行”。
多进程间共享数据,可以使用 multiprocessing.Value 和 multiprocessing.Array
试题:NO.02
2.Python是如何进行内存管理的?
Python引用了一个内存池(memory pool)机制,即Pymalloc机制(malloc:n.分配内存),用于管理对小块内存的申请和释放
内存池(memory pool)的概念:
当创建大量消耗小内存的对象时,频繁调用new/malloc会导致大量的内存碎片,致使效率降低。内存池的概念就是预先在内存中申请一定数量的,大小相等 的内存块留作备用,当有新的内存需求时,就先从内存池中分配内存给这个需求,不够了之后再申请新的内存。这样做最显著的优势就是能够减少内存碎片,提升效率。
内存池的实现方式有很多,性能和适用范围也不一样。
python中的内存管理机制——Pymalloc:
python中的内存管理机制都有两套实现,一套是针对小对象,就是大小小于256bits时,pymalloc会在内存池中申请内存空间;当大于256bits,则会直接执行new/malloc的行为来申请内存空间。 关于释放内存方面,当一个对象的引用计数变为0时,python就会调用它的析构函数。在析构时,也采用了内存池机制,从内存池来的内存会被归还到内存池中,以避免频繁地释放动作。
试题:NO.03
3.什么是lambda函数?它有什么好处?
lambda 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的函数。 lambda 函数不能包含命令,它们所包含的表达式不能超过一个。不要试图向lambda 函数中塞入太多的东西;如果你需要更复杂的东西,应该定义一个普通函数,然后想让它多长就多长。
试题:NO.04
4.如何用Python输出一个Fibonacci数列?
1
2
3
4
a,b = 0, 1
while b<100:
print (b),
a, b = b, a+b
试题:NO.05
5.介绍一下Python中webbrowser的用法?
webbrowser模块提供了一个高级接口来显示基于Web的文档,大部分情况下只需要简单的调用open()方法。
webbrowser定义了如下的异常:
exception webbrowser.Error, 当浏览器控件发生错误是会抛出这个异常
webbrowser有以下方法:
webbrowser.open(url[, new=0[, autoraise=1]])
这个方法是在默认的浏览器中显示url, 如果new = 0, 那么url会在同一个浏览器窗口下打开,如果new = 1, 会打开一个新的窗口,如果new = 2, 会打开一个新的tab, 如果autoraise = true, 窗口会自动增长。
webbrowser.open_new(url)
在默认浏览器中打开一个新的窗口来显示url, 否则,在仅有的浏览器窗口中打开url
webbrowser.open_new_tab(url)
在默认浏览器中当开一个新的tab来显示url, 否则跟open_new()一样
webbrowser.get([name]) 根据name返回一个浏览器对象,如果name为空,则返回默认的浏览器
webbrowser.register(name, construtor[, instance])
注册一个名字为name的浏览器,如果这个浏览器类型被注册就可以用get()方法来获取。
试题:NO.06
6.解释一下python的and-or语法
与C表达式 bool ? a : b类似,但是bool and a or b,当 a 为假时,不会象C表达式 bool ? a : b 一样工作
应该将 and-or 技巧封装成一个函数:
defchoose(bool, a, b):return(booland[a]or[b])[0]
因为 [a] 是一个非空列表,它永远不会为假。甚至 a 是 0 或 ‘’ 或其它假值,列表[a]为真,因为它有一个元素。
试题:NO.07
7.how do I iterate over a sequence in reverse order?
for x in reversed(sequence):
…#dosomethingwithx…
如果不是list, 最通用但是稍慢的解决方案是:
for i in range(len(sequence)-1, -1, -1):
x = sequence[i]
试题:NO.08
8.Python是如何进行类型转换的?
大牛总结的20个经典python面试题
试题:NO.09
9.Python里面如何实现tuple和list的转换?
1
2
3
4
5
l = tuple(iplist)
print(l)
t = list(l)
print(t)
试题:NO.10
10.请写出一段Python代码实现删除一个list里面的重复元素?
1
2
3
4
5
6
7
8
9
l = [1,1,2,3,4,5,4]
list(set(l))
[1,2,3,4,5]
#或者
d = {}
for x in l:
d[x] = 1
l = list(d.keys())
试题:NO.11
11.Python如何实现单例模式?其他23种设计模式python如何实现?
大牛总结的20个经典python面试题
试题:NO.12
12.Python里面如何拷贝一个对象?
标准库中的copy模块提供了两个方法来实现拷贝.一个方法是copy,它返回和参数包含内容一样的对象.
使用deepcopy方法,对象中的属性也被复制
试题:NO.13
13.如何用Python来进行查询和替换一个文本字符串?
可以使用sub()方法来进行查询和替换,sub方法的格式为:sub(replacement, string[, count=0])
replacement是被替换成的文本
string是需要被替换的文本
count是一个可选参数,指最大被替换的数量
试题:NO.14
14.Python里面search()和match()的区别?
match()函数只检测RE是不是在string的开始位置匹配,search()会扫描整个string查找匹配, 也就是说match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回none 。
试题:NO.15
15.有两个序列a,b,大小都为n, 序列元素的值任意整形数,无序?
要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。
将两序列合并为一个序列,并排序,为序列Source
拿出最大元素Big,次大的元素Small
在余下的序列S[:-2]进行平分,得到序列max,min
将Small加到max序列,将Big加大min序列,重新计算新序列和,和大的为max,小的为min。
试题:NO.16
16.python程序中文输出问题怎么解决?
在文件开头加上
大牛总结的20个经典python面试题
试题:NO.17
17.python如何捕获异常?
(1)使用try和except语句来捕获异常
大牛总结的20个经典python面试题
捕获到的IOError错误的详细原因会被放置在对象e中,然后运行该python 异常处理的except代码块捕获所有的异常
(2)用raise语句手工引发一个异常:
大牛总结的20个经典python面试题
(3)采用sys模块回溯最后的异常
大牛总结的20个经典python面试题
试题:NO.18
18.python代码得到列表list的交集与差集?
交集
大牛总结的20个经典python面试题
差集
大牛总结的20个经典python面试题
试题:NO.19
19.如何用Python来发送邮件?
可以使用smtplib标准库。
以下代码可以在支持SMTP监听器的服务器上执行。
大牛总结的20个经典python面试题
试题:NO.20
20.介绍一下except的用法和作用? Python的except用来捕获所有异常,因为Python里面的每次错误都会抛出一个异常,所以每个程序的错误都被当作一个运行时错误。
Chapter2
为了充实自己,小编决定上传自己见到的笔试题和面试题。可能要写好长时间,一时半会写不了多少,只能说遇到多少写多少吧,但是只要小编有时间,会持续上传(但是答案却不能保证,所以有看到错误的及时联系小编,以免误导其他人)。
1.单引号,双引号,三引号的区别
1
2
3
4
5
6
7
8
9
10
11
分别阐述3种引号用的场景和区别
1),单引号和双引号主要用来表示字符串
比如:
单引号:‘python’
双引号:“python”
2).三引号
三单引号:’’‘python ‘’’,也可以表示字符串一般用来输入多行文本,或者用于大段的注释
三双引号:""“python”"",一般用在类里面,用来注释类,这样省的写文档,直接用类的对象__doc__访问获得文档
区别:
若你的字符串里面本身包含单引号,必须用双引号
比如:“can’t find the log\n”
2.Python的参数传递是值传递还是引用传递
1
2
3
4
5
6
7
8
9
10
11
举例说明Python函数参数传递的几种形式,并说明函数传参是值传递还是引用传递
1).Python的参数传递有:
位置参数
默认参数,
可变参数,
关键字参数
2).函数的传值到底是值传递还是引用传递,要分情况
a.不可变参数用值传递:
像整数和字符串这样的不可变对象,是通过拷贝进行传递的,因为你无论如何都不可能在原处改变不可变对象
b.可变参数是用引用传递的
比如像列表,字典这样的对象是通过引用传递,和C语言里面的用指针传递数组很相似,可变对象能在函数内部改变.
3.什么是lambda函数?它有什么好处?
1
2
3
4
5
6
举例说明lambda的用法,并说明用lambda的优点
1).lambda的用法:
lambda是匿名函数,用法如下:lambda arg1,arg2…argN:expression using args
2).优点
lambda能和def做同样种类的工作,特别是对于那些逻辑简单的函数,直接用lambda会更简洁,
而且省去取函数名的麻烦(给函数取名是个技术活)
4.字符串格式化:%和.format的区别
1
2
字符串的format函数非常灵活,很强大,可以接受的参数不限个数,并且位置可以不按顺序,
而且有较为强大的格式限定符(比如:填充,对齐,精度等)
5.Python是如何进行内存管理的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1).对象的引用计数机制
Python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数。
引用计数增加的情况:
一个对象分配一个新名称
将其放入一个容器中(如列表、元组或字典)
引用计数减少的情况:
使用del语句对对象别名显示的销毁
引用超出作用域或被重新赋值
2).垃圾回收
当一个对象的引用计数归零时,它将被垃圾收集机制处理掉。
3).内存池机制
Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统:
Pymalloc机制:为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。
对于Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。
也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。
6.写一个函数, 输入一个字符串, 返回倒序排列的结果
输入: string_reverse(‘abcdef’), 返回: ‘fedcba’,写出你能想到的多种方法
1).利用字符串本身的翻转
1
2
def string_reverse1(text=‘abcdef’):
return text[::-1]
2).把字符串变成列表,用列表的reverse函数
img
3).新建一个列表,从后往前取
img
4).利用双向列表deque中的extendleft函数
img
5).递归
img
7.按升序合并如下两个list, 并去除重复的元素
1
2
list1 = [2, 3, 8, 4, 9, 5, 6]
list2 = [5, 6, 10, 17, 11, 2]
1).最简单的方法用set
1
2
list3=list1+list2
print sorted(list(set(list3)))
2).递归
先选一个中间数,然后一边是小的数字,一边是大的数字,然后再循环递归,排完序(是不是想起了c里面的冒泡)
img
8.以下的代码的输出将是什么? 说出你的答案并解释
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Parent(object):
x = 1
class Child1(Parent):
pass
class Child2(Parent):
pass
print Parent.x, Child1.x, Child2.x
Child1.x = 2
print Parent.x, Child1.x, Child2.x
Parent.x = 3
print Parent.x, Child1.x, Child2.x
1 1 1
1 2 1
3 2 3
解答:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
使你困惑或是惊奇的是关于最后一行的输出是 3 2 3 而不是 3 2 1。
为什么改变了 Parent.x 的值还会改变 Child2.x 的值,但是同时 Child1.x 值却没有改变?
这个答案的关键是,在 Python中,类变量在内部是作为字典处理的。
如果一个变量的名字没有在当前类的字典中发现,将搜索祖先类(比如父类)直到被引用的变量名被找到.
首先,在父类中设置 x = 1 会使得类变量 x 在引用该类和其任何子类中的值为 1。
这就是因为第一个 print 语句的输出是 1 1 1
然后,如果任何它的子类重写了该值(例如,我们执行语句 Child1.x = 2)该值仅仅在子类中被改变
。这就是为什么第二个 print 语句的输出是 1 2 1
最后,如果该值在父类中被改变(例如,我们执行语句 Parent.x = 3),这个改变会影响
到任何未重写该值的子类当中的值(在这个示例中被影响的子类是 Child2)。
这就是为什么第三个 print 输出是 3 2 3
9.下面的代码会不会报错
1
2
list = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’]
print list[10:]
不会报错,而且会输出一个 [],并且不会导致一个 IndexError
解答:
1
2
3
4
5
当试图访问一个超过列表索引值的成员将导致 IndexError(比如访问以上列表的 list[10])。
尽管如此,试图访问一个列表的以超出列表长度数作为开始索引的切片将不会导致 IndexError,
并且将仅仅返回一个空列表
一个讨厌的小问题是它会导致出现 bug ,并且这个问题是难以追踪的,
因为它在运行时不会引发错误,吐血啊~~
10.说出下面list1,list2,list3的输出值
1
2
3
4
5
6
7
8
9
10
11
12
13
def extendList(val, list=[]):
list.append(val)
return list
list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList(‘a’)
print “list1 = %s” % list1
print “list2 = %s” % list2
print “list3 = %s” % list3
list1 = [10, ‘a’]
list2 = [123]
list3 = [10, ‘a’]
许多人会错误的认为 list1 应该等于 [10] 以及 list3 应该等于 [‘a’]。认为 list 的参数会在 extendList 每次被调用的时候会被设置成它的默认值 []。
尽管如此,实际发生的事情是,新的默认列表仅仅只在函数被定义时创建一次。随后当 extendList 没有被指定的列表参数调用的时候,其使用的是同一个列表。这就是为什么当函数被定义的时候,表达式是用默认参数被计算,而不是它被调用的时候。
因此,list1 和 list3 是操作的相同的列表。而list2是操作的它创建的独立的列表(通过传递它自己的空列表作为list参数的值)
所以这一点一定要切记切记.下面我们把list置为None就可以避免一些麻烦了
img
11.写出你认为最Pythonic的代码
Pythonic编程风格是Python的一种追求的风格,精髓就是追求直观,简洁而容易读.
下面是一些比较好的例子
1).交互变量
非Pythonic
1
2
3
temp = a
a = b
b = temp
pythonic:
1
a,b=b,a
2).判断其值真假
1
2
3
name = ‘Tim’
langs = [‘AS3’, ‘Lua’, ‘C’]
info = {‘name’: ‘Tim’, ‘sex’: ‘Male’, ‘age’:23 }
非Pythonic
1
2
if name != ‘’ and len(langs) > 0 and info != {}:
print(‘All True!’)
pythonic:
1
2
if name and langs and info:
print(‘All True!’)
3).列表推导式
1
[x for x in range(1,100) if x%2==0]
4).zip创建键值对
1
2
3
keys = [‘Name’, ‘Sex’, ‘Age’]
values = [‘Jack’, ‘Male’, 23]
dict(zip(keys,values))
12.写出一段python 代码实现一个删除一个list 里面重复元素。
答案:
1
2
3
4
list_element = [‘a’,‘c,’,‘z’,‘x’,‘a’] #此列表元素有重复
delete_element = list( set(list_element)) #利用集合的唯一性删除重复元素
print(“原始列表为:”,list_element)
print(“修改后的列表为:”,delete_element)
结果:
1
2
3
4
原始列表为: [‘a’, ‘c,’, ‘z’, ‘x’, ‘a’]
修改后的列表为: [‘c,’, ‘x’, ‘z’, ‘a’]
Process finished with exit code 0
但是这样做有缺点,就是去重后,元素的排序改变了,想保持原来的排序,我们需要用下面的方法:
1
2
3
4
5
list_element = [‘a’,‘c,’,‘z’,‘x’,‘a’] #此列表元素有重复
delete_element = list( set(list_element)) #利用集合的唯一性删除重复元素
delete_element.sort(key = list_element.index) #对修改后的列表进行排序
print(“原始列表为:”,list_element)
print(“修改后的列表为:”,delete_element)
结果:
1
2
3
4
原始列表为: [‘a’, ‘c,’, ‘z’, ‘x’, ‘a’]
修改后的列表为: [‘a’, ‘c,’, ‘z’, ‘x’]
Process finished with exit code 0
13.什么是切片?
1
2
3
4
5
答案:
切片的第一个索引为起始点,第二个索引则是比我们需要的最后一个元素的索引值大1的数字。
严格的讲,list[i,j] 就是原始列表从索引i(包含)处开始,一直到索引 j 处(不包含)结束的一个切片。
注释:Python使用这种约定的原因是为了与列表索引的合法规则保持一致(从0开始,最高比例列表长度小1的数字)
14:模块是什么?
1
2
3
4
5
6
模块(module)是 Python 中非常重要的东西,你可以把它理解为 Python 的扩展工具。
换言之,Python 默认情况下提供了一些可用的东西,但是这些默认情况下提供的还远远不能满足编程实践的需要,于是就有人专门制作了另外一些工具。这些工具被称之为“模块”
任何一个 Pythoner 都可以编写模块,并且把这些模块放到网上供他人来使用。
当安装好 Python 之后,就有一些模块默认安装了,这个称之为“标准库”,“标准库”中的模块不需要安装,就可以直接使用。
如果没有纳入标准库的模块,需要安装之后才能使用。模块的安装方法,我特别推荐使用 pip 来安装。
15:dir()是什么指令?
1
dir(module)是一个非常有用的指令,可以通过它查看任何模块中所包含的工具。
16:如何把一个文件内的字符串形式通过json转化为相应的字典格式?
常见错误:
1
2
3
4
5
6
7
#account_file是文件的绝对路径
with open(account_file, “r”, encoding=“utf-8”) as f: #打开文件
file_data = json.load(account_file)
print(file_data)
这样竟然出错了!!
错误信息:AttributeError: ‘str’ object has no attribute ‘read’
改正后为:
1
2
3
4
5
#改正:
if os.path.isfile(account_file): #如果用户文件存在(即用户存在)
with open(account_file, “r”, encoding=“utf-8”) as f: #打开文件
file_data = json.load(f)
print(file_data)
17:反斜杠的困扰
1
与大多数编程语言相同,正则表达式里面使用“ \ ”作为转义字符,这就可能造成反斜杠困扰,假如你需要匹配文本中的字符’’ \ ‘’ 那么使用编程语言表示的正则表达式里面将需要4个反斜杠"\\",前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里面转义成一个反斜杠,python里的原生字符串很好的解决了这个问题,这个例子中的正则表达式可以使用 r"\ 表示。同样,匹配一个数字的"\d"可以写成r"\d.有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
仅仅需要知道及格匹配模式
1
2
3
re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
M(MULTILINE): 多行模式,改变’^‘和’$‘的行为(参见上图)
S(DOTALL): 点任意匹配模式,改变’.'的行为
18:python中 if name == ‘main‘: 的作用是什么呢
这段代码的功能理解如下:
一个python的文件有两种使用方法:
1
2
作用一:直接作为脚本执行
作用二:import 到其他的python脚本中被调用执行
简而言之:name就是当前模块名,当模块被直接运行时候模块名称为main。当模块被直接运行的时候,代码被运行,当模块被导入的时候,代码不被运行。
详细解释:
模块是对象,并且所有的模块都有一个内置属性name。一个模块的name的值取决于我们如何应用模块,如果import 一个模块,那么模块name的值通常是模块文件名,不带路径或者文件扩展名,但是我们也可以像一个标准的程序直接运行模块,在这种情况下,name的值将是一个特别缺省”main“
首先,可以让大家看一下在cmd中运行.py文件则name的值为“main”
1
2
3
4
Python 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32
Type “help”, “copyright”, “credits” or “license” for more information.
name
‘main’
而在import 一个.py文件后,name的值就不是’main‘了;
从而用if name == ‘main‘来判断是否是在直接运行该.py文件
运行原理
每个python模块(python文件)都包含内置的变量name,当运行模块被执行的时候,name等于文件名(包含了后缀.py)。如果import到其他模块中,则name等于模块名称(不包含后缀.py)。而“main”等于当前执行文件的名称(包含了后缀.py)。所以当模块被直接执行时,name == ‘main‘结果为真;而当模块被import到其他模块中时,name == ‘main‘结果为假,就是不调用对应的方法。
19:深浅copy
具体内容见博客:http://www.cnblogs.com/wj-1314/p/7436299.html
20:递归函数
(假设面试官让你把number =[2, -5, 9, -7, 2, 5, 4, -1, 0, -3, 8]中的正数的平均值求出来,你怎么算**)
首先循环列表中的值,累计次数,并对大于0的数进行累加,最后求取平均值。
这就是命令式编程——你要做什么事情,你得把达到目的的步骤详细的描述出来,然后交给机器去运行。
这也正是命令式编程的理论模型——图灵机的特点。一条写满数据的纸带,一条根据纸带内容运动的机器,机器每动一步都需要纸带上写着如何达到。
还有一种方法:
1
2
3
4
5
6
7
8
9
10
number =[2, -5, 9, -7, 2, 5, 4, -1, 0, -3, 8]
positive = filter(lambda x: x>0, number)
average = reduce(lambda x,y: x+y, positive)/len(positive)
print average
#输出===
5
这段代码最终达到的目的同样是求取正数平均值,但是它得到结果的方式和 之前有着本质的差别:通过描述一个列表->正数平均值 的映射,而不是描述“从列表得到正数平均值应该怎样做”来达到目的。
Chapter3 110道
1、一行代码实现1–100之和
利用sum()函数求和
img
2、如何在一个函数内部修改全局变量
利用global 修改全局变量
img
3、列出5个python标准库
os:提供了不少与操作系统相关联的函数
sys: 通常用于命令行参数
re: 正则匹配
math: 数学运算
datetime:处理日期时间
4、字典如何删除键和合并两个字典
del和update方法
img
5、谈下python的GIL
GIL 是python的全局解释器锁,同一进程中假如有多个线程运行,一个线程在运行python程序的时候会霸占python解释器(加了一把锁即GIL),使该进程内的其他线程无法运行,等该线程运行完后其他线程才能运行。如果线程运行过程中遇到耗时操作,则解释器锁解开,使其他线程运行。所以在多线程中,线程的运行仍是有先后顺序的,并不是同时进行。
多进程中因为每个进程都能被系统分配资源,相当于每个进程有了一个python解释器,所以多进程可以实现多个进程的同时运行,缺点是进程系统资源开销大
6、python实现列表去重的方法
先通过集合去重,在转列表
img
7、fun(args,**kwargs)中的args,**kwargs什么意思?
img
img
8、python2和python3的range(100)的区别
python2返回列表,python3返回迭代器,节约内存
9、一句话解释什么样的语言能够用装饰器?
函数可以作为参数传递的语言,可以使用装饰器
10、python内建数据类型有哪些
整型–int
布尔型–bool
字符串–str
列表–list
元组–tuple
字典–dict
11、简述面向对象中new和init区别
init是初始化方法,创建对象后,就立刻被默认调用了,可接收参数,如图
img
1、new至少要有一个参数cls,代表当前类,此参数在实例化时由Python解释器自动识别
2、new必须要有返回值,返回实例化出来的实例,这点在自己实现new时要特别注意,可以return父类(通过super(当前类名, cls))new出来的实例,或者直接是object的new出来的实例
3、init有一个参数self,就是这个new返回的实例,init在new的基础上可以完成一些其它初始化的动作,init不需要返回值
4、如果new创建的是当前类的实例,会自动调用init函数,通过return语句里面调用的new函数的第一个参数是cls来保证是当前类实例,如果是其他类的类名,;那么实际创建返回的就是其他类的实例,其实就不会调用当前类的init函数,也不会调用其他类的init函数。
img
12、简述with方法打开处理文件帮我我们做了什么?
img
打开文件在进行读写的时候可能会出现一些异常状况,如果按照常规的f.open
写法,我们需要try,except,finally,做异常判断,并且文件最终不管遇到什么情况,都要执行finally f.close()关闭文件,with方法帮我们实现了finally中f.close
(当然还有其他自定义功能,有兴趣可以研究with方法源码)
13、列表[1,2,3,4,5],请使用map()函数输出[1,4,9,16,25],并使用列表推导式提取出大于10的数,最终输出[16,25]
map()函数第一个参数是fun,第二个参数是一般是list,第三个参数可以写list,也可以不写,根据需求
img
14、python中生成随机整数、随机小数、0–1之间小数方法
随机整数:random.randint(a,b),生成区间内的整数
随机小数:习惯用numpy库,利用np.random.randn(5)生成5个随机小数
0-1随机小数:random.random(),括号中不传参
img
15、避免转义给字符串加哪个字母表示原始字符串?
r , 表示需要原始字符串,不转义特殊字符
img
18、数据表student有id,name,score,city字段,其中name中的名字可有重复,需要消除重复行,请写sql语句
select distinct name from student
19、10个Linux常用命令
ls pwd cd touch rm mkdir tree cp mv cat more grep echo
20、python2和python3区别?列举5个
1、Python3 使用 print 必须要以小括号包裹打印内容,比如 print(‘hi’)
Python2 既可以使用带小括号的方式,也可以使用一个空格来分隔打印内容,比如 print ‘hi’
2、python2 range(1,10)返回列表,python3中返回迭代器,节约内存
3、python2中使用ascii编码,python中使用utf-8编码
4、python2中unicode表示字符串序列,str表示字节序列
python3中str表示字符串序列,byte表示字节序列
5、python2中为正常显示中文,引入coding声明,python3中不需要
6、python2中是raw_input()函数,python3中是input()函数
21、列出python中可变数据类型和不可变数据类型,并简述原理
不可变数据类型:数值型、字符串型string和元组tuple
不允许变量的值发生变化,如果改变了变量的值,相当于是新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象(一个地址),如下图用id()方法可以打印对象的id
img
可变数据类型:列表list和字典dict;
允许变量的值发生变化,即如果对变量进行append、+=等这种操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化,不过对于相同的值的不同对象,在内存中则会存在不同的对象,即每个对象都有自己的地址,相当于内存中对于同值的对象保存了多份,这里不存在引用计数,是实实在在的对象。
img
img
img
img
img
32、用python删除文件和用linux命令删除文件方法
python:os.remove(文件名)
linux: rm 文件名
img
37、正则表达式匹配中,(.)和(.?)匹配区别?
(.*)是贪婪匹配,会把满足正则的尽可能多的往后匹配
(.*?)是非贪婪匹配,会把满足正则的尽可能少匹配
img
38、简述Django的orm
ORM,全拼Object-Relation Mapping,意为对象-关系映射
实现了数据模型与数据库的解耦,通过简单的配置就可以轻松更换数据库,而不需要修改代码只需要面向对象编程,orm操作本质上会根据对接的数据库引擎,翻译成对应的sql语句,所有使用Django开发的项目无需关心程序底层使用的是MySQL、Oracle、sqlite….,如果数据库迁移,只需要更换Django的数据库引擎即可
img
还有更骚的方法,将列表转成numpy矩阵,通过numpy的flatten()方法,代码永远是只有更骚,没有最骚imgimgimg
img
img
43、举例说明zip()函数用法
zip()函数在运算时,会以一个或多个序列(可迭代对象)做为参数,返回一个元组的列表。同时将这些序列中并排的元素配对。
zip()参数可以接受任何类型的序列,同时也可以有两个以上的参数;当传入参数的长度不同时,zip能自动以最短序列长度为准进行截取,获得元组。
img
45、写5条常用sql语句
show databases;
show tables;
desc 表名;
select * from 表名;
delete from 表名 where id=5;
update students set gender=0,hometown=”北京” where id=5
46、a=”hello”和b=”你好”编码成bytes类型
img
48、提高python运行效率的方法
1、使用生成器,因为可以节约大量内存
2、循环代码优化,避免过多重复代码的执行
3、核心模块用Cython PyPy等,提高效率
4、多进程、多线程、协程
5、多个if elif条件判断,可以把最有可能先发生的条件放到前面写,这样可以减少程序判断的次数,提高效率
49、简述mysql和redis区别
redis: 内存型非关系数据库,数据保存在内存中,速度快
mysql:关系型数据库,数据保存在磁盘中,检索的话,会有一定的Io操作,访问速度相对慢
50、遇到bug如何处理
1、细节上的错误,通过print()打印,能执行到print()说明一般上面的代码没有问题,分段检测程序是否有问题,如果是js的话可以alert或console.log
2、如果涉及一些第三方框架,会去查官方文档或者一些技术博客。
3、对于bug的管理与归类总结,一般测试将测试出的bug用teambin等bug管理工具进行记录,然后我们会一条一条进行修改,修改的过程也是理解业务逻辑和提高自己编程逻辑缜密性的方法,我也都会收藏做一些笔记记录。
4、导包问题、城市定位多音字造成的显示错误问题
51、正则匹配,匹配日期2018-03-20
url=’https://sycm.taobao.com/bda/tradinganaly/overview/get_summary.json?dateRange=2018-03-20|2018-03-20&dateType=recent1&device=1&token=ff25b109b&_=1521595613462’
仍有同学问正则,其实匹配并不难,提取一段特征语句,用(.*?)匹配即可
img
53、写一个单列模式
因为创建对象时new方法执行,并且必须return 返回实例化出来的对象所cls.__instance是否存在,不存在的话就创建对象,存在的话就返回该对象,来保证只有一个实例对象存在(单列),打印ID,值一样,说明对象同一个
img
55、求三个方法打印结果
fn(“one”,1)直接将键值对传给字典;
fn(“two”,2)因为字典在内存中是可变数据类型,所以指向同一个地址,传了新的额参数后,会相当于给字典增加键值对
fn(“three”,3,{})因为传了一个新字典,所以不再是原先默认参数的字典
img
56、列出常见的状态码和意义
200 OK
请求正常处理完毕
204 No Content
请求成功处理,没有实体的主体返回
206 Partial Content
GET范围请求已成功处理
301 Moved Permanently
永久重定向,资源已永久分配新URI
302 Found
临时重定向,资源已临时分配新URI
303 See Other
临时重定向,期望使用GET定向获取
304 Not Modified
发送的附带条件请求未满足
307 Temporary Redirect
临时重定向,POST不会变成GET
400 Bad Request
请求报文语法错误或参数错误
401 Unauthorized
需要通过HTTP认证,或认证失败
403 Forbidden
请求资源被拒绝
404 Not Found
无法找到请求资源(服务器无理由拒绝)
500 Internal Server Error
服务器故障或Web应用故障
503 Service Unavailable
服务器超负载或停机维护
57、分别从前端、后端、数据库阐述web项目的性能优化
该题目网上有很多方法,我不想截图网上的长串文字,看的头疼,按我自己的理解说几点
前端优化:
1、减少http请求、例如制作精灵图
2、html和CSS放在页面上部,javascript放在页面下面,因为js加载比HTML和Css加载慢,所以要优先加载html和css,以防页面显示不全,性能差,也影响用户体验差
后端优化:
1、缓存存储读写次数高,变化少的数据,比如网站首页的信息、商品的信息等。应用程序读取数据时,一般是先从缓存中读取,如果读取不到或数据已失效,再访问磁盘数据库,并将数据再次写入缓存。
2、异步方式,如果有耗时操作,可以采用异步,比如celery
3、代码优化,避免循环和判断次数太多,如果多个if else判断,优先判断最有可能先发生的情况
数据库优化:
1、如有条件,数据可以存放于redis,读取速度快
2、建立索引、外键等
58、使用pop和del删除字典中的”name”字段,dic={“name”:”zs”,”age”:18}
img
59、列出常见MYSQL数据存储引擎
InnoDB:支持事务处理,支持外键,支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库,也可以选择InnoDB,因为支持事务的提交(commit)和回滚(rollback)。
MyISAM:插入数据快,空间和内存使用比较低。如果表主要是用于插入新记录和读出记录,那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比 较低,也可以使用。
MEMORY:所有的数据都在内存中,数据的处理速度快,但是安全性不高。如果需要很快的读写速度,对数据的安全性要求较低,可以选择MEMOEY。它对表的大小有要求,不能建立太大的表。所以,这类数据库只使用在相对较小的数据库表。
img
61、简述同源策略
同源策略需要同时满足以下三点要求:
1)协议相同
2)域名相同
3)端口相同
http:www.test.com与https:www.test.com 不同源——协议不同
http:www.test.com与http:www.admin.com 不同源——域名不同
http:www.test.com与http:www.test.com:8081 不同源——端口不同
只要不满足其中任意一个要求,就不符合同源策略,就会出现“跨域”
62、简述cookie和session的区别
1,session 在服务器端,cookie 在客户端(浏览器)
2、session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效,存储Session时,键与Cookie中的sessionid相同,值是开发人员设置的键值对信息,进行了base64编码,过期时间由开发人员设置
3、cookie安全性比session差
63、简述多线程、多进程
进程:
1、操作系统进行资源分配和调度的基本单位,多个进程之间相互独立
2、稳定性好,如果一个进程崩溃,不影响其他进程,但是进程消耗资源大,开启的进程数量有限制
线程:
1、CPU进行资源分配和调度的基本单位,线程是进程的一部分,是比进程更小的能独立运行的基本单位,一个进程下的多个线程可以共享该进程的所有资源
2、如果IO操作密集,则可以多线程运行效率高,缺点是如果一个线程崩溃,都会造成进程的崩溃
应用:
IO密集的用多线程,在用户输入,sleep 时候,可以切换到其他线程执行,减少等待的时间
CPU密集的用多进程,因为假如IO操作少,用多线程的话,因为线程共享一个全局解释器锁,当前运行的线程会霸占GIL,其他线程没有GIL,就不能充分利用多核CPU的优势
64、简述any()和all()方法
any():只要迭代器中有一个元素为真就为真
all():迭代器中所有的判断项返回都是真,结果才为真
python中什么元素为假?
答案:(0,空字符串,空列表、空字典、空元组、None, False)
img
测试all()和any()方法
img
65、IOError、AttributeError、ImportError、IndentationError、IndexError、KeyError、SyntaxError、NameError分别代表什么异常
IOError:输入输出异常
AttributeError:试图访问一个对象没有的属性
ImportError:无法引入模块或包,基本是路径问题
IndentationError:语法错误,代码没有正确的对齐
IndexError:下标索引超出序列边界
KeyError:试图访问你字典里不存在的键
SyntaxError:Python代码逻辑语法出错,不能执行
NameError:使用一个还未赋予对象的变量
66、python中copy和deepcopy区别
1、复制不可变数据类型,不管copy还是deepcopy,都是同一个地址当浅复制的值是不可变对象(数值,字符串,元组)时和=“赋值”的情况一样,对象的id值与浅复制原来的值相同。
img
2、复制的值是可变对象(列表和字典)
浅拷贝copy有两种情况:
第一种情况:复制的 对象中无 复杂 子对象,原来值的改变并不会影响浅复制的值,同时浅复制的值改变也并不会影响原来的值。原来值的id值与浅复制原来的值不同。
第二种情况:复制的对象中有 复杂 子对象 (例如列表中的一个子元素是一个列表), 改变原来的值 中的复杂子对象的值 ,会影响浅复制的值。
深拷贝deepcopy:完全复制独立,包括内层列表和字典
img
67、列出几种魔法方法并简要介绍用途
init:对象初始化方法
new:创建对象时候执行的方法,单列模式会用到
str:当使用print输出对象的时候,只要自己定义了str(self)方法,那么就会打印从在这个方法中return的数据
del:删除对象执行的方法
68、C:\Users\ry-wu.junya\Desktop>python 1.py 22 33命令行启动程序并传参,print(sys.argv)会输出什么数据?
文件名和参数构成的列表
img
img
img
img
img
img
img
85、python字典和json字符串相互转化方法
json.dumps()字典转json字符串,json.loads()json转字典
img
86、MyISAM 与 InnoDB 区别:
1、InnoDB 支持事务,MyISAM 不支持,这一点是非常之重要。事务是一种高
级的处理方式,如在一些列增删改中只要哪个出错还可以回滚还原,而 MyISAM
就不可以了;
2、MyISAM 适合查询以及插入为主的应用,InnoDB 适合频繁修改以及涉及到
安全性较高的应用;
3、InnoDB 支持外键,MyISAM 不支持;
4、对于自增长的字段,InnoDB 中必须包含只有该字段的索引,但是在 MyISAM
表中可以和其他字段一起建立联合索引;
5、清空整个表时,InnoDB 是一行一行的删除,效率非常慢。MyISAM 则会重
建表;
87、统计字符串中某字符出现次数
img
img
91、简述python引用计数机制
python垃圾回收主要以引用计数为主,标记-清除和分代清除为辅的机制,其中标记-清除和分代回收主要是为了处理循环引用的难题。
引用计数算法
当有1个变量保存了对象的引用时,此对象的引用计数就会加1
当使用del删除变量指向的对象时,如果对象的引用计数不为1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除
img
92、int(“1.4”),int(1.4)输出结果?
int(“1.4”)报错,int(1.4)输出1
93、列举3条以上PEP8编码规范
1、顶级定义之间空两行,比如函数或者类定义。
2、方法定义、类定义与第一个方法之间,都应该空一行
3、三引号进行注释
4、使用Pycharm、Eclipse一般使用4个空格来缩进代码
94、正则表达式匹配第一个URL
img
96、简述乐观锁和悲观锁
悲观锁, 就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
乐观锁,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制,乐观锁适用于多读的应用类型,这样可以提高吞吐量
97、r、r+、rb、rb+文件打开模式区别
模式较多,比较下背背记记即可
img
98、Linux命令重定向 > 和 >>
Linux 允许将命令执行结果 重定向到一个 文件
将本应显示在终端上的内容 输出/追加 到指定文件中
表示输出,会覆盖文件原有的内容
表示追加,会将内容追加到已有文件的末尾
用法示例:
1
将 echo 输出的信息保存到 1.txt 里echo Hello Python > 1.txt将 tree 输出的信息追加到 1.txt 文件的末尾tree >> 1.txt
99、正则表达式匹配出
www.itcast.cn
前面的<>和后面的<>是对应的,可以用此方法
img
101、求两个列表的交集、差集、并集
img
104、常见的网络传输协议
UDP、TCP、FTP、HTTP、SMTP等等
105、单引号、双引号、三引号用法
1、单引号和双引号没有什么区别,不过单引号不用按shift,打字稍微快一点。表示字符串的时候,单引号里面可以用双引号,而不用转义字符,反之亦然。
1
2
3
4
'She said:“Yes.” 'or
"She said: ‘Yes.’ "
2、但是如果直接用单引号扩住单引号,则需要转义,像这样:
’ She said:‘Yes.’ ’
3、三引号可以直接书写多行,通常用于大段,大篇幅的字符串
1
“”"
hello
world
1
“”"
106、python垃圾回收机制
python垃圾回收主要以引用计数为主,标记-清除和分代清除为辅的机制,其中标记-清除和分代回收主要是为了处理循环引用的难题。
引用计数算法
当有1个变量保存了对象的引用时,此对象的引用计数就会加1
当使用del删除变量指向的对象时,如果对象的引用计数不为1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除
img
107、HTTP请求中get和post区别
1、GET请求是通过URL直接请求数据,数据信息可以在URL中直接看到,比如浏览器访问;而POST请求是放在请求头中的,我们是无法直接看到的;
2、GET提交有数据大小的限制,一般是不超过1024个字节,而这种说法也不完全准确,HTTP协议并没有设定URL字节长度的上限,而是浏览器做了些处理,所以长度依据浏览器的不同有所不同;POST请求在HTTP协议中也没有做说明,一般来说是没有设置限制的,但是实际上浏览器也有默认值。总体来说,少量的数据使用GET,大量的数据使用POST。
3、GET请求因为数据参数是暴露在URL中的,所以安全性比较低,比如密码是不能暴露的,就不能使用GET请求;POST请求中,请求参数信息是放在请求头的,所以安全性较高,可以使用。在实际中,涉及到登录操作的时候,尽量使用HTTPS请求,安全性更好。
108、python中读取Excel文件的方法
img
109、简述多线程、多进程
进程:
1、操作系统进行资源分配和调度的基本单位,多个进程之间相互独立
2、稳定性好,如果一个进程崩溃,不影响其他进程,但是进程消耗资源大,开启的进程数量有限制
线程:
1、CPU进行资源分配和调度的基本单位,线程是进程的一部分,是比进程更小的能独立运行的基本单位,一个进程下的多个线程可以共享该进程的所有资源
2、如果IO操作密集,则可以多线程运行效率高,缺点是如果一个线程崩溃,都会造成进程的崩溃
应用:
IO密集的用多线程,在用户输入,sleep 时候,可以切换到其他线程执行,减少等待的时间
CPU密集的用多进程,因为假如IO操作少,用多线程的话,因为线程共享一个全局解释器锁,当前运行的线程会霸占GIL,其他线程没有GIL,就不能充分利用多核CPU的优势
110、python正则中search和match
img
Chapter4 Python比较全面的概述
1 Python的函数参数传递
看两个例子:
1
2
a = 1def fun(a): a = 2fun(a)print a # 1
a = []def fun(a): a.append(1)fun(a)print a # [1]
所有的变量都可以理解是内存中一个对象的“引用”,或者,也可以看似c中void*的感觉。
这里记住的是类型是属于对象的,而不是变量。而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象。(这就是这个问题的重点)
当一个引用传递给函数的时候,函数自动复制一份引用,这个函数里的引用和外边的引用没有半毛关系了.所以第一个例子里函数把引用指向了一个不可变对象,当函数返回的时候,外面的引用没半毛感觉.而第二个例子就不一样了,函数内的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改.
如果还不明白的话,这里有更好的解释: http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference
2 Python中的元类(metaclass)
这个非常的不常用,但是像ORM这种复杂的结构还是会需要的,详情请看:《两句话掌握Python最难知识点——元类》
3 @staticmethod和@classmethod
Python其实有3个方法,即静态方法(staticmethod),类方法(classmethod)和实例方法,如下:
1
def foo(x): print “executing foo(%s)”%(x)class A(object): def foo(self,x): print “executing foo(%s,%s)”%(self,x) @classmethod def class_foo(cls,x): print “executing class_foo(%s,%s)”%(cls,x) @staticmethod def static_foo(x): print “executing static_foo(%s)”%xa=A()
这里先理解下函数参数里面的self和cls.这个self和cls是对类或者实例的绑定,对于一般的函数来说我们可以这么调用foo(x),这个函数就是最常用的,它的工作跟任何东西(类,实例)无关.对于实例方法,我们知道在类里每次定义方法的时候都需要绑定这个实例,就是foo(self, x),为什么要这么做呢?因为实例方法的调用离不开实例,我们需要把实例自己传给函数,调用的时候是这样的a.foo(x)(其实是foo(a, x)).类方法一样,只不过它传递的是类而不是实例,A.class_foo(x).注意这里的self和cls可以替换别的参数,但是python的约定是这俩,还是不要改的好.
对于静态方法其实和普通的方法一样,不需要对谁进行绑定,唯一的区别是调用的时候需要使用a.static_foo(x)或者A.static_foo(x)来调用.
4 类变量和实例变量
1
class Person: name="aaa"p1=Person()p2=Person()p1.name="bbb"print p1.name # bbbprint p2.name # aaaprint Person.name # aaa
类变量就是供类使用的变量,实例变量就是供实例使用的.
这里p1.name=”bbb”是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,p1.name一开始是指向的类变量name=”aaa”,但是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量,self.name不再引用Person的类变量name了.
可以看看下面的例子:
1
class Person: name=[]p1=Person()p2=Person()p1.name.append(1)print p1.name # [1]print p2.name # [1]print Person.name # [1]
5 Python自省
这个也是python彪悍的特性.
自省就是面向对象的语言所写的程序在运行时,所能知道对象的类型.简单一句就是运行时能够获得对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().
2017年最全面的Python语言特性详解
想要系统学习python和免费学习资料的 可以加裙 474534951
6 字典推导式
可能你见过列表推导时,却没有见过字典推导式,在2.7中才加入的:
1
d = {key: value for (key, value) in iterable}
7 Python中单下划线和双下划线
1
class MyClass():… def init(self):… self.__superprivate = “Hello”… self._semiprivate = “, world!”…>>> mc = MyClass()>>> print mc.__superprivateTraceback (most recent call last): File “”, line 1, in AttributeError: myClass instance has no attribute ‘__superprivate’>>> print mc._semiprivate, world!>>> print mc.dict{’_MyClass__superprivate’: ‘Hello’, ‘_semiprivate’: ‘, world!’}
foo:一种约定,Python内部的名字,用来区别其他用户自定义的命名,以防冲突.
_foo:一种约定,用来指定变量私有.程序员用来指定私有变量的一种方式.
foo:这个有真正的意义:解析器用_classnamefoo来代替这个名字,以区别和其他类相同的命名.
8 字符串格式化:%和.format
.format在许多方面看起来更便利.对于%最烦人的是它无法同时传递一个变量和元组.你可能会想下面的代码不会有什么问题:
1
“hi there %s” % name
但是,如果name恰好是(1,2,3),它将会抛出一个TypeError异常.为了保证它总是正确的,你必须这样做:
1
“hi there %s” % (name,) # 提供一个单元素的数组而不是一个参数
但是有点丑…format就没有这些问题.你给的第二个问题也是这样,.format好看多了.
你为什么不用它?
不知道它(在读这个之前)
为了和Python2.5兼容(譬如logging库建议使用%(issue #4))
9 迭代器和生成器
这个是stackoverflow里python排名第一的问题,值得一看: http://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python
10 args and *kwargs
用args和*kwargs只是为了方便并没有强制使用它们.
当你不确定你的函数里将要传递多少参数时你可以用*args.例如,它可以传递任意数量的参数:
1
def print_everything(*args): for count, thing in enumerate(args):… print ‘{0}. {1}’.format(count, thing)…>>> print_everything(‘apple’, ‘banana’, ‘cabbage’)0. apple1. banana2. cabbage
相似的,**kwargs允许你使用没有事先定义的参数名:
1
def table_things(**kwargs):… for name, value in kwargs.items():… print ‘{0} = {1}’.format(name, value)…>>> table_things(apple = ‘fruit’, cabbage = ‘vegetable’)cabbage = vegetableapple = fruit
你也可以混着用.命名参数首先获得参数值然后所有的其他参数都传递给args和*kwargs.命名参数在列表的最前端.例如:
1
def table_things(titlestring, kwargs)
args和kwargs可以同时在函数的定义中,但是args必须在**kwargs前面.
当调用函数时你也可以用和*语法.例如:
1
def print_three_things(a, b, c):… print ‘a = {0}, b = {1}, c = {2}’.format(a,b,c)…>>> mylist = [‘aardvark’, ‘baboon’, ‘cat’]>>> print_three_things(mylist)a = aardvark, b = baboon, c = cat
就像你看到的一样,它可以传递列表(或者元组)的每一项并把它们解包.注意必须与它们在函数里的参数相吻合.当然,你也可以在函数定义或者函数调用时用.
11 面向切面编程AOP和装饰器
这个AOP一听起来有点懵,同学面阿里的时候就被问懵了…
装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
这个问题比较大,推荐: http://stackoverflow.com/questions/739654/how-can-i-make-a-chain-of-function-decorators-in-python
2017年最全面的Python语言特性详解
想要系统学习python和免费学习资料的 可以加裙 474534951
12 鸭子类型
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。
比如在python中,有很多file-like的东西,比如StringIO,GzipFile,socket。它们有很多相同的方法,我们把它们当作文件使用。
又比如list.extend()方法中,我们并不关心它的参数是不是list,只要它是可迭代的,所以它的参数可以是list/tuple/dict/字符串/生成器等.
鸭子类型在动态语言中经常使用,非常灵活,使得python不想java那样专门去弄一大堆的设计模式。
13 Python中重载
函数重载主要是为了解决两个问题。
可变参数类型。
可变参数个数。
另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应当使用重载,而应当使用一个名字不同的函数。
好吧,那么对于情况 1 ,函数功能相同,但是参数类型不同,python 如何处理?答案是根本不需要处理,因为 python 可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在 python 中很可能是相同的代码,没有必要做成两个不同函数。
那么对于情况 2 ,函数功能相同,但参数个数不同,python 如何处理?大家知道,答案就是缺省参数。对那些缺少的参数设定为缺省参数即可解决问题。因为你假设函数功能相同,那么那些缺少的参数终归是需要用的。
好了,鉴于情况 1 跟 情况 2 都有了解决方案,python 自然就不需要函数重载了。
14 新式类和旧式类
这个面试官问了,我说了老半天,不知道他问的真正意图是什么.
新式类很早在2.2就出现了,所以旧式类完全是兼容的问题,Python3里的类全部都是新式类.这里有一个MRO问题可以了解下(新式类是广度优先,旧式类是深度优先),
15 new和init的区别
这个new确实很少见到,先做了解吧.
new是一个静态方法,而init是一个实例方法.
new方法会返回一个创建的实例,而init什么都不返回.
只有在new返回一个cls的实例时后面的init才能被调用.
当创建一个新实例时调用new,初始化一个实例时用init.
ps: metaclass是创建类时起作用.所以我们可以分别使用metaclass,new和init来分别在类创建,实例创建和实例初始化的时候做一些小手脚.
16 单例模式
这个绝对常考啊.绝对要记住1~2个方法,当时面试官是让手写的.
1 使用new方法
1
class Singleton(object): def new(cls, *args, **kw): if not hasattr(cls, ‘_instance’): orig = super(Singleton, cls) cls._instance = orig.new(cls, *args, **kw) return cls._instanceclass MyClass(Singleton): a = 1
2 共享属性
创建实例时把所有实例的dict指向同一个字典,这样它们具有相同的属性和方法.
1
class Borg(object): _state = {} def new(cls, *args, **kw): ob = super(Borg, cls).new(cls, *args, **kw) ob.dict = cls._state return obclass MyClass2(Borg): a = 1
3 装饰器版本
1
def singleton(cls, *args, **kw): instances = {} def getinstance(): if cls not in instances: instances[cls] = cls(*args, **kw) return instances[cls] return getinstance@singletonclass MyClass: …
4 import方法
作为python的模块是天然的单例模式
1
17 Python中的作用域
Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。
当 Python 遇到一个变量的话他会按照这样的顺序进行搜索:
本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)
2017年最全面的Python语言特性详解
18 GIL线程全局锁
线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.
解决办法就是多进程和下面的协程(协程也只是单CPU,但是能减小切换代价提升性能).
19 协程
知乎被问到了,呵呵哒,跪了
简单点说协程是进程和线程的升级版,进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间,而协程就是用户自己控制切换的时机,不再需要陷入系统的内核态.
Python里最常见的yield就是协程的思想!可以查看第九个问题.
20 闭包
闭包(closure)是函数式编程的重要的语法结构。闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。
当一个内嵌函数引用其外部作作用域的变量,我们就会得到一个闭包. 总结一下,创建一个闭包必须满足以下几点:
必须有一个内嵌函数
内嵌函数必须引用外部函数中的变量
外部函数的返回值必须是内嵌函数
感觉闭包还是有难度的,几句话是说不明白的,还是查查相关资料.
重点是函数运行后并不会被撤销,就像16题的instance字典一样,当函数运行完后,instance并不被销毁,而是继续留在内存空间里.这个功能类似类里的类变量,只不过迁移到了函数上.
闭包就像个空心球一样,你知道外面和里面,但你不知道中间是什么样.
21 lambda函数
其实就是一个匿名函数,为什么叫lambda?因为和后面的函数式编程有关.
22 Python函数式编程
这个需要适当的了解一下吧,毕竟函数式编程在Python中也做了引用.
python中函数式编程支持:
filter 函数的功能相当于过滤器。调用一个布尔函数bool_func来迭代遍历每个seq中的元素;返回一个使bool_seq返回值为true的元素的序列。
1
a = [1,2,3,4,5,6,7]>>>b = filter(lambda x: x > 5, a)>>>print b>>>[6,7]
map函数是对一个序列的每个项依次执行函数,下面是对一个序列每个项都乘以2:
1
a = map(lambda x:x*2,[1,2,3])>>> list(a)[2, 4, 6]
reduce函数是对一个序列的每个项迭代调用函数,下面是求3的阶乘:
1
reduce(lambda x,y:x*y,range(1,4))6
24 Python垃圾回收机制
Python GC主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率。
1 引用计数
PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少.引用计数为0时,该对象生命就结束了。
优点:
简单
实时性
缺点:
维护引用计数消耗资源
循环引用
2 标记-清除机制
基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。
3 分代技术
分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。
Python默认定义了三代对象集合,索引数越大,对象存活时间越长。
举例:
当某些内存块M经过了3次垃圾收集的清洗之后还存活时,我们就将内存块M划到一个集合A中去,而新分配的内存都划分到集合B中去。当垃圾收集开始工作时,大多数情况都只对集合B进行垃圾回收,而对集合A进行垃圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。在这个过程中,集合B中的某些内存块由于存活时间长而会被转移到集合A中,当然,集合A中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟。
25 Python的List
26 Python的is
is是对比地址,==是对比值
27 read,readline和readlines
read 读取整个文件
readline 读取下一行,使用生成器方法
readlines 读取整个文件到一个迭代器以供我们遍历
28 Python2和3的区别
推荐:《Python 2.7.x 和 3.x 版本的重要区别》
Chapter Me Python知识技巧
1.直接复制、深拷贝和浅拷贝
直接赋值:其实就是对象的引用(别名)。
浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象。
深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象。
解析
https://starky99.com/2019/07/02/Python/Python面试.html
1、b = a: 赋值引用,a 和 b 都指向同一个对象。
img
2、b = a.copy(): 浅拷贝, a 和 b 是一个独立的对象,但他们的子对象还是指向统一对象(是引用)。
img
b = copy.deepcopy(a): 深度拷贝, a 和 b 完全拷贝了父对象及其子对象,两者是完全独立的。
img
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from copy import copy, deepcopy
lst = [1, 2, [3, 4]]
a, b = copy(lst), deepcopy(lst)
a, b
([1, 2, [3, 4]], [1, 2, [3, 4]])id(lst[2]), id(a[2]), id(b[2])
(139842737414224, 139842737414224, 139842737414584)lst[0] = 10
a
[1, 2, [3, 4]]b
[1, 2, [3, 4]]lst[2][0] = ‘test’
lst
[10, 2, [‘test’, 4]]a
[1, 2, [‘test’, 4]]b
[1, 2, [3, 4]]
瀚文的话总结:
https://starky99.com/2019/07/02/Python/Python面试.html
赋值就是同一个对象
浅拷贝:是表面上是两个,但是里面的更深层次的嵌套还是同一个
深拷贝:完全独立,就是两个不相干的对象了
2.Python 中的 GIL 是什么?全称?举个例子说说其具体体现。
GIL 全称 Global Interpreter Lock(全局解释器锁),任何 Python 线程执行前,必须先获得 GIL 锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。要避免这种“现象”利用操作系统的多核优势可以有下面几种方法:
使用 C 语言编写扩展,创建原生线程,摆脱 GIL,但是即使是扩展,在 Python 代码内,任意一条Python 代码还是会有 GIL 限制
使用多进程代替多线程,使用多进程时,每个进程都有自己的 GIL。故不存在进程与进程之间的 GIL 限制。但是多进程不能共享内存。
3.Python函数定义及传参方式
一、函数初识
1、定义:
将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可。
2、好处:
代码重用;保持一致性;可扩展性。
3、示例如下:
1
2
3
4
5
6
def sayHello():
print(‘Hello world!’)
sayHello()
二、函数传参方式
如上面的实例是函数中最基础的一种,是不传参数的,说到这里,我们有必要了解一下何为函数参数:
1、函数参数:
形参变量: 只有在被调用时才分配内存单元,调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。
函数调用结束返回主调函数后不能再使用该形参变量
实参:可以是常量,变量,表达式,函数等,无论实参是何种类型的量,在进行函数调用,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值。
2、函数传参的分类
<1> 位置参数
位置参数顾名思义,就是调用函数时传的实参与函数的形参位置上一一对应的参数。 如下实例:
1
2
3
4
5
6
7
8
9
10
11
12
#位置参数
print(’\n以下是位置参数传值\n’)
def stu_info(name,age,major,country):
print(’--------学生信息-------’)
print(‘姓名:’,name)
print(‘年龄:’,age)
print(‘专业:’,major)
print(‘国籍:’,country)
stu1 = stu_info(‘Jack’,21,‘Chinese’,‘CN’) # 实参依次与函数中的name,age,major,country对应
stu2 = stu_info(‘Frank’,20,‘JP’,‘UN’)
stu3 = stu_info(‘Rose’,19,‘Art’,‘UK’)
<2> 默认参数
默认参数就有点不同了,是你在函数形参中定义好的,当实参中未传对应的参数时,它就派上用场了,默认给你加上。是不是有点贴心呢?
注意:默认参数,必须放在位置参数之后,否则会出错
实例如下:
1
2
3
4
5
6
7
8
9
10
11
12
#默认参数
print(’\n以下是默认参数传值\n’)
def stu_info(name,age,major,country = ‘CN’):# country设为了默认参数,必须放在位置参数之后,否则会出错
print(’--------学生信息-------’)
print(‘姓名:’,name)
print(‘年龄:’,age)
print(‘专业:’,major)
print(‘国籍:’,country)
stu1 = stu_info(‘Jack’,21,‘Chinese’) # 此处未传对应的值,但形参中已经定义了,所以不用担心找不家了!
stu2 = stu_info(‘Frank’,20,‘JP’) # 你也是的
stu3 = stu_info(‘Rose’,19,‘Art’,‘UK’) # 既然你已经传参了,就随你了。
<3> 关键参数
正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可(指定参数名的参数就叫关键参数),但记住一个要求就是,关键参数必须放在位置参数(以位置顺序确定对应关系的参数)之后。
还是奉上实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
#关键参数,不能重复赋值,且指定的参数应在位置参数之后
print(’\n以下是关键参数传值\n’)
def stu_info(name,age,major,country = ‘CN’): #
print(’--------学生信息-------’)
print(‘姓名:’,name)
print(‘年龄:’,age)
print(‘专业:’,major)
print(‘国籍:’,country)
stu1 = stu_info(‘Jack’,21,‘Chinese’)
stu2 = stu_info(‘Frank’,20,major=‘JP’) # major即为关键参数,单独指定,但必须放在位置参数之后
stu3 = stu_info(‘Rose’,19,‘Art’,country=‘UK’)
<4> 非固定传参
这种传参方式可就大有讲究了,花样可谓繁多,自然本领也就大多了,不信往下看。
可以细分为两类:
非固定传参方式一:
可同时指定多个用户,传过来的所有参数打包成元祖。如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#--coding:utf-8--
#方式一
def send_alert(msg,*users): # ’*users‘ 表示非固定传参,可同时指定多个用户,传过来的所有参数打包元祖
for u in users:
print(‘报警!请及时查看…’,u,msg)
send_alert(‘你的系统已濒临崩溃!’,‘cc’,‘hyt’,‘yuq’,‘dy’)
#方式二
def send_alert(msg,*users): # ’users‘ 表示非固定传参,可同时指定多个用户,传过来的所有参数打包元祖
for u in users:
print(‘报警!请及时查看…’,u,msg)
send_alert(‘你的系统已濒临崩溃!’,[‘cc’,‘hyt’,‘yuq’,‘dy’])
‘’’
如果列表前不加 * 号,整个列表就会被当作元组里的一个元素,
加 * 号后就相当于列表里每个元素都是元祖的一个元素了。就会向元组里的每个成员都发出讯息了。
‘’’
def send_alert(msg,*users,age):
for u in users:
print(‘报警!请及时查看…’,u,msg)
send_alert(‘你的系统已濒临崩溃!’,‘sc’,‘qh’,age=22)
‘’’
’*users‘此时会默认获取前一个位置参数之后所有的元素,若传参时最后不指定关键参数就会报错,age无法获取传值
‘’’
非固定传参方式二:
可同时指定多个用户,传过来的所有参数打包成元组或字典。如下:
1
2
3
4
5
6
7
8
9
10
#--coding:utf-8--
def func(name,*args,**kwargs): # 形参依次是位置参数,元组,字典
print(name,args,kwargs)
func(‘Hope’,22,‘CN’,‘tomorrow’) #输出:Hope (22, ‘CN’, ‘tomorrow’) {}
func(‘Try’,21,‘will’,addr=‘HG’,num=666) #输出:Try (21, ‘will’) {‘addr’: ‘HG’, ‘num’: 666}
dit = {‘major’:‘Math’,‘interest’:‘reading’}
func(‘want’,*[‘day’,‘up’],**dit) #输出:want (‘day’, ‘up’) {‘major’: ‘Math’, ‘interest’: ‘reading’}
4.请新建一个只有一个元素 1 的列表和元组。
1
2
lst = [1]
tup = (1,)
本文标题: Python面试
文章作者: David Stark
发布时间: 2019年07月02日 - 11:07
最后更新: 2019年07月15日 - 22:07
本文累计阅读:2
原始链接:
https://starky99.com/2019/07/02/Python/Python面试.html
—本文结束✔感谢阅读—
← Python里面的reduce函数和lambda · 190701每天都在进步 →
Chapter1 20道
试题:NO.01
试题:NO.02
试题:NO.03
试题:NO.05
试题:NO.06
试题:NO.07
试题:NO.08
试题:NO.09
试题:NO.10
试题:NO.11
试题:NO.12
试题:NO.13
试题:NO.14
试题:NO.15
试题:NO.16
试题:NO.17
试题:NO.18
试题:NO.19
试题:NO.20
Chapter2
1.单引号,双引号,三引号的区别
2.Python的参数传递是值传递还是引用传递
3.什么是lambda函数?它有什么好处?
4.字符串格式化:%和.format的区别
5.Python是如何进行内存管理的
6.写一个函数, 输入一个字符串, 返回倒序排列的结果
7.按升序合并如下两个list, 并去除重复的元素
8.以下的代码的输出将是什么? 说出你的答案并解释
9.下面的代码会不会报错
10.说出下面list1,list2,list3的输出值
11.写出你认为最Pythonic的代码
12.写出一段python 代码实现一个删除一个list 里面重复元素。
13.什么是切片?
14:模块是什么?
15:dir()是什么指令?
16:如何把一个文件内的字符串形式通过json转化为相应的字典格式?
17:反斜杠的困扰
18:python中 if name == ‘main‘: 的作用是什么呢
19:深浅copy
20:递归函数
Chapter3 110道
www.itcast.cn
Chapter4 Python比较全面的概述
Chapter Me Python知识技巧
1.直接复制、深拷贝和浅拷贝
2.Python 中的 GIL 是什么?全称?举个例子说说其具体体现。
3.Python函数定义及传参方式
4.请新建一个只有一个元素 1 的列表和元组。
— David Stark —
最新文章
博客-主题优化进阶篇
博客-主题优化高级篇
博客-CSS颜色
MORE →
分类
Python
技术
旅行
每日
算法
读书笔记
标签云
Blog
LeetCode
Python面试
Ubuntu
c++
docker
一亩三分地
人工智能
历史
实习
广州
房间选择
数据库
数据结构
旅游
旅行规划
暑研
杂记
环境
研究生申请
程序员
美国
职场
苏州
英语
规划
题
鸡汤
David Stark
搜索 …
David Stark © 2019
欢迎支持我的知乎Live?
David Stark icon
David Stark
—
Python面试
https://starky99.com/2019/07/02/Python/Python面试.html
原始链接: https://starky99.com/2019/07/24/tech/me/blog/我的博客部署.html
原始链接: https://starky99.com/2019/07/24/tech/knowledge/搜索引擎的技巧.html
原始链接: https://starky99.com/2019/07/28/tech/me/blog/Hexo-Casper主题.html
原始链接: https://starky99.com/2019/07/28/tech/me/blog/博客的属性.html
原始链接: https://starky99.com/2019/07/08/Python/pip3.html
原始链接: https://starky99.com/2019/07/02/Python/Python100例.html
原始链接: https://starky99.com/2019/07/02/Python/Python里面的reduce函数和lambda.html
原始链接: https://starky99.com/2019/06/10/读书笔记/《美国的故事》.html
原始链接: https://starky99.com/2019/06/29/onlyTAG/1point3acre/masterApply.html
原始链接: https://starky99.com/2019/06/28/travel/19Summer-Suzhou/A-sweet-trip-to-Suzhou-with-sweetie-Annika.html
原始链接: https://starky99.com/2019/06/24/tech/me/blog/搭建博客.html
原始链接: https://starky99.com/2019/07/03/tech/knowledge/当···时发生了什么?.html
原始链接: https://starky99.com/2019/07/02/Python/Python面试.html