Python 基础 面试问题

这篇博客详细介绍了Python的基础语法面试问题,涵盖输入输出、条件与循环、文件操作、异常、模块与包等内容。讨论了输入输出的异常处理、数据结构的特性、range与xrange的区别、文件读取策略以及异常处理的机制。此外,还讲解了Python中的模块与标准库,如os、time、random等,以及浅拷贝和深拷贝的概念和区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、基础语法

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()是否为文件

 

未完待续

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值