申明:这里整理的面试题题目主要来源于网络搜集,答案根据自己实践整理修改。
1. 简述解释型语言和编译型语言区别
解释型:
在运行的时候将代码翻译成目标机器代码进行执行,每次执行都会进行翻译。现代解释型语言基本都会将源码翻译成中间字节码,然后在运行的时候将中间字节码翻译成目标机器代码进行执行。
编译型:
先编译成机器语言再执行,编译和执行是分开的。每次执行的时候不需要再编译。
2. Python解释器种类以及特点?
- CPython
c语言开发的 使用最广的解释器,默认使用的解释器。 - JPython
Java编写的,运行在Java上的解释器 直接把python代码编译成Java字节码执行。 - IPython
IPython 是一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数。 - PyPy
Python编写的。目标是执行效率 采用JIT(Just In Time:即时编译技术,简单的例子就是对于循环里的语句不会每次循环的时候都重新翻译,而是一次性翻译然后存起来,等到执行到的时候就将已经翻译过来的机器码直接拿来使用)技术 对python代码进行动态编译,提高执行效率。但是由于是用Python编写,所以在启动的时候会比CPython解释器启动慢。 - IronPython
.net编写的,运行在微软 .NET 平台上的解释器,把python编译成. NET 的字节码。
3. 请至少列举5个 PEP8 规范(越多越好)。
- 每一级缩进使用4个空格。
- 所有行限制的最大字符数为79。
- 顶层函数和类的定义,前后用两个空行隔开。
- 类里的方法定义用一个空行隔开。
- import通常在分开的行,例如:
推荐: import os
import sys
不推荐: import sys, os
4. 完成以下的进制转换
4.1 从10进制转成2、8、16进制
设v = 18
- 10进制转2进制
print(bin(v))
- 10进制转8进制
print(oct(v))
- 10进制转16进制
print(hex(v))
4.2 从2、8、16进制转10进制
- 2进制转10进制:v = "0b1111011"
print(int(v, 2))
- 8进制转10进制:v = "011"
print(int(v, 8))
- 16进制转10进制:v = "0x1c"
print(int(v, 16))
5. 请编写一个函数实现将IP地址转换成一个整数。
如 10.3.9.12 转换规则为:
10 -> 00001010
3 -> 00000011
9 -> 00001001
12 -> 00001100
再将以上二进制拼接起来计算十进制结果:00001010 00000011 00001001 00001100 = ?
def ip_transfer(ip):
ip_items = ip.split('.')
# 10进制转2进制 且 拼接
s = ''.join(bin(int(item))[2::] for item in ip_items)
return int(s, 2)
if __name__ == '__main__':
print(ip_transfer("10.1.15.110"))
6. python递归的最大层数
由于python为了防止无限递归,设计了递归限制是998。
可以自行设置递归最大限制
import sys
sys.setrecursionlimit(100000)
7. ascii、unicode、utf-8、gbk区别
- Ascii
美国信息互换标准代码 - Gbk
在gb2312的基础上增加了汉字,而gb2312在ascii的基础上增加了汉字 - Unicode
是字符集 - Utf-8
是编码规则,是对unicode的一种实现,可以将unicode码对应再编码成1-4字节大小。
8. 字节码和机器码的区别
- 字节码
字节码是一种中间状态(介于源代码和目标机器代码之间)的二进制代码。需要转译成目标机器代码。 - 机器码
计算机可以直接执行的代码。
9. 列举 Python2和Python3的区别
- Python2
- print "aa"
- 整数之间 / ,只保留整数部分
- 不等于 <>
- Python3
- print("aa")
- 整数之间 / ,保留小数部分
- 不等于 !=
10. Python3和Python2中 int 和 long的区别
在py2中,long是作为长整型的,但在py3中,没有long了,int长度不受限制。
11. xrange和range的区别
- xrange
xrange只在Python2中有,返回的是一个可迭代对象,但并不是迭代器,因为没有实现next。
在Python3中没有xrange。 - range
在Python2中,range返回一个list。
在Python3中,range类似于Python2中的xrange,返回的是一个可迭代对象,但也并不是迭代器,因为并没有实现next。
在Python2中xrange比range快,因为range会直接生成一个list,会一开始就开辟一块需要的内存空间,当范围越大这个内存空间越大,而xrange则是惰性计算的。但是为什么开辟一块大的内存空间就会导致慢呢?
详细关于Py2中的xrange、Python3中的range对象,与迭代器之间的区别,见https://zhuanlan.zhihu.com/p/34157478](https://zhuanlan.zhihu.com/p/34157478)
Python3中的range比xrange要快很多,详见https://zhuanlan.zhihu.com/p/24873916
12. 文件操作时:xreadlines和readlines的区别
- readlines
将所有的都读到内存,生成一个list - xreadlines
则返回一个迭代器,但是在py2.3之后就不推荐这么用了,取而代之的是下面这种,这种所需文件内容是自动从buffer中按照需要读取的。
For line in file:
# Do somenthing
13. 字符串、列表、元组、字典每个常用的5个方法
-
字符串
- join方法。如:
print(''.join(['a', 'b'])) >>> 'ab'
- split方法。如:
print('ab,c'.split(',')) >>> ['ab', 'c']
- strip方法。如:
print('abc'.strip('c')) >>> ab
- lstrip/rstrip方法。去掉左/右端的字符。如:
print('abc'.rstrip('c')) >>> ab
- count方法。计算字符串中的某个字符出现的次数。如:
print('accbc'.count('c')) >>> 3
- find方法。找到这个字符返回下标,多个时返回第一个;不存在的字符返回-1。如:
print('abc'.find('b')) >>> 1
-
列表
- 切片。
print(['a', 'b'][0:1]) >>> a
- append(self, obj)
l = [1,2] l.append(3) print(l) >>> [1,2,3]
- insert(self, index, obj)
l = [1,2] l.insert(1, 3) print(l) >>> [1,3,2]
- pop(self, index)
l = [1,2] l.pop(1) print(l) >>> [1]
- remove(self, obj)
l = [1,2] l.remove(2) print(l) >>> [1]
- 字典
- pop(key)
d = {'a':1, 'b':2}
d.pop('a')
print(d)
>>> {'b': 2}
- copy() 属于浅拷贝
d = {'a':1, 'b':2}
copy_d = d.copy()
print(copy_d)
>>> {'a': 1, 'b': 2}
- len(d)
d = {'a':1, 'b':[1]}
print(len(d))
>>> 2
- d.items() 返回由字典中的每一个键值对字典组成的列表
d = {'a':1, 'b':[1]}
print(d.items())
>>> dict_items([('a', 1), ('b', [1])])
- del d['key'] 删除指定的key对应的键值对
d = {'a':1, 'b':[1]}
del d['a']
print(d)
>>> {'b': [1]}
14. lambda表达式格式以及应用场景
lambda x: x+1
试用场景,不需要多次使用的地方,例如reduce、map、filter等。
15. pass的作用
没有实际意义,可以保持结构完整(当没想好要怎么写的时候就写个pass上去)
16. arg和*kwarg作用
可以获取未知个位置参数和关键字参数
17. is和==的区别
is比较的是id(存放的地址值就是) ==比较的是值
18. 简述Python的深浅拷贝以及应用场景
浅拷贝就是对引用的拷贝,深拷贝就是对资源的拷贝。
如下:b是浅拷贝,c是深拷贝。根据所打印的id值,可以看出来。
import copy
a = [1, [2, 3]]
b = copy.copy(a)
c = copy.deepcopy(a)
a[0] = 11
a[1].append(4)
print(a)
print(b)
print(c)
print(id(a[1]), id(b[1]), id(c[1]))
>>> [11, [2, 3, 4]]
>>> [1, [2, 3, 4]]
>>> [1, [2, 3]]
>>> 2127624863432 2127624863432 2127624889032
Python中,相同的数字或者字符串,都是引用的同一个地址,因此对于数字和字符串来说,无论通过赋值,浅拷贝还是深拷贝,同一个值永远用的是同一个内存地址。
应用场景:
当需要拷贝一份模板资料进行修改,就不能用浅拷贝,这样我用过了别人用的就可能会受到影响
19. Python垃圾回收机制
Python中的垃圾回收是以引用计数为主,利用标记清除算法解决引用计数的循环引用问题,通过分代收集提高标记清除的效率。
引用计数:
在Python中每一个对象的核心就是一个结构体PyObject,它的内部有一个引用计数器(ob_refcnt)。程序在运行的过程中会实时的更新ob_refcnt的值,来反映引用当前对象的名称数量。当某对象的引用计数值为0,那么它的内存就会被立即释放掉。但是引用计数无法解决循环引用的问题,例如:
a=[] a.append(a)
标记--清除算法:
- 标记阶段
遍历所有的对象,如果是可达的(reachable),也就是还有对象引用它,那么就标记该对象为可达。 - 清除阶段
再次遍历对象,如果发现某个对象没有标记为可达,则将其回收。
分代回收:
在循环引用对象的回收中,整个应用程序会被暂停,为了减少应用程序暂停的时间,Python 通过“分代回收”(Generational Collection)以空间换时间的方法提高垃圾回收效率。
分代回收是基于这样的一个统计事实,对于程序,存在一定比例的内存块的生存周期比较短;而剩下的内存块,生存周期会比较长,甚至会从程序开始一直持续到程序结束。生存期较短对象的比例通常在 80%~90% 之间,这种思想简单点说就是:对象存在时间越长,越可能不是垃圾,应该越少去收集。这样在执行标记-清除算法时可以有效减小遍历的对象数,从而提高垃圾回收的速度。
python gc给对象定义了三种世代(0,1,2),每一个新生对象在generation zero中,如果它在一轮gc扫描中活了下来,那么它将被移至generation one,在那里他将较少的被扫描,如果它又活过了一轮gc,它又将被移至generation two,在那里它被扫描的次数将会更少。
详见:https://zhuanlan.zhihu.com/p/83251959
20. Python的可变类型和不可变类型
- 可变类型
list、set、dict - 不可变类型
string、int、float、tuple、frozenset(不可变集合)
21. 求结果
题目:
v = dict.fromkeys(['k1','k2'],[])
v['k1'].append(666)
print(v)
v['k1'] = 777
print(v)
结果:
{'k1': [666], 'k2': [666]}
{'k1': 777, 'k2': [666]}
原因:
因为k1和k2对应的value是同一个list地址,当v['k1'].append(666)的时候,由于k1和k2指向的是同一个地址,所以k2对应的value和k1的一样。当v['k1'] = 777的时候,k1对应的value的地址变了,但是k2对应的值还是之前的list的地址,所以k1变成了777,k2还是[666]。
22. 求值
题目:
def num():
return [lambda x:i*x for i in range(4)]
print([m(2) for m in num()])
结果:
[6, 6, 6, 6]
原因:
一般可能认为答案应该是[0, 2, 4, 6],但是由于Python闭包的延迟绑定的特性,答案变成了[6, 6, 6, 6]。
Python的延迟绑定其实就是只有当运行到该函数的时候,才会引用外部变量i,不运行的时候,并不是会去找i的值。
在当前的题目中,num()只是返回4个lambda对象组成的list,此时lambda函数并没有运行。如下:
[<function num.<locals>.<listcomp>.<lambda> at 0x000002A67F4E8488>, <function num.<locals>.<listcomp>.<lambda> at 0x000002A67F4E8400>, <function num.<locals>.<listcomp>.<lambda> at 0x000002A67F4E8510>, <function num.<locals>.<listcomp>.<lambda> at 0x000002A67F4E8598>]
当运行到[m(2) for m in num()]的时候,才会真正运行到lambda函数。此时,i已经是3了,所以实际上得到的结果是[6, 6, 6, 6]
23. 列举常见的内置函数
len、bin、hex、oct、dir、max、min、type、sorted、isinstance、issubclass
24. filter、map、reduce的作用
- filter(function, iterable)
根据function,将iterable中的不符合条件的过滤掉。filter返回一个迭代器。
例如:
l = [1,2]
l = filter(lambda x: True if x==1 else False, l)
print(l)
print(list(l))
>>> <filter object at 0x0000020ADB68B2B0>
>>> [1]
- map(func, iterables)
将func作用域iterables中的每个序列的参数,返回一个map对象,该map对象也是一个迭代器。
例如:
l = map(lambda x,y :x+y, [1,2], [2,3])
print(list(l))
>>> [3, 5]
- reduce(function, sequence, initial=None)
function是一个接受2个参数的函数。将function累计地作用到sequence中的每个元素上,从左到右,将这个sequence的所有值计算成一个值。
例如:
print(reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]))
# ((((1+2)+3)+4)+5)
>>> 15
25. 一行代码实现9*9乘法表
- 这里用了f-string
print('\n'.join([' '.join([f'{y} * {x} = {x * y}' for y in range(1, x+1)]) for x in range(1,10)]))
26. 至少列举8个常用模块都有那些
os sys json time datetime random requests copy re...
27. re的match和search区别
- match
必须字符串的开头就匹配上。 - search
不需要字符串的开头就匹配上。匹配到结果后就返回
28. 什么是正则的贪婪匹配
贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配,而非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配。
例如:
import re
s = 'abbcbbc'
res1 = re.search(r'a.*c', s)
res2 = re.search(r'a.*?c', s)
print(res1[0])
print(res2[0])
>>> abbcbbc
>>> abbc
29. 求结果
- 1 or 2
1 - 1 and 2
1 - 1 < (2==2)
False
因为(2==2)先执行 - 1 < 2 == 2
True
因为Python可以链式比较,这里这句话是相当于(1<2) and (2==2)
30. def func(a,b=[]) 这种写法有什么坑
假如在调用的时候不给b传值,用默认的list,会造成所有默认的都是用同一个list
例如:
def func(a, b=[]):
b.append(a)
print(b)
func(1)
func(1)
>>> [1]
>>> [1, 1]
31. 如何实现 “1,2,3” 变成 [‘1’,’2’,’3’]
"1,2,3".split(',')
32. 如何实现[‘1’,’2’,’3’]变成[1,2,3]
l = ['1','2','3']
lis = list(map(lambda x:int(x), l))
33. 比较: a = [1,2,3] 和 b = [(1),(2),(3) ] 以及 b = [(1,),(2,),(3,) ] 的区别
a是列表
b = [(1),(2),(3)] 虽然列表的每个元素加上了括号,但是当括号内只有一个元素并且没有逗号时,其数据类型是元素本身的数据类型
b2中的元素是tuple[元组]
34. 如何用一行代码生成[1,4,9,16,25,36,49,64,81,100]
li = [x*x for x in range(1,11)]
35. 一行代码实现删除列表中重复的值
list0 = ['b', 'c', 'd', 'b', 'c', 'a', 'a']
print(list(set(list0)))
36. 如何在函数中设置一个全局变量
- step1. 在全局作用域申明一个变量
- step2. 在函数中,通过global关键字将该变量申明为全局变量。如果不申明,会被当成函数内的局部变量而报错。
例如:
a = 1
def func():
global a
a += 1
func()
print(a)
>>> 2
37. logging模块的作用,以及应用场景
logging.debug(msg, *args, **kwargs)
logging.info(msg, *args, **kwargs)
logging.warning(msg, *args, **kwargs)
logging.error(msg, *args, **kwargs)
logging.critical(msg, *args, **kwargs)
作用:根据不同需要输出不同等级、详细程度不同的信息。
应用场景:网站运维,程序的实时监控。
38. 请用代码简答stack
class Stack():
def __init__(self):
self._stack = []
def push(self, v):
self._stack.append(v)
def pop(self):
try:
return self._stack.pop()
except IndexError:
raise ValueError("empty stack")
def is_empty(self):
return bool(self._stack)
def watch(self):
return self._stack
39. 常用字符串格式化哪几种
- %s %d
a= 'f'
print('%s' % a)
>>> f
- f-string
a = 1
print(f'{a}+2={a+2}')
>>> 1+2=3
- format
print('{name} am handsome boy.'.format(name="I"))
>>> I am handsome boy.
40. 生成器、迭代器、可迭代对象、应用场景
- 生成器
可以理解为是一种一边循环一边计算的数据类型。
两种方式:- 生成器表达式。例如:
print(i for i in range(10)) >>> <generator object <genexpr> at 0x000001F6BA656A40>
- 函数中加yield。例如:
def func(): for i in range(10): yield i print(func()) >>> <generator object func at 0x00000251C8716A40>
- 迭代器
任何实现了iter和next的对象就是迭代器。例如:
from collections import Iterator
class IterA:
def __iter__(self):
pass
def __next__(self):
pass
print(isinstance(IterA(), Iterator))
>>> True
- 可迭代对象
对象内部实现了iter()方法,并调用这个方法可返回一个迭代器对象。例如:
from collections import Iterable
class IterA:
def __iter__(self):
pass
print(isinstance(IterA(), Iterable))
>>> True
应用场景:优化代码,节省内存
41. 用Python实现一个二分查找的函数
def two_search(list, value):
lindex = 0
rindex = len(list) - 1
cindex = (lindex + rindex) // 2 # / 在py3中是包括了小数部分的
res = -1
# 二分法唯一的一个问题是,当所求的数是最右边的时候,按照cindex = (lindex + rindex) / 2的方式,当cindex = lindex的时候会死循环
if list[-1] == value:
res = rindex
else:
while lindex != cindex or cindex == 0:
if value == list[cindex]:
res = cindex
break
elif value > list[cindex]:
lindex = cindex
cindex = (lindex + rindex) // 2
else:
rindex = cindex
cindex = (lindex + rindex) // 2
return res
l = [1, 2, 3, 4, 5, 6, 9, 19, 40]
print(two_search(l, 5))
>>> 4
42. 谈谈你对闭包的理解
- 闭包可以使得我们能获取到外部函数的参数和局部变量。
- 闭包的使用,可以减少全局变量的污染,因为当使用全局变量的时候,全局变量可以被其他的所有的函数修改。
- 闭包在装饰器上也有应用,把被修饰的函数作为参数保存了下来。
- 闭包的缺点:是常驻内存的,会对增大内存的使用量。
43. os和sys模块的作用
- os
os模块负责程序与操作系统的交互,提供了访问操作系统底层的接口;
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd - sys
sys模块负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控python的运行时环境。
Sys.exit(n)退出程序
Sys.version返回python解释器版本
44. 如何生成一个随机数
- Random.random() 随机生成一个浮点数,但是不能指定范围
- Random.uniform(start,stop)随机生成一个浮点数,可以指定范围
- Random.randomint(start, stop)生成一个整形的随机数
45. 如何使用python删除一个文件
Os.remove()
46. 谈谈你对面向对象的理解
- 面向对象是一种编程思想。思想是万物皆对象。所有物体可以归类,每个实际的东西就是对应的那个类别的实例。
- 面向对象的编程是以对象为中心,以消息为驱动的,就是 程序=对象+消息。
- 面向对象有三大特性:
封装:将具体的对象封装成抽象的类,对外封装属性,但是提供使用接口,目的是降低复杂 度,加大安全性。
继承:儿子继承爸爸的方法和属性,减少冗余代码。
多态:通过多态可以实现用一个函数名调用不同内容的函数。分为静态多态性和动态多态性
静态多态性:静态就是在执行之前python解释器已经知道要调用哪个函数了,多态就是我们不用管到底是操作的对象是什么类型的,多种形态都是可以进行这个运算的。
动态多态性:编译时无法立即确定其处理方式 , 只有在执行时才确定处理方式 , 注意一定要同名
47. Python面向对象中的继承有什么特点
- 在新式类中,方法的调用按照C3算法:拓扑排序+最左优先原则。
48. 面向对象中super的作用
调用父类的方法
49. 是否使用过functools中的函数?其作用是什么
functools主要是一些python高阶函数相关的函数
reduce函数
作用是用传入的函数对序列的每个值递进式地计算,最终计算出一个值。
50. 列举面向对象中带双下划线的特殊方法。
- new:实例化对象的时候被调用
- dict:获取类或对象中的所有成员
- getitem、setitem、delitem:通过 [] 被调用
- getattr、setattr、delattr:通过 . 被调用
- call:为了将一个实例当做函数一样调用,例如a是A的实例,让a()可以直接执行
- str:打印实例的时候调用的,一般是return一个字符串。例如a=A(),print(a)就会执行
51. 如何判断是函数还是方法
在类中定义的函数就是方法
52. 静态方法和类方法区别
- 静态方法:当类去调用方法的时候不用实例化实例就可以调用;参数设置上不需要传递表示实例的self参数;依赖于装饰器@staticmethod
- 类方法:当类去调用的时候不用实例化;参数设置上,第一个表示实例的self参数被表示类的cls取代了;依赖于装饰器@classmethod
这里的self和cls都只是大家默认的而已,改成任何别的字母都是可以的
53. 1、2、3、4、5 能组成多少个互不相同且无重复的三位数
count = 0
for i in range(1, 6):
for j in range(1, 6):
for k in range(1, 6):
if i != j and j != k and i != k:
count += 1
print(count)
>>> 60
54. 什么是反射?以及应用场景
它的核心本质其实就是利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动。
应用场景:当a写程序程序写到一半没写完,但是b写的会用到a中的函数或者类,b就可以通过反射机制写完自己的程序。
55. metaclass作用,以及应用场景
作用:
metaclass直译为元类
metaclasss可以作为类声明时候的一个参数,可以传入我们自定义的元类
元类相当于是类的类,Python中内置的元类是type
所以所有自定义的元类都需要继承自type
应用场景:
可以控制类的调用,比方说当类中没有注释(doc)的时候,抛出异常之类,当类的名称命名规则不对的时候,抛出异常之类
56. 单例模式
是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
57. 装饰器
特点:
- 不改变原函数的源代码
- 不改变原函数的调用
实现:
利用闭包、高阶函数、语法糖实现。
例如:
def wrapper(f):
def inner(*args, **kwargs):
print("before")
f()
print("after")
return inner
@wrapper
def func():
print(1)
func()
>>> before
>>> 1
>>> after
带参数的装饰器:
在wrapper外面再套一层函数来接受参数,并将wrapper方法返回。在语法糖调用的时候加上括号,并填入参数,就相当于在执行到@语法糖对应的语句之前先执行了outer(a="...")函数,而outer函数返回wrapper函数,这样在把参数通过outer(a="...")函数传递进去之后,又变成了@wrapper的形式。
def outer(a):
def wrapper(f):
def inner(*args, **kwargs):
print("before")
print("print outer's args: ", a)
f()
print("after")
return inner
return wrapper
@outer(a="outer")
def func():
print(1)
应用场景:
性能测试、权限判断等
58. 什么是面向对象的mro
mro(method resolution order)方法解析列表
代表了新式类继承的顺序,具体是用了一个c3算法,就是拓扑排序+最左优先原则
59. isinstance作用以及应用场景
isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。
isinstance() 与 type() 区别:
type() 不会认为子类是一种父类类型,不考虑继承关系。
isinstance() 会认为子类是一种父类类型,考虑继承关系。
如果要判断两个类型是否相同推荐使用 isinstance()。
60 . json序列化时,可以处理的数据类型有哪些,如何定制支持datetime类型
可以处理的数据类型:
string、int、list、tuple、dict、bool、null
支持datetime:
import json
import datetime
ret = datetime.datetime.now()
class CJsonEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.date):
return obj.strftime('%Y-%m-%d %H:%M:%S')
else:
return json.JSONEncoder.default(self, obj)
print(json.dumps(ret, cls=CJsonEncoder))
61. json序列化时,默认遇到中文会转换成unicode,如果想要保留中文怎么办
在序列化是将json.dumps中的默认参数ensure_ascii改为False就可以保留中文了
json.dumps(obj,ensure_ascii=False)
62. 什么是断言,应用场景
什么是断言:
断言是编程术语,表示为一些布尔表达式。如果它为真,就不做任何事。如果它为假,则会抛出AssertError并且包含错误信息。
应用场景:
在执行某些步骤前,先检查参数是否正确。
63. 有用过with statement吗,它的好处是什么
有用过,用来打开文件的时候使用。
好处:
- 解决异常退出时资源释放的问题; (不用try catch)
- 解决用户忘记调用close方法而产生的资源泄漏问题;(不用手动关闭)
64. 使用代码实现查看列举目录下的所有文件
import os
import sys
sys.setrecursionlimit(100000)
def pridir(path=os.getcwd()):
list = os.listdir(path)
if len(list) != 0:
for i in list:
newpath = path+os.sep+i
if os.path.isdir(newpath):
pridir(newpath)
elif os.path.isfile(newpath):
print(i)
pridir("D:\\rm")
65. 简述 yield和yield from关键字
-
yield:
1.向外抛出value
2.暂停等待外部send/next()恢复
3.将send进来的值赋值 -
yield from
yield from iterable本质上等于for item in iterable: yield item的缩写版
例如:
def fun_inner():
i = 0
while True:
i = yield i
# outer的作用就是将传递进来的参数传给inner,并且把inner返回的传给调用outer的地方
def fun_outer():
inner = fun_inner()
inner.send(None)
while True:
a = inner.send(1)
yield a
if __name__ == '__main__':
outer = fun_outer()
outer.send(None)
for i in range(5):
print(outer.send(i))
用yield from修改后如下:
def fun_inner():
i = 0
while True:
i = yield i
def fun_outer():
yield from fun_inner()
if __name__ == '__main__':
outer = fun_outer()
outer.send(None)
for i in range(5):
print(outer.send(i))
网友评论