目录
101. 一个包里有三个模块,demo1.py, demo2.py, demo3.py,但使用 from tools import *导入模块时,如何保证只有 demo1、demo3 被导入了。
102. 列举 5 个 Python 中的异常类型以及其含义
104. 代码中经常遇到的*args, **kwargs 含义及用法。
105. Python 中会有函数或成员变量包含单下划线前缀和结尾,和双下划线前缀结尾,区别是什么?
125. 有一组“+”和“-”符号,要求将“+”排到左边,“-”排到右边,写出具体的实现方法。
131. 在 requests 模块中,requests.content 和 requests.text 什么区别
****************其他内容****************
84.解释一下python中pass语句的作用?
Python pass 是空语句,是为了保持程序结构的完整性。
pass 不做任何事情,一般用做占位语句
85.简述你对 input()函数的理解
result = input('put in something please:')
print(result)
print(type(result))
input()函数接收一个标准的输入的数据,返回string类型
86. python中的is和==
Python中对象包含的三个基本要素,分别是:id(身份标识)、type(数据类型)和value(值)。
is和==都是对对象进行比较判断作用的,但对对象比较判断的内容并不相同。
下面来看看具体区别在哪。
==是python标准操作符中的比较操作符,用来比较判断两个对象的value(值)是否相等
>>> a = 'cheesezh'
>>> b = 'cheesezh'
>>> a == b
True
is也被叫做同一性运算符,这个运算符比较判断的是对象间的唯一身份标识,也就是id是否相同
>>> x = y = [4,5,6]
>>> z = [4,5,6]
>>> x == y
True
>>> x == z
True
>>> x is y
True
>>> x is z
False
>>>
>>> print id(x)
>>> print id(y)
>>> print id(z)
87. Python 中的作用域
python中的作用域遵循LEGB原则:
L (Local) 局部作用域
E (Enclosing) 闭包函数外的函数中
G (Global) 全局作用域
B (Built-in) 内建作用域
python按照LEGB原则搜索变量,即优先级L>E>G>B 例如:
print(type(list)) #list为 builtins
list = 1
print(list)
a = 3 #globals
def func1( ):
a = 3 #enclosing
def func2( ):
a = 4 #locals
return func2
88. 三元运算写法和应用场景?
(1)y = 99 if x > 3 else 999
(2)result = {True:1, False:2}[a>b]
(3)result = (‘FalseValue’,’TrueValue’)[a>b]
只要符合条件符合要求都可以应用吧,问的什么破问题
89. 了解 enumerate 么?
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中
例:
普通的for循环
>>>i = 0
>>> seq = ['one', 'two', 'three']
>>> for element in seq:
... print i, seq[i]
... i +=1
...
0 one
1 two
2 three
使用enumerate的for循环
>>>seq = ['one', 'two', 'three']
>>> for i, element in enumerate(seq):
... print i, element
...
0 one
1 two
2 three
90. 列举 5 个 Python 中的标准模块
time,sys,os,datetime,random, shutil, re
91. 如何在函数中设置一个全局变量
global a
92. pathlib 的用法举例
引用网址:
https://www.jianshu.com/p/a820038e65c3
from pathlib import Path
p = Path(r'd:\test\tt.txt.bk')
p.name # 获取文件名
p.stem # 获取文件名除后缀的部分
p.suffix # 文件后缀
p.suffixs # 文件的后缀们...
# ['.txt', '.bk']
p.parent # 相当于dirnanme
# WindowsPath('d:/test')
p.parents # 返回一个iterable, 包含所有父目录
# <WindowsPath.parents>
for i in p.parents:
print(i)
# d:\test
# d:\
a.parts # 将路径通过分隔符分割成一个元祖
# ('d:\\', 'test', 'tt.txt.bk')
遍历文件夹
p = Path(r'd:\test')
p = Path(p, 'tt.txt') # 字符串拼接
p.exists() # 判断文件是否存在
p.is_file() # 判断是否是文件
p.is_dir() # 判断是否是目录
创建文件夹
p = Path(r'd:\test\tt\dd')
p.mkdir(exist_ok=True) # 创建文件目录(前提是tt目录存在, 否则会报错)
# 一般我会使用下面这种创建方法
p.mkdir((exist_ok=True, parents=True) # 递归创建文件目录
文件信息
p = Path(r'd:\test\tt.txt')
p.stat() # 获取详细信息
p.stat().st_size # 文件大小
p.stat().st_ctime # 创建时间
p.stat().st_mtime # 修改时间
93. Python 中的异常处理,写一个简单的应用场景
异常处理语句try except finally
def div(a, b):
try:
print(a / b)
except ZeroDivisionError:
print("Error: b should not be 0 !!")
else:
print('Run into else only when everything goes well')
finally:
print('Always run into finally block.')
try与except只有是分支选项只有一个可以执行,没有发生异常时else语句会执行,finally总是被执行
94. Python 中递归的最大次数,那如何突破呢?
import sys
sys.setrecursionlimit(1500) # set the maximum depth as 1500
def recursion(n):
if(n <= 0):
return
print (n)
recursion(n - 1)
if __name__ == "__main__":
recursion(1469)
默认递归次数是1000,实际运行递归不报错大概是970左右,第二行是修改最大递归次数方法set recursion limit
95. 什么是面向对象的 mro
mro, method resolution order 方法解析顺序
https://blog.youkuaiyun.com/wangjianno2/article/details/56672442 or
https://blog.youkuaiyun.com/weixin_42104289/article/details/88528301
96. isinstance 作用以及应用场景?
用来判断一个量是否是相应的类型
print(isinstance(a,int)) #判断a是否为int类型
97. 什么是断言?应用场景?
assert断言语句用来声明某个条件是真的,
其作用是测试一个条件是否成立,如果不成立则抛出异常
例1:
assert (v1 > v2),'{0} is not bigger than {1}'.format(v1,v2)
如果v1<v2,则抛出的异常是:
AssertionError: 1 is not bigger than 2
断言跟异常的区别:
断言是用来检查非法情况而不是错误情况的,用来帮开发者快速定位问题的位置。
异常处理用于对程序发生异常情况的处理,增强程序的健壮性和容错性
98. lambda 表达式格式以及应用场景?
例1:
f = lambda x: x/2
f(6)的结果是3
例2:
fs = [(lambda x,i=i:i/x)for i in range(10)]
如果上面的式子不写i=i,而是直接写i,此处的i是首先选用全局变量的,所以如果恰好有全局变量i,就会得出其他结果,要注意;
fs[6](2)的结果是3,[ ]内是i的值,()内是x的值,这里需要说明一下,fs的type是list但是这里的list是用表达式表示的,所以有些不同,
fs[2]
Out[105]: <function __main__.<listcomp>.<lambda>>
a = fs[2]
print(a(1))
2.0
如果是fs[:](3)或者fs(3)或者fs[11]都会报错,这是lambda与for迭代结合后的一些特性
99. 新式类和旧式类的区别
新式类都从object继承,经典类不需要。
新式类的MRO(method resolution order 基类搜索顺序)算法采用C3算法广度优先搜索,而旧式类的MRO算法是采用深度优先搜索
新式类相同父类只执行一次构造函数,经典类重复执行多次。
100. dir()是干什么用的?
获得模块的属性列表
101. 一个包里有三个模块,demo1.py, demo2.py, demo3.py,但使用 from tools import *导入模块时,如何保证只有 demo1、demo3 被导入了。
增加__init__.py文件,并在文件中增加:__all__ = ['mod1','mod3']
102. 列举 5 个 Python 中的异常类型以及其含义
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
103. copy 和 deepcopy 的区别是什么?
拷贝之前再说下 b =a,这种情况两者的id是一个
[[], []] 列表的嵌套, [{}, {}] 字典的嵌套,可变类型嵌套了可变类型, 浅拷贝只拷贝最外层,会生成新的对象, 内层是引用, 深拷贝外层和内层都会进行拷贝,都是全新的对象, 都有独立的存储空间
In [22]: a = [11, 22]
In [23]: b = [33, 44]
In [24]: c = [a, b]
In [25]: d = copy.copy(c)
In [26]: e = copy.deepcopy(c)
In [27]: id(c)
Out[27]: 2644923219336
In [28]: id(d)
Out[28]: 2644923160392
In [29]: id(e)
Out[29]: 2644923143624
In [30]: id(a)
Out[30]: 2644913732296
In [32]: id(d[0])
Out[32]: 2644913732296
In [33]: id(e[0])
Out[33]: 2644923077512
104. 代码中经常遇到的*args, **kwargs 含义及用法。
https://blog.youkuaiyun.com/lcxxcl_1234/article/details/80726668
*args和**kwargs主要用于函数定义。可以将不定数量的参数传递给某个函数
*args是用来发送一个非键值对的可变数量的参数列表给一个函数
**kwargs允许你将不定长度的键值对作为参数传递给一个函数。如果你想要在一个函数里处理带名字的参数,你应该使用**kwargs
其实关键是*与**,而args与kwargs换成其他也可以,只不过是一种常见的写法
105. Python 中会有函数或成员变量包含单下划线前缀和结尾,和双下划线前缀结尾,区别是什么?
_xxx
单下划线开头的变量,表明这是一个受保护(protected)的变量,原则上不允许直接访问
但是外部类还是可以访问到这个变量。
__xxx
双下划线开头的,表示的是私有类型(private)的变量,只能允许这个类本身进行访问,甚至它的子类也不可以,用于命名一个类属性(类变量),调用时名字会被改变
可以通过dir(sd)查看变量,通过python的私有变量碾压特性,sd.__name变成了sd._Student__name。Python把以两个或以上下划线字符开头且没有以两个或以上下划线结尾的变量当作私有变量。私有变量会在代码生成之前被转换为长格式(变为公有)。转换机制是这样的:在变量前端插入类名,再在前端加入一个下划线字符。这就是所谓的私有变量碾压(Private name mangling)
__xxx__
以双下划线开头,并且以双下划线结尾的,是内置变量,内置变量是可以直接访问的,如__init__,__import__或是__file__。所以,不要自己定义这类变量。
添加个进阶的链接:
https://www.cnblogs.com/hester/articles/4936603.html
106. w、a+、wb 文件写入模式的区别
w:只写模式,文件不存在则新建文件,文件指针在文件开头,会清空原来的文件内容
a+:读写模式,文件不存在新建文件,文件指针位于文件结尾,不会清空原来文件内容,可在任意位置读取,但只能在文件末尾写入
wb:与w的区别是,wb打开的是二进制模式,w打开的是文本模式,所有带‘b’的都是二进制模式打开
107. 举例 sort 和 sorted 的区别
使用sort()方法对list排序会修改list本身,不会返回新list,sort()不能对dict字典进行排序;
sorted方法对可迭代的序列排序生成新的序列,对dict排序默认会按照dict的key值进行排序,最后返回的结果是一个对key值排序好的list;
python2.4开始,list.sort()与sorted()增加了key参数,具体用法请自查
108. 什么是负索引?
负索引就是像a[-1],表示从末尾向前数的第一个
109. pprint 模块是干什么的?
pprint是打印模块,与print的区别是pprint打印出来的数据结构更加完整;
所谓的完整一般就是分行打印,每行一个数据结构,方便阅读;
110. 解释一下 Python 中的赋值运算符
111. 解释一下 Python 中的逻辑运算符
112. 讲讲 Python 中的位运算符

113. 在 Python 中如何使用多进制数字?
二进制:0bxxxx,
转为二进制:bin(xxx)
八进制:0oxxxx,
转为八进制:oct(xxx)
十进制:xxxx,
转为十进制:dec(xxx)
十六进制:0fxxxx,
转为十六进制:hex(xxx)
114. 怎样声明多个变量并赋值?
多个变量赋值:
a,b = 1,2
多个变量声明并赋值:
for i in range(10):
cmd = "var_%s = i" % i
exec (cmd)
#eval("var_%s" % i)
print (var_5)
结果:5
****************算法和数据结构****************
115. 已知:
AList = [1,2,3]
BSet = {1,2,3}
(1) 从 AList和BSet中查找4,最坏时间复杂度那个大?
(2) 从 AList和BSet中插入4,最坏时间复杂度那个大?
需要弄清楚列表与哈希表的区别:
对于查找,列表的时间复杂度是O(n), set是O(1)
对于插入,两个都是O(1)
可以关注下链接,讲的python数据结构与算法,很不错
https://www.cnblogs.com/pengsixiong/p/5304065.html
116. 用 Python 实现一个二分查找的函数
def dichotomy_search(list_f,target_d):
start = 0
end = len(list_f)-1
find_state = False
while start <= end and not find_state:
midpoint = (start+end)//2
#print(midpoint)
if list_f[midpoint] < target_d:
start = midpoint + 1
elif list_f[midpoint] > target_d:
end = midpoint - 1
else:
find_state = True
return (find_state,midpoint)
list_f = [1,2,3,4,5,6,7,8,9,11,23,45]
#target_d = 8
result = dichotomy_search(list_f,3)
print(result)
117. python 单例模式的实现方法
单例模式就是一个类只能创建一个实例化,创建的所有实例化的id都是相同的
单例模式实现有两种方式,
1. 使用__metaclass__元类来实现
class Singleton(type):
def __init__(cls, name, bases, dict):
super(Singleton, cls).__init__(name, bases, dict)
cls._instance = None
def __call__(cls, *args, **kw):
if cls._instance is None:
cls._instance = super(Singleton, cls).__call__(*args, **kw)
return cls._instance
class MyClass(metaclass= Singleton):
def __init__(self,name):
self.name = name
a = MyClass('')
print(a)
b = MyClass('')
print(b)
2.使用装饰器(decorator)
def singleton(cls, *args, **kw):
instances = {}
def _singleton():
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return _singleton
@singleton
class MyClass(object):
a = 1
def __init__(self, x=0):
self.x = x
3.使用模块
Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了
class Singleton(object):
def foo(self):
pass
singleton = Singleton()
保存为mysingleton.py文件
form * import singleton 这样就ok了
这是比较简单易实现的方法还有其他比如类方法等等
118. 使用 Python 实现一个斐波那契数列
1.用递归方式打印第n项
def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return(1)
elif n == 2:
return(1)
else:
return(fibonacci(n-1)+fibonacci(n-2))
print(fibonacci(10))
2.常规方法打印前n项数列
def fibonacci(n):
list_f = [0,1]
if n > 1:
for i in range(n-1):
list_f.append(list_f[i]+list_f[i+1])
return(list_f[:n])
print(fibonacci(10))
119. 找出列表中的重复数字
1.用count计数
mylist = [1,2,2,2,2,3,3,3,4,4,4,4]
myset = set(mylist)
for item in myset:
print("the %d has found %d" %(item,mylist.count(item)))
2.
from collections import Counter
result = Counter([1,2,2,2,2,3,3,3,4,4,4,4])
print(result)
需要说明,结果是dict,输出的结果是Counter({2: 4, 4: 4, 3: 3, 1: 1})
120. 找出列表中的单个数字
在119的1基础上稍微修改就可以
121. 写一个冒泡排序
list_f = [12,32,31,52,17,6,19,10]
def bubble_sort(list_f):
length_list = len(list_f)
while(length_list>1):
for i in range(length_list-1):
if list_f[i] > list_f[i+1]:
inmed_var = list_f[i]
list_f[i] = list_f[i+1]
list_f[i+1] = inmed_var
length_list = length_list-1
print(length_list)
return list_f
print(bubble_sort(list_f))
122. 写一个快速排序
快速排序常用且重要,这里总结出3种排序方式:
1.表达式方式
array = [2,5,6,1,2,89,34,21,3]
quick_sort = (
lambda array: array if len(array) <= 1 else
quick_sort([item for item in array[1:] if item <= array[0]])
+ [array[0]]
+ quick_sort([item for item in array[1:] if item > array[0]])
)
print(quick_sort(array))
通过一个表达式完成,有两点说明:
长表达式换行有两种方式一个是( ) or [ ] or { },另一种就是在想要换行的位置加’\’
另一个是,用lambda实现递归时,公式中的递归quick_sort( )括号内的内容是在当前执行出结果然后将list给递归函数,换句话说就是quick_sort([item for item in array[1:] if item <= array[0]])这个公式,递归时quick_sort(list),是这种模式,然后list是[item for item in array[1:] if item <= array[0]]的运行后的结果。
2.一般思路的块排
array = [2,5,6,1,2,89,34,21,3]
def quick_sort(array, left, right):
if left >= right:
return
low = left
high = right
key = array[low]
while left < right:
while left < right and array[right] > key:
right -= 1
array[left] = array[right]
while left < right and array[left] <= key:
left += 1
array[right] = array[left]
array[right] = key
quick_sort(array, low, left - 1)
quick_sort(array, left + 1, high)
quick_sort(array,0,8)
print(array)
感觉还是比较绕的,多在纸上写一下推到一下可能会更容易理解;
3.这种方法相对简洁一些
array = [2,5,6,1,12,89,34,21,3]
def quick_sort(array, l, r):
if l < r:
q = partition(array, l, r)
quick_sort(array, l, q - 1)
quick_sort(array, q + 1, r)
def partition(array, l, r):
x = array[r]
i = l - 1
for j in range(l, r):
if array[j] <= x:
i += 1
array[i], array[j] = array[j], array[i]
array[i + 1], array[r] = array[r], array[i+1]
return i + 1
quick_sort(array,0,len(array)-1)
print(array)
4.用栈的方式实现非递归的快排程序
array = [2,5,6,1,12,89,34,21,3]
def quick_sort(array, l, r):
if l >= r:
return
stack = [ ]
stack.append(l)
stack.append(r)
print(stack)
while stack:
low = stack.pop(0)
high = stack.pop(0)
if high - low <= 0:
continue
x = array[high]
i = low - 1
for j in range(low, high):
if array[j] <= x:
i += 1
array[i], array[j] = array[j], array[i]
array[i + 1], array[high] = array[high], array[i + 1]
stack.extend([low, i, i + 2, high])
print(stack)
quick_sort(array,0,len(array)-1)
print(array)
快排的几种实现方式都不是很好理解
123. 写一个拓扑排序
def toposort(graph):
in_degrees = dict((u,0) for u in graph) #初始化所有顶点入度为0
vertex_num = len(in_degrees)
for u in graph:
for v in graph[u]:
in_degrees[v] += 1 #计算每个顶点的入度
Q = [u for u in in_degrees if in_degrees[u] == 0] # 筛选入度为0的顶点
Seq = []
while Q:
u = Q.pop() #默认从最后一个删除
Seq.append(u)
for v in graph[u]:
in_degrees[v] -= 1 #移除其所有指向
if in_degrees[v] == 0:
Q.append(v) #再次筛选入度为0的顶点
if len(Seq) == vertex_num: #如果循环结束后存在非0入度的顶点说明图中有环,不存在拓扑排序
return Seq
else:
print("there's a circle.")
G = {'a':'bce','b':'d','c':'bd','d':'','e':'cd'}
print(toposort(G))
124. python 实现一个二进制计算
这个题目的真正目的我没有太理解,
如果理解成二进制的转化,bin( )也可以直接完成,不过这里需要注意的是,type(bin())是str,如果str进行加法,是将两个字符串拼接,并不是我们想要的计算
如果c = 0b11011,type(c)是intpython是没有二进制这个数据格式的,如果要实现只能转化成int计算后转回二进制形式
如果非要代码的形式实现二进制的+-*/,可能会繁琐一点,这里略
125. 有一组“+”和“-”符号,要求将“+”排到左边,“-”排到右边,写出具体的实现方法。
target = '+--++++--'
result1 = []
result2 = []
for i in target:
if i == '+':
result1.append(i)
else:
result2.append(i)
result1.extend(result2)
print(result1)
print(('').join(result1))
126. 单链表反转
class Node(object):
def __init__(self, data, next=None):
self.val = data
self.next = next
def fun4(head):
if head == None:
return None
L,M,R = None,None,head
while R.next != None:
L = M
M = R
R = R.next
M.next = L
R.next = M
return R
#测试用例
if __name__ == '__main__':
l1 = Node(3)
l1.next = Node(2)
l1.next.next = Node(1)
l1.next.next.next = Node(9)
l = fun4(l1)
print (l.val, l.next.val, l.next.next.val, l.next.next.next.val)
127. 交叉链表求交点
class ListNode:
def init(self, x):
self.val = x
self.next = None
def node(l1, l2):
length1, length2 = 0, 0
# 求两个链表长度
while l1.next:
l1 = l1.next
length1 += 1
while l2.next:
l2 = l2.next
length2 += 1
# 长的链表先走
if length1 > length2:
for _ in range(length1 - length2):
l1 = l1.next
else:
for _ in range(length2 - length1):
l2 = l2.next
while l1 and l2:
if l1.next == l2.next:
return l1.next
else:
l1 = l1.next
l2 = l2.next
128. 用队列实现栈
队列是先进先出,栈是先进后出,如果非要把队列当栈来实现的话,如下:
from collections import deque
queue = deque(["a"])
queue.append("b")
queue.append("c")
for _ in range(3):
print(queue.pop())
如果是queue.popleft( )的话,就符合先进先出的特性了;这个功能的实现其实是导入了tensorflow的包,算是钻了个空子吧。
129. 找出数据流的中位数
import heapq
class BigHeap():
def __init__(self):
self.arr = list()
def heap_insert(self, val):
heapq.heappush(self.arr, -val)
def heapify(self):
heapq.heapify(self.arr)
def heap_pop(self):
return -heapq.heappop(self.arr)
def get_top(self):
if not self.arr:
return
return -self.arr[0]
class SmallHeap():
def __init__(self):
self.arr = list()
def heap_insert(self, val):
heapq.heappush(self.arr, val)
def heapify(self):
heapq.heapify(self.arr)
def heap_pop(self):
return heapq.heappop(self.arr)
def get_top(self):
if not self.arr:
return
return self.arr[0]
class MedianHolder():
def __init__(self):
self.bigHeap = BigHeap()
self.smallHeap = SmallHeap()
def addNum(self, num):
if len(self.bigHeap.arr) == 0:
self.bigHeap.heap_insert(num)
return
if self.bigHeap.get_top() >= num:
self.bigHeap.heap_insert(num)
else:
if len(self.smallHeap.arr) == 0:
self.smallHeap.heap_insert(num)
return
if self.smallHeap.get_top() > num:
self.bigHeap.heap_insert(num)
else:
self.smallHeap.heap_insert(num)
self.modifyTwoHeapSize()
def getMedian(self):
smallHeapSize = len(self.smallHeap.arr)
bigHeapSize = len(self.bigHeap.arr)
if smallHeapSize + bigHeapSize == 0:
return None
smallHeapHead = self.smallHeap.get_top()
bigHeapHead = self.bigHeap.get_top()
if (smallHeapSize + bigHeapSize) %2 == 0:
return (smallHeapHead+bigHeapHead)/2
else:
return smallHeapHead if smallHeapSize > bigHeapSize else bigHeapHead
def modifyTwoHeapSize(self):
smallHeapSize = len(self.smallHeap.arr)
bigHeapSize = len(self.bigHeap.arr)
if smallHeapSize == bigHeapSize + 2:
self.bigHeap.heap_insert(self.smallHeap.heap_pop())
if bigHeapSize == smallHeapSize + 2:
self.smallHeap.heap_insert(self.bigHeap.heap_pop())
if __name__ == '__main__':
arr = [68,51,42,92,13,46,24,58,62,72,32]
medianHold = MedianHolder()
for i in range(len(arr)):
medianHold.addNum(arr[i])
print(medianHold.getMedian())
关于heapq的说明见以下链接:
https://rookiefly.cn/detail/225
130. 二叉搜索树中第 K 小的元素
1.递归
class Solution(object):
def kthSmallest(self, root, k):
self.count=k
self.res=0
def core(root):
if root :
core(root.left)
self.count=self.count-1
if self.count==0:
self.res=root.val
core(root.right)
core(root)
return self.res
2.循环
class Solution(object):
def kthSmallest(self, root, k):
stack=[]
while True:
if root:
stack.append(root)
root=root.left
else:
root=stack.pop()
k=k-1
if k==0:
return root.val
else:
root=root.right
****************爬虫问题****************
131. 在 requests 模块中,requests.content 和 requests.text 什么区别
可以参考这个链接:
https://blog.youkuaiyun.com/xie_0723/article/details/51361006
内容概括如下
区别总结就是:
requests.text返回的是Unicode型的数据。
requests.content返回的是bytes型也就是二进制的数据
操作方式就是,如果想取得文本就用.text,如果想获取图片,就用.content
给个例子:
import requests
jpg_url = 'http://img2.niutuku.com/1312/0804/0804-niutuku.com-27840.jpg'
content = requests.get(jpg_url).content
with open('demo.jpg', 'wb') as fp:
fp.write(content)
132. 简要写一下 lxml 模块的使用方法框架
lxml是处理网页数据的第三方库,用Cython实现。
细节参考链接:
https://www.cnblogs.com/ospider/p/5911339.html
133.说一说 scrapy 的工作流程
1.首先Spiders(爬虫)将需要发送请求的url(requests)经ScrapyEngine(引擎)交给Scheduler(调度器)。
2.Scheduler(排序,入队)处理后,经ScrapyEngine,DownloaderMiddlewares(可选,主要有User_Agent, Proxy代理)交给Downloader。
3.Downloader向互联网发送请求,并接收下载响应(response)。将响应(response)经ScrapyEngine,SpiderMiddlewares(可选)交给Spiders。
4.Spiders处理response,提取数据并将数据经ScrapyEngine交给ItemPipeline保存(可以是本地,可以是数据库)。
5.提取url重新经ScrapyEngine交给Scheduler进行下一个循环。直到无Url请求程序停止结束
https://blog.youkuaiyun.com/miner_zhu/article/details/81094077