目录
Python基础
1. print()函数调用Python底层的什么方法?
2. 简单说下对input()函数的理解
3. read、readline和readlines的区别
4. 在except中return还会不会执行finally中的代码?如何抛出自定义异常?
5. 内存小于文件大小的场景,如何读入文件内容?怎么实现?
6. 字符串拼接使用+和使用str.join()方法的比较
7. 经典类和新式类的区别
8. 单例模式实现
9. 赋值、浅拷贝和深拷贝
9.1 赋值
9.2 浅拷贝
9.3 深拷贝
10. Python单元测试框架
11. 输入年、月、日,判断这一天是这一年的第几天
12. 列举random模块的常用方法
13. lambda函数
14. 闭包
15. 不使用中间变量交换两个变量的值
Python并发
1. Python线程的描述
2. Python进程的描述
3. 进程与线程的区别
4. Python多线程执行耗时长的原因
数据库
1. 使用 Python DB Api访问数据库流程
Linux
1. find .
2. 查找目录中大于特定大小的文件
算法
1. 冒泡排序
1.1 原理
1.2 代码
1.3 分析
TCP/IP
1. 常见HTTP状态码
1.1 404
1.2 403
1.3 500
编程题
题目1:求字符串中的最长子串
题目描述
解决方案
代码
题目2: 求一个数的n次方
题目描述
解决方案
笔者总结下自己在2019.7 ---- 2019.8这个时间段内面试Python相关岗位时遇到的部分面试题。仅供参考。
绝大多数公司在面试的开始会提问几个基础性问题做为暖场。
答案:print()函数默认调用sys.stdout.write()方法,即往控制台打印字符串。
print()函数传送门:
https://blog.csdn.net/TCatTime/article/details/83450692
答案:在Python3中,input()函数获取用户输入,无论用户输入的是什么,获取到的都是字符串类型。
input()函数传送门:
https://blog.csdn.net/TCatTime/article/details/82556033
read()方法传送门:
https://blog.csdn.net/TCatTime/article/details/97376248
在except中return(甚至exit())都还会执行finally中的代码。
使用关键字raise抛出自定义异常。
设计思路
文件需要分批读入。分批读入数据要记录每次读入数据的位置;还要考虑每次分批读入数据的大小,太小就会在读取操作上花费过多时间。
代码实现
import os
def get_data(url, size):
if not os.isFile(url):
raise Exception("%s is not a file." % url)
if size <= 0:
raise Exception("Can not read file. Size must more than zero.")
with open(url, "r") as file:
while True:
line = file.readlines(size)
if not line:
break
yield line
在Python中字符串是不可变对象,修改字符串就得将原字符串中的值复制,开辟一块新的内存,将修改后的内容写到新内存中,以达到“修改”字符串的效果。使用+多次拼接字符串时,重复性的申请新内存和写入消耗了大量时间。而使用join()方法拼接字符串时,会先计算总共需要申请多少内存,然后一次性申请所需内存并将字符串拼接后的结果复制过去。这样便省去了重复性的内存申请和写入,节省了时间消耗。
str.join()方法传送门:
https://blog.csdn.net/TCatTime/article/details/85254896
def deo(cls):
ins = {}
def wapper(*args, **kwargs):
if cls not in ins:
ins[cls] = cls(*args, **kwargs)
return ins[cls]
return wapper
@ deo
class Demo():
pass
对象的赋值就是简单地对象引用。
赋值操作不会开辟新的内存空间,它只是复制了对象的引用。
>>> demo = 3
>>> new_demo = demo
>>> id(demo)
4531386368
>>> id(new_demo)
4531386368
【定义】
浅拷贝会创建新的对象,其内容并非原对象本身的引用,而是原对象内第一层对象的引用。
【浅拷贝的三种形式】
【示例】
例如下面的代码,使用copy.copy()函数浅拷贝了demo列表得到一个新列表new。new的内存地址与demo不同,但是new内的每一个元素的内存地址与demo的每一个元素的内存地址是一样的。
>>> import copy
>>> demo = [2, 6, 1]
>>> new = copy.copy(demo)
>>> id(demo)
4534666120
>>> id(new)
4534627272
>>>
>>> id(demo[0])
4531386336
>>> id(new[0])
4531386336
【定义】
深拷贝拷贝对象的所有元素,包括多层嵌套的元素。因此深拷贝的时空开销较高。
【深拷贝的形式】
【示例】
import copy
class Test():
def __init__(self, data):
self.level = data
if __name__ == '__main__':
t1 = Test(3)
t2 = Test(6)
demo = [t1, t2]
clone = copy.deepcopy(demo)
print("id(demo)=%s, id(clone)=%s" % (id(demo), id(clone)))
print("id(demo[0])=%s, id(clone[0])=%s" % (id(demo[0]), id(clone[0])))
运行结果:
id(demo)=4424245384, id(clone)=4424228296
id(demo[0])=4424516328, id(clone[0])=4424555600
可见,深拷贝将每一层嵌套的元素也都拷贝了。
unittest测试框架
import datetime
def compute_days(year, month, day):
try:
date1 = datetime.date(year=int(year), month=int(month),
day=int(day))
date2 = datetime.date(int(year), 1, 1)
result = (date1 - date2).days + 1
return result
except ValueError:
print("Invalid datetime %s-%s-%s." % (year, month, day))
⚠️注意事项:注意审题,结果是要求“第”几天,因此要在求得的最终差值上+1.
lambda函数是用一条语句表达的匿名函数,可以用它来代替小的函数。通常使用实际的函数会比使用lambda函数更清晰明了。但是,当需要定义很多小的函数以及记住它们的名字时,lambda会非常有用。
闭包是一个可以由另一个函数动态生成的函数,并且可以改变和存储函数外创建的变量的值。
>>> a = 1
>>> b = 2
>>> a, b = b, a
>>> print("a=%s, b=%s" % (a, b))
a=2, b=1
线程是一个基本的CPU执行单元。它必须依托于进程存活。一个线程是一个执行上下文,即一个CPU执行时所需要的一串指令。在Python中,多线程耗时更长。
进程是指一个程序在给定数据集合上的一次执行过程,是系统进行资源分配和运行调用的独立单位。可以简单地理解为操作系统中正在执行的程序。也就是说,每个应用程序都有一个自己的进程。
每一个进程启动时都会最先产生一个线程,即主线程。主线程会创建其它的子线程。
其它语言(例如Java),CPU是多核时是支持多个线程同时执行。但在Python中,无论程序执行在单核还是多核的机器,同时只能由一个线程在执行,其根源是GIL的存在。
GIL是全局解释器锁。来源是Python设计之初的考虑,为了数据安全所做的决定。某个线程想要执行,必须先拿到GIL。但在一个Python进程中,GIL只有一个。拿不到GIL的线程,就不允许进入CPU执行。
1、创建connection
2、获取cursor
3、执行命令,处理数据
4、关闭cursor
5、关闭connection
find . 命令列出当前目录下的所有文件和文件夹
find 目录 -size +大小
例如要查找当前目录下文件大于10k的文件:
➜ log git:(master_6.0.0) ✗ find /Users/mymac/FusionStudent_lite/log -size +10k
/Users/mymac/FusionStudent_lite/log/warn.log
/Users/mymac/FusionStudent_lite/log/.DS_Store
/Users/mymac/FusionStudent_lite/log/info.log
从第1个元素开始,比较相邻元素的大小。若大小顺序有误,则对调后再进行下一个元素的比较。如此扫描过一次之后,就可以确保最后一个元素位于正确的顺序。
def bubble_sort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n-i-1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
服务器无法根据客户端发送的请求找到资源(网页)。
服务器理解客户端的请求,但是拒绝执行此请求。
服务器内部错误,无法完成请求。
编写一个函数,要求在一个已知字符串找到最长的子串,子串要求首尾字符相同,在此子串中不能再包含首尾字符,输出复合要求的最长子串。
例如:ABCDAEFA的最长子串输出为BCD
请考虑所有可能的情况进行程序设计。
可以使用队列来解决此问题。当队列的首尾字符相同时,队列中间部分的字符串就是所得解。比较所有所得解的最长字符,就是最终的结果。最后将结果输出即可。
class Queue():
def __init__(self):
self.base = []
def insert(self, element):
self.base.append(element)
def length(self):
return len(self.base)
def pop(self):
if self.length() <= 0:
return
return self.base.pop(0)
def bingo(self):
if self.length() <= 1:
return False
return self.base[0] == self.base[-1]
def front(self):
if self.length() <= 0:
return
return self.base[0]
def exist(self, text):
if self.length() < 1:
return False
top = self.base[0]
if top in text:
return True
else:
return False
def dump(queue):
pre = ""
first = queue.pop()
while queue.front() != first:
pre += queue.pop()
return pre
def get_max_length_string(text):
result = ""
queue = Queue()
index = 0
for char in text:
queue.insert(char)
if queue.bingo():
pre = dump(queue)
if len(pre) > len(result):
result = pre
if not queue.exist(text[index:]):
queue.pop()
index += 1
return result
if __name__ == '__main__':
demo = "abacdsqa"
result = get_max_length_string(demo)
print(result)
给定一个整数x和一个整数n,求的值。要求时间复杂度尽可能低。
时间复杂度为的解决方案:
pow(x, n)
时间复杂度为的解决方案:
def my_pow(x, n):
if n == 0:
return 1
p = pow(x, n//2)
if n % 2 == 0:
return p * p
if n > 0:
return p * p * x
return p * p / x
在上例优化下,使用递归变成更短的时间复杂度:
def my_pow(x, n):
if n == 0:
return 1
p = pow(x, n//2)
if n % 2 == 0:
return p * p
if n > 0:
return p * p * x
return p * p / x
def power(x, n):
if n < 0:
result = my_pow(x, abs(n))
return 1 / result
else:
return my_pow(x, n)
if __name__ == '__main__':
print(power(3, -1))