一、基础语法
1. 输入与输出
1.1 代码中要修改不可变数据会出现什么问题? 抛出什么异常?
代码不会正常运行,抛出TypeError 异常。
1.2 a=1,b=2,不用中间变量交换a 和b 的值?
a,b = b,a
1.3 print 调用Python 中底层的什么方法?
print 方法默认调用sys.stdout.write 方法,即往控制台打印字符串。
1.4 下面这段代码的输出结果将是什么?请解释?
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 #继承自父类的类属性x,所以都一样,指向同一块内存地址。
1 2 1 #更改Child1,Child1 的x 指向了新的内存地址。
3 2 3 #更改Parent,Parent 的x 指向了新的内存地址。
1.5 简述你对input()函数的理解?
在Python3 中,input()获取用户输入,不论用户输入的是什么,获取到的都是字符串类型的。
在Python2 中有raw_input()和input(), raw_input()和Python3 中的input()作用是一样的,input()输入的是什么数据类型的,获取到的就是什么数据类型的。
2. 条件与循环
2.1 阅读下面的代码,写出A0,A1 至An 的最终值。
A0 = dict(zip(('a','b','c','d','e'),(1,2,3,4,5)))
A1 = range(10)
A2 = [i for i in A1 if i in A0]
A3 = [A0[s] for s in A0]
A4 = [i for i in A1 if i in A3]
A5 = {i:i*i for i in A1}
A6 = [[i,i*i] for i in A1]
A0 = {'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4}
A1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
A2 = []
A3 = [1, 2, 3, 4, 5]
A4 = [1, 2, 3, 4, 5]
A5 = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
A6 = [[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36],[7, 49],[8, 64] [9,81]]
2.2 range 和xrange 的区别?
两者用法相同,不同的是range 返回的结果是一个列表,而xrange 的结果是一个生成器,前者是直接开辟一块内存空间来保存列表,后者是边循环边使用,只有使用时才会开辟内存空间,所以当列表很长时,使用xrange 性能要比range 好。
2.3 考虑以下Python 代码,如果运行结束,命令行中的运行结果是什么?
l = []
for i in range(10):
l.append({'num':i})
print(l)
在考虑以下代码,运行结束后的结果是什么?
l = []
a = {'num':0}
for i in range(10):
a['num'] = i
l.append(a)
print(l)
以上两段代码的运行结果是否相同,如果不相同,原因是什么?
上方代码的结果:
1. [{‘num’:0},{‘num’:1},{‘num’:2},{‘num’:3},{‘num’:4},{‘num’:5},{‘num’:6},{‘num’:7},{‘num’:8},
{‘num’:9}]
下方代码结果:
1. [{‘num’:9},{‘num’:9},{‘num’:9},{‘num’:9},{‘num’:9},{‘num’:9},{‘num’:9},{‘num’:9},{‘num’:9},
{‘num’:9}
原因是:字典是可变对象,在下方的l.append(a)的操作中是把字典a 的引用传到列表l 中,当后续操作修改a[‘num’]的值的时候,l 中的值也会跟着改变,相当于浅拷贝。
2.4 以下Python 程序的输出?
for i in range(5,0,-1):
print(i)
答:5 4 3 2 1
3. 文件操作
3.1 4G 内存怎么读取一个5G 的数据?
方法一:
可以通过生成器,分多次读取,每次读取数量相对少的数据(比如500MB)进行处理,处理结束后在读取后面的500MB 的数据。
方法二:
可以通过linux 命令split 切割成小文件,然后再对数据进行处理,此方法效率比较高。可以按照行数切割,可以按照文件大小切割。
3.2 现在考虑有一个jsonline 格式的文件cd.txt 大小约为10K,之前处理文件的代码如下所示:
def get_lines():
l = []
with open("C:\Users\Administrator\Desktop\cd.txt","rb") as f:
for eachline in f:
l.append(eachline)
return l
if __name__ == "__main__":
for e in get_lines():
print(e) #处理每一行数据
现在要处理一个大小为10G 的文件,但是内存只有4G,如果在只修改get_lines 函数而其他代码保持不变的情况下,应该如何实现?需要考虑的问题都有哪些?
def get_lines():
l = []
with open("C:\Users\Administrator\Desktop\cd.txt","rb") as f:
data = f.readlines(60000)
l.append(data)
yield l
要考虑到的问题有:
内存只有4G 无法一次性读入10G 的文件,需要分批读入。分批读入数据要记录每次读入数据的位置。分批每次读入数据的大小,太小就会在读取操作上花费过多时间。
3.3 read、readline 和readlines 的区别?
read:读取整个文件。
readline:读取下一行,使用生成器方法。
readlines:读取整个文件到一个迭代器以供我们遍历。
3.4.补充缺失的代码?
"""
这个函数接收文件夹的名称作为输入参数
返回该文件夹中文件的路径
以及其包含文件夹中文件的路径
os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表。
os.path.join()函数:连接两个或更多的路径名组件
1.如果各组件名首字母不包含’/’,则函数会自动加上
2.如果有一个组件是一个绝对路径,则在它之前的所有组件均会被舍弃
3.如果最后一个组件为空,则生成的路径以一个’/’分隔符结尾
os.path.isdir()函数判断某一路径是否为目录
"""
# 补充代码
import os
def print_directory_contents(sPath):
for sChild in os.listdir(sPath):
sChildPath = os.path.join(sPath, sChild)
if os.path.isdir(sChildPath):
print_directory_contents(sChildPath)
else:
print(sChildPath)
4. 异常
4.1 在except 中return 后还会不会执行finally 中的代码?怎么抛出自定义异常?
会继续处理finally 中的代码;用raise 方法可以抛出自定义异常。
4.2 介绍一下except 的作用和用法?
except: #捕获所有异常
except: <异常名>: #捕获指定异常
except:<异常名1, 异常名2> : 捕获异常1 或者异常2
except:<异常名>,<数据>:捕获指定异常及其附加的数据
except:<异常名1,异常名2>:<数据>:捕获异常名1 或者异常名2,及附加的数据
5. 模块与包
5.1 常用的Python 标准库都有哪些?
os 操作系统,time 时间,random 随机,pymysql 连接数据库,threading 线程,multiprocessing进程,queue 队列。
第三方库:
django 和flask 也是第三方库,requests,virtualenv,selenium,scrapy,xadmin,celery,
re,hashlib,md5。
常用的科学计算库(如Numpy,Scipy,Pandas)。
5.2 赋值、浅拷贝和深拷贝的区别?
一、赋值
在Python 中,对象的赋值就是简单的对象引用,这点和C++不同,如下所示:
a = [1,2,"hello",['python', 'C++']]
b = a
在上述情况下,a 和b 是一样的,他们指向同一片内存,b 不过是a 的别名,是引用。
我们可以使用b is a 去判断,返回True,表明他们地址相同,内容相同,也可以使用id()函数来查看两个列表的地址是否相同。
赋值操作(包括对象作为参数、返回值)不会开辟新的内存空间,它只是复制了对象的引用。也就是说除了b 这个名字之外,没有其他的内存开销。修改了a,也就影响了b,同理,修改了b,也就影响了a。
二、浅拷贝(shallow copy)
浅拷贝会创建新对象,其内容非原对象本身的引用,而是原对象内第一层对象的引用。
浅拷贝有三种形式:切片操作、工厂函数、copy 模块中的copy 函数。
比如上述的列表a;
切片操作:b = a[:] 或者b = [x for x 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 和b 是不同的对象,修改列表b 理论上不会影响到列表a。但是要注意的是,浅拷贝之所以称之为浅拷贝,是它仅仅只拷贝了一层,在列表a 中有一个嵌套的list,如果我们修改了它,情况就不一样了。 比如:a[3].append('java')。查看列表b,会发现列表b 也发生了变化,这是因为,我们修改了嵌套的list,修改外层元素,会修改它的引用,让它们指向别的位置,修改嵌套列表中的元素,列表的地址并未发生变化,指向的都是用一个位置。
三、深拷贝(deep copy)
深拷贝只有一种形式,copy 模块中的deepcopy()函数。
深拷贝和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。因此,它的时间和空间开销要高。
同样的对列表a,如果使用b = copy.deepcopy(a),再修改列表b 将不会影响到列表a,即使嵌套的列表具有更深的层次,也不会产生任何影响,因为深拷贝拷贝出来的对象根本就是一个全新的对象,不再与原来的对象有任何的关联。
四、拷贝的注意点
对于非容器类型,如数字、字符,以及其他的“原子”类型,没有拷贝一说,产生的都是原对象的引用。
如果元组变量值包含原子类型对象,即使采用了深拷贝,也只能得到浅拷贝。
5.3__init__ 和__new__的区别?
init 在对象创建后,对对象进行初始化。
new 是在对象创建之前创建一个对象,并将该对象返回给init
5.4 Python 里面如何生成随机数?
在Python 中用于生成随机数的模块是random,在使用前需要import. 如下例子可以酌情列
举:
random.random():生成一个0-1 之间的随机浮点数;
random.uniform(a, b):生成[a,b]之间的浮点数;
random.randint(a, b):生成[a,b]之间的整数;
random.randrange(a, b, step):在指定的集合[a,b)中,以step 为基数随机取一个数;
random.choice(sequence):从特定序列中随机取一个元素,这里的序列可以是字符串,列表,元组等。
5.5 输入某年某月某日,判断这一天是这一年的第几天?(可以用Python 标准库)
import datetime
def dayofyear():
year = int(input("请输入年份:"))
month = int(input("请输入月份:"))
day = int(input("请输入天:"))
date1 = datetime.date(year=int(year),month = int(month),day = int(day))
date2 = datetime.date(year=int(year),month = 1,day = 1)
return (date1 - date2).days+1
if __name__ == '__main__':
print(dayofyear())
5.6 打乱一个排好序的list 对象alist?
import random
random.shuffle(alist)
5.7 说明一下os.path 和sys.path 分别代表什么?
os.path 主要是用于对系统路径文件的操作。
sys.path 主要是对Python 解释器的系统环境参数的操作(动态的改变Python 解释器搜索路径)。
5.8 Python 中的os 模块常见方法?
os.remove()删除文件
os.rename()重命名文件
os.walk()生成目录树下的所有文件名
os.chdir()改变目录
os.listdir()列出指定目录的文件
os.getcwd()取得当前工作目录
os.chmod()改变目录权限
os.path.basename()去掉目录路径,返回文件名
os.path.dirname()去掉文件名,返回目录路径
os.path.join()将分离的各部分组合成一个路径名
os.path.split()返回(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()是否为文件
未完待续