Python面试宝典

转自黑马程序员《Python面试宝典》http://bbs.itheima.com/thread-402667-1-1.html 可以下载PDF文件。

目录

Q1 代码中要修改不可变数据会出现什么问题?抛出什么异常?

Q2 不适用中间变量交换变量a,b的值。

Q3 print调用的什么底层方法?

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

Q5 input()函数

Q6 range()和xrange()的区别。(Python2)

Q7 4G内存如何读取一个5G的数据?

Q8 现在考虑有一个 jsonline 格式的文件 file.txt 大小约为 10K,之前处理文件的代码如下所示.

Q9 read、readline和readlines的区别?

Q10 补充缺失的代码。

Q11 在except中return后还会执行finally中的代码吗?如何抛出自定义异常?

Q12 except的作用和用法。

Q13 有哪些常用的python标注库。

Q14 赋值、浅拷贝和深拷贝的区别。

Q15 __init__ 和__new__区别

Q16 随机数

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

Q18 打乱一个排好序的list对象

Q19 说明os.path 和sys.path分别表示什么?

Q20 os模块常见方法

Q21  python中sys模块常用方法?

Q22 unittest

Q23 模块和包

Q24 Python是强语言类型还是弱语言类型?

Q25 解释型语言和编译型语言。

Q26 Python日志

Q27Python是如何进行类型转换的?

Q28 Python2和Python3的区别。

Q29 关于Python程序的运行,有什么手段能提升性能。

Q30 Python中的作用域。

Q31 Python自省

Q32 Python代码规范


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程序的运行,有什么手段能提升性能。

  1. 使用多进程,充分利用机器的多核性能。
  2. 对于性能意向比较大的部分代码,可以使用c或c++编写。
  3. 对于IO阻塞造成的性能影响,可以使用IO多路复用来解决。
  4. 尽量使用Python的内置函数。
  5. 尽量使用局部变量。

Q30 Python中的作用域。

Python,一个变量的作用域总是由在代码中被赋值的地方所决定。变量作用域的搜索顺序LEGB

本地作用域(Local)--》当前作用域被嵌入的本地作用域(Enclosing locals)----》 全局、模块作用域(Global)---》内置作用域(Built-in)

Q31 Python自省

Python自省是Python具有的一种能力,是程序员面向对象的语言所写的程序在运行时,能够获得对象的类型。更多关于Python自省请参考http://python.jobbole.com/82110/

Q32 Python代码规范

PEP8规范。

猜你喜欢

转载自blog.csdn.net/qq_24816993/article/details/81904280
今日推荐