转自黑马程序员《Python面试宝典》http://bbs.itheima.com/thread-402667-1-1.html 可以下载PDF文件。
目录
Q6 range()和xrange()的区别。(Python2)
Q8 现在考虑有一个 jsonline 格式的文件 file.txt 大小约为 10K,之前处理文件的代码如下所示.
Q9 read、readline和readlines的区别?
Q11 在except中return后还会执行finally中的代码吗?如何抛出自定义异常?
Q19 说明os.path 和sys.path分别表示什么?
Q1 代码中要修改不可变数据会出现什么问题?抛出什么异常?
代码会报错,抛出TypeErrory异常
- 可变数据类型:列表list和字典dict,集合set
- 不可变数据类型:基本数据类型(int,float,string)元组tuple
>>> a=tuple((1,23,5,34)) >>> a[1]=22 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment
Q2 不适用中间变量交换变量a,b的值。
方法1:
a=a+b b=a-b a=a-b
方法2:
a=a^b b=b^a a=a^b
方法3:
a,b=b,a
Q3 print调用的什么底层方法?
print方法默认调用sys.stdout.write方法,即往控制台打印字符串。
Q4 下面这段代码的输出结果是什么?请解释。
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)
结果为:
111 #继承自父类的类属性x,所有都一样,指向同一块内存地址。
121 #Child1.x进行赋值,指向了新的内存地址。
323 #更改Parent.x, 指向了新的内存地址,Child3继承父类,也指向改地址。
Q5 input()函数
在Python3中,input()获取用户输入,不论用户输入什么,获取到的都是字符串类型。
在Python2中有raw_input() input(),raw_input()在Python3中的input()作用一样,input()输入什么数据类型,获取到的就是什么数据类型。
Q6 range()和xrange()的区别。(Python2)
两者用法相同,不同的是range返回的结果是一个列表,而xrange的结果是一个生成器,前者是直接开辟一块内存空间来保存列表,后者是边循环边使用,只有使用时才会开辟内存空间,所以当列表很长时,使用xrange性能要比range好,而range则是用空间来换取时间。
在Python3中range()相当于2中的xrange(),所以3中已经没有xrange()函数了。
Q7 4G内存如何读取一个5G的数据?
方法一:
可以通过生成器,分多次读取,每次读取比较少量的数据进行处理,处理结束后在一次读取后面的数据。
方法二:
可以通过Linux命令split切割成小文件,然后对数据进行处理,此方法效率比较高。可以按照行数切割,也可以按照文件大小切割。
Q8 现在考虑有一个 jsonline 格式的文件 file.txt 大小约为 10K,之前处理文件的代码如下所示.
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) #处理每一行数据
现在要处理一个大小为 10G 的文件,但是内存只有 4G,如果在只修改 get_lines 函数而其他代码保持不变的情况下,应该如何实现?需要考虑的问题都有哪些?
要考虑的问题:
内存只有4G无法一次性读入10G的文件,需要分批读入。分批读入数据要记录每次读入数据的位置。
要考虑每次读入数据的大小,太小就会在读取操作上花费过多的时间。
修改后的代码:
def get_lines(): l=[] with open('file.txt','rb') as f: data=f.readlines(6000) l.append(data) yield l
书中给的代码并不能循环迭代,修改如下。
def get_lines(): # l=[] flag=True with open('file.txt','rb') as f: while flag: data=f.readlines(1000) # l.append(data) if data: yield data else: flag=False
Q9 read、readline和readlines的区别?
read:读取整个文件
readline:读取一行,使用生成器方法。
readlines:读取整个文件到一个迭代器以便遍历。
Q10 补充缺失的代码。
def print_directory_contents(sPath):
'''
这个函数接收文件夹的名称作为输入参数。
返回该文件夹中文件的路径
以及其包含文件夹中文件的路径
'''
#请补充代码
完整代码如下,
#首先导入os库 import os def print_directory_contents(sPath): #os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表。 #只支持在 Unix, Windows 下使用。 for sChild in os.listdir(sPath): #os.path.join(path1,path2,...)用于路径拼接文件路径 sChildPath=os.path.join(sPath,sChild) #os.path.isdir()函数判断是否为文件夹,是文件夹返回True. if os.path.isdir(sChildPath): print_directory_contents(sChildPath) else: print(sChildPath)
Q11 在except中return后还会执行finally中的代码吗?如何抛出自定义异常?
return之后依然执行finally中的代码。
用raise方法可以抛出自定义异常。
Q12 except的作用和用法。
try:
#except 要和try一起使用。
except:#捕获所有异常
except <异常名>:#捕获指定异常
except <异常1,异常2>:捕获异常1或者异常2
except<异常名>,<数据>:捕获指定异常及其附加的数据
except<异常1,异常2>,<数据>:捕获异常1或者异常2,及其附加的数据。
Q13 有哪些常用的python标注库。
标准库:os操作系统;time时间;random随机;pymysql连接数据库;threading线程;multiprocessing进程;queue队列;math数学
第三方库:django,flask,requests,hashlib,md5,selenium,scrapy,xadmin。
常用的科学计算库:Numpy,Scipy,Pandas
可视化库:matplotlib
Q14 赋值、浅拷贝和深拷贝的区别。
赋值
在python中,对象的赋值就是简单的对象引用。如:
a=[1,2,3,"abc",['hello',567]] b=a
此时a和b指向同一块内存地址,相当于把a的引用赋值给了b。
a is b,为True,id(a)=id(b)
赋值操作(包括对象作为参数、返回值)不会开辟新的内存空间,它只是赋值了对象的引用。修改了a,也就影响了b;修改了b也就意向了a。
浅拷贝 shallow copy
浅拷贝会创建新对象,其内容非元对象本身的引用,而是原对象内第一层对象的引用。
浅拷贝有三种形式:切片操作,工厂函数、copy模块中的copy函数。
切片操作:b=a[:] 或者b=[x for i in a];
工厂函数:b=list(a);
copy函数:b=copy.copy(a)
浅拷贝产生的列表b不再是列表a了,用is判断已经不是同一个对象了,id也不同,也不指向同一片内存空间。但是当我们使用id(x) for x in a 和 id(x) for x in b来查看a和b中元素地址时,会发现两者包含的元素的地址是相同。
需要注意的是浅拷贝值拷贝了一层,在列表a中有一个嵌套的list,修改嵌套列表中的袁术,列表的地址并未发生变化,指向的都是同一个位置。
深拷贝 deepcopy
深拷贝和浅拷贝相对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。因此它的时间和空间开销要高。
同时对列表a,如果使用b=copy.deepcopy(a),再修改列表b不会影响列表a,嵌套中列表也不会产生任何影响,因为深拷贝拷贝出来的对象是一个全新的对象,不再与原来的对象有任何关联。
注意:对于非容器对象,如数字、字符、以及其他的“原子”类型,没有拷贝一说,产生的都是原对象的引用。
如果元组变量值包含原子类型对象,即使采用了深拷贝,也只能得到浅拷贝。
Q15 __init__ 和__new__区别
__init__ 用来初始化实例,为其实例设置属性。
__init__的第一个占位参数是class的实例对象。
init 在对象创建后,对对象进行初始化。
__new__用来创建实例,在返回的实例上执行__init__,如果不返回实例那么__init__将不会执行。
__new__的第一个占位参数是class对象。
当一个类实例化时,最先执行的是__new__,而不是__init__。
new 是在对象创建之前创建一个对象,并将该对象返回给 init。
Q16 随机数
在python中用生成随机数的模块是random,在使用前需要import。
random.random():生成一个0-1之间的随机浮点数、
random.uniform(a,b):生成[a, b]之间的浮点数。
ramdom.randint(a,b):生成【a,b】之间的整数。
random.randrange(a,b,step):在指定的集合[a, b)中,以step为基数随机取一个数。
random.choice(sequence):从特定序列中随机取一个元素,这里的序列可以是字符串,列表,元组等。
Q17 输入某年某月某日,判断这一天是这一年的第几天?
源码如下,书中代码有一定错误。
import datetime def dayofyear(): try: years=int(input("请输入年份:")) months=int(input("请输入月份:")) days=int(input("请输入天:")) except: print("输入有误,请输入整数") date1=datetime.date(year=years,month=months,day=days) date2=datetime.date(year=years,month=1,day=1) return (date1-date2).days+1 if __name__ == '__main__': days=dayofyear() print(days)
Q18 打乱一个排好序的list对象
import random #random.shuffle()会在原地进行操作,没有返回值。 random.shuffle(alist)
Q19 说明os.path 和sys.path分别表示什么?
os.path:主要用于对系统路径文件的操作
sys.path:主要是对python解释器的系统环境参数的操作。(动态的改变Python解释器搜索路径。)
Q20 os模块常见方法
os.remove(‘path/filename’) 删除文件
os.rename(oldname, newname) 重命名文件
os.walk() 生成目录树下的所有文件名
os.chdir('dirname') 改变目录
os.mkdir/makedirs('dirname')创建目录/多层目录
os.rmdir/removedirs('dirname') 删除目录/多层目录
os.listdir('dirname') 列出指定目录的文件
os.getcwd() 取得当前工作目录
os.chmod() 改变目录权限
os.path.basename(‘path/filename’) 去掉目录路径,返回文件名
os.path.dirname(‘path/filename’) 去掉文件名,返回目录路径
os.path.join(path1[,path2[,...]]) 将分离的各部分组合成一个路径名
os.path.split('path') 返回( dirname(), basename())元组
os.path.splitext() 返回 (filename, extension) 元组
os.path.getatime\ctime\mtime 分别返回最近访问、创建、修改时间
os.path.getsize() 返回文件大小
os.path.exists() 是否存在
os.path.isabs() 是否为绝对路径
os.path.isdir() 是否为目录
os.path.isfile() 是否为文件
更多os模块的方法请参考:http://www.runoob.com/python3/python3-os-file-methods.html
Q21 python中sys模块常用方法?
sys.argv 命令行参数List,第一个元素是程序本身路径
sys.modules.keys() 返回所有已经导入的模块列表
sys.exc_info() 获取当前正在处理的异常类,exc_type、exc_value、exc_traceback当前处理的异常详细信息
sys.exit(n) 退出程序,正常退出时exit(0)
sys.hexversion 获取Python解释程序的版本值,16进制格式如:0x020403F0
sys.version 获取Python解释程序的版本信息
sys.maxint 最大的Int值
sys.maxunicode 最大的Unicode值
sys.modules 返回系统导入的模块字段,key是模块名,value是模块
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
sys.stdout 标准输出
sys.stdin 标准输入
sys.stderr 错误输出
sys.exc_clear() 用来清除当前线程所出现的当前的或最近的错误信息
sys.exec_prefix 返回平台独立的python文件安装的位置
sys.byteorder 本地字节规则的指示器,big-endian平台的值是'big',little-endian平台的值是'little'
sys.copyright 记录python版权相关的东西
sys.api_version 解释器的C的API版本
Q22 unittest
unittest是Python中的单元测试框架。它拥有支持共享搭建、自动测试、在测试中暂停代码、将不同测试迭代成一组等工程
Q23 模块和包
在python中模块是搭建程序的一种方式。每一个Python代码文件都是一个模块,并可以引用其他模块,比如对象和属性。
一个包含许多python代码的文件夹就是一包。一个包可以包含模块和子文件夹。
Q24 Python是强语言类型还是弱语言类型?
Python是强类型的动态脚本语言。
强类型:不允许不同类型相加。
动态:不使用显示数据类型声明,切确定一个变量的类型是在第一次给它赋值的时候。
脚本语言:一般也是解释型语言,运行代码只需要一个解释器,不需要编译。
Q25 解释型语言和编译型语言。
计算机不能直接理解高级语言,只能直接理解机器语言,所以必须要把高级语言翻译成机器语言,计算机才能执行高级语言编写的程序。
解释型语言在运行程序的时候才会进行翻译,边翻译边运行。
编译型语言在程序运行之前,需要一个专门的编译过程,把程序编译成机器语言,会生成一个编译文件,直接运行该编译文件即可。若源代码没有修改,再次运行程序时,无需再次编译。
Q26 Python日志
Python中自带logging模块,用于日志管理。调用logging.basicConfig()方法,配置需要的日志等级和相关参数,Python解释器会按照配置的参数生成相应的日志。
Q27Python是如何进行类型转换的?
Python内部封装了各种转换函数,可以使用目标类型关键字进行强制类型转换,进制之间的转换可以用int('str',base='n')将特定进制的字符串转换为十进制,再用相应的进制转换函数将十进制转换为目标进制。
还有列表和元组之间的相互转换:
list-->tuple tuple(list)
tuple-->list list(tuple)
Q28 Python2和Python3的区别。
核心类区别:
1.Python3对Unicode字符的原生支持。
Python2中使用ASCII码作为默认编码方式导致string有两种类型str和Unicode,Python3中只支持Unicode类型的string。
2.Python3中采用的是绝对路径的方式进行import。
Python2中相对路径的import会导致标准库导入变得困难(同一目录下有file.py,如何同时导入这个文件和标准库文件file)。Python3中这一点被修改了,如果还需要导入同一目录的文件必须使用绝对路径,否则只能使用相关导入的方式来进行导入。
3.Python2中存在老式类和新式类,Python3中统一采用新式类。新式类申明要求继承object,必须使用新式类应用多重继承。
4.Python3使用更加严格的缩进。Python2的缩进机制中,一个tab和8个space是等价的,所以在缩进中同时允许tab和space在代码中共存。这种等价机制会导致部分IDE使用存在问题。Python3中1个tab只能找另一个tab代替,因此tab和space共存会导致报错:TabError:inconsistent use of tabs and spaces in indentaion.
废弃类差别:1. print 语句被 Python3 废弃,统一使用 print 函数
2. exec 语句被 python3 废弃,统一使用 exec 函数
3. execfile 语句被 Python3 废弃,推荐使用 exec(open("./filename").read())
4. 不相等操作符"<>"被 Python3 废弃,统一使用"!="
5. long 整数类型被 Python3 废弃,统一使用 int
6. xrange 函数被 Python3 废弃,统一使用 range,Python3 中 range 的机制也进行修改并提高
了大数据集生成效率
7. Python3 中这些方法再不再返回 list 对象:dictionary 关联的 keys()、values()、items(),zip(),
map(),filter(),但是可以通过 list 强行转换:1. mydict={"a":1,"b":2,"c":3} 2. mydict.keys() #<built-in method keys of dict object at 0x000000000040B4C8> 3. list(mydict.keys()) #['a', 'c', 'b']
8. 迭代器 iterator 的 next()函数被 Python3 废弃,统一使用 next(iterator)
9. raw_input 函数被 Python3 废弃,统一使用 input 函数
10. 字典变量的 has_key 函数被 Python 废弃,统一使用 in 关键词
11. file 函数被 Python3 废弃,统一使用 open 来处理文件,可以通过 io.IOBase 检查文件类型
12. apply 函数被 Python3 废弃
13. 异常 StandardError 被 Python3 废弃,统一使用 Exception修改类差异:
1.浮点数除法操作符“/”和“//”的区别:
"/":
Python2 中若两个整形进行运算,结果为整形,但若其中有一个浮点数类型,则结果为浮点数。
python3为真除法,运算结果为float类型。
“//”:
Python2 中返回小于除法运算结果的最大整数,从类型上讲,与"/"运算符返回类型逻辑一致。
Python3中与python2作用相同。
2.异常抛出和捕捉机制的区别。
Python2
1. raise IOError, "file error" #抛出异常 2. except NameError, err: #捕捉异常
Python3
1. raise IOError("file error") #抛出异常 2. except NameError as err: #捕捉异常
3.for循环中变量值区别。
Python2 中,for循环会修改外部相同名称变量的值。
i=1 print('comprehension: ', [i for i in range(5)]) print('after: i=.',i) #i=4
Python3中,for循环不会修改外部相同名称变量的值。
i=1 print('comprehension: ', [i for i in range(5)]) print('after: i=.',i) #i=1
4.round函数返回值区别
Python2中,round函数返回float类型值。
isinstance(round(15.5),float) #True
Python3中,round函数返回int类型值。
isinstance(round(15.5),int) #True
5.比较操作符的区别。
Python2中任意两个对象都可以比较。
Python3中只有同一类型数据的对象才可以进行比较。
Q29 关于Python程序的运行,有什么手段能提升性能。
- 使用多进程,充分利用机器的多核性能。
- 对于性能意向比较大的部分代码,可以使用c或c++编写。
- 对于IO阻塞造成的性能影响,可以使用IO多路复用来解决。
- 尽量使用Python的内置函数。
- 尽量使用局部变量。
Q30 Python中的作用域。
Python,一个变量的作用域总是由在代码中被赋值的地方所决定。变量作用域的搜索顺序LEGB
本地作用域(Local)--》当前作用域被嵌入的本地作用域(Enclosing locals)----》 全局、模块作用域(Global)---》内置作用域(Built-in)
Q31 Python自省
Python自省是Python具有的一种能力,是程序员面向对象的语言所写的程序在运行时,能够获得对象的类型。更多关于Python自省请参考http://python.jobbole.com/82110/
Q32 Python代码规范
PEP8规范。