我的面试准备
Python
值传递和引用传递
参考:https://www.jianshu.com/p/e93b6131a5cb
- python中统一都是引用传递,同时要注意类型是属于对象的,而不是变量。而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。
- 不可变实际上指的是不会更该字符串,比如把a = '123' 变为 a ='1234' 实际上是先创建了 “1234” 再用a去指向它。像list,dict等“可更改”的变量,他们会直接再本地更改,不会进行副本拷贝。
- c = copy.copy(a) #对象拷贝,浅拷贝
d = copy.deepcopy(a) #对象拷贝,深拷贝 - 函数把引用指向了一个不可变对象,当函数返回的时候,外面的引用没半毛感觉.
函数内的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改.
垃圾回收
- 当对象被创建时, 就创建了一个引用计数, 当这个对象不再需要时, 也就是说, 这个对象的引用计数变为0 时, 它被垃圾回收。但是回收不是"立即"的, 由解释器在适当的时机,将垃圾对象占用的内存空间回收。
- 垃圾回收机制不仅针对引用计数为0的对象,同样也可以处理循环引用的情况。循环引用指的是,两个对象相互引用,但是没有其他变量引用他们。这种情况下,仅使用引用计数是不够的。Python 的垃圾收集器实际上是一个引用计数器和一个循环垃圾收集器。作为引用计数的补充, 垃圾收集器也会留心被分配的总量很大(即未通过引用计数销毁的那些)的对象。 在这种情况下, 解释器会暂停下来, 试图清理所有未引用的循环。
函数方法
参考:https://www.runoob.com/python3
匿名函数
参考:https://www.cnblogs.com/xiao-apple36/p/8577727.html#_label0_0
- 例一:if else
calc = lambda x,y:x * y if x > y else x / y print(calc(2,5))
例二:与map函数使用li = [1,2,3,4,5,6,7,8,9] print(list(map(lambda x:x*x,li))) # [1, 4, 9, 16, 25, 36, 49, 64, 81]
例三:与reduce函数使用#接受一个list并利用reduce()求积 from functools import reduce li = [1,2,3,4,5,6,7,8,9] print(reduce(lambda x,y:x * y,li)) # 结果=1*2*3*4*5*6*7*8*9 = 362880
例四:与filter函数使用# 回数是指从左向右读和从右向左读都是一样的数,例如12321,909。请利用filter()筛选出回数 li = list(range(1, 200)) print(list(filter(lambda x:int(str(x))==int(str(x)[::-1]),li))) [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191]
例五:与sorted函数使用# 对列表按照绝对值进行排序 li= [-21, -12, 5, 9, 36] print(sorted(li, key = lambda x:abs(x))) # [5, 9, -12, -21, 36]
装饰器
知识点:__call__,类的实例对象
from functools import wraps class logit(object): def __init__(self, logfile='out.log'): self.logfile = logfile def __call__(self, func): @wraps(func) def wrapped_function(*args, **kwargs): log_string = func.__name__ + " was called" print(log_string) # 打开logfile并写入 with open(self.logfile, 'a') as opened_file: # 现在将日志打到指定的文件 opened_file.write(log_string + '\n') # 现在,发送一个通知 self.notify() return func(*args, **kwargs) return wrapped_function def notify(self): # logit只打日志,不做别的 pass
TCP/IP
OSI网络七层模型
参考:https://www.cnblogs.com/javayu/p/5853460.html
TCP三次握手
参考:https://blog.csdn.net/qq_38950316/article/details/81087809
TCP四次挥手
参考:https://blog.csdn.net/qq_38950316/article/details/81087809
ping命令执行过程详解
参考:https://www.cnblogs.com/cherishry/p/5717387.html
- 同一网段
ping通知系统建立一个固定格式的ICMP请求数据包
ICMP协议打包这个数据包和机器B的IP地址转交给IP协议层(一组后台运行的进程,与ICMP类似)
IP层协议将以机器B的IP地址为目的地址,本机IP地址为源地址,加上一些其他的控制信息,构建一个IP数据包
获取机器B的MAC地址
IP层协议通过机器B的IP地址和自己的子网掩码,发现它跟自己属同一网络,就直接在本网络查找这台机器的MAC
若两台机器之前有过通信,在机器A的ARP缓存表应该有B机IP与其MAC的映射关系
若没有,则发送ARP请求广播,得到机器B的MAC地址,一并交给数据链路层
数据链路层构建一个数据帧,目的地址是IP层传过来的MAC地址,源地址是本机的MAC地址,再附加一些控制信息,依据以太网的介质访问规则,将他们传送出去
机器B收到这个数据帧后,先检查目的地址,和本机MAC地址对比
符合,接收。接收后检查该数据帧,将IP数据包从帧中提取出来,交给本机的IP协议层协议。IP层检查后,将有用的信息提取交给ICMP协议,后者处理后,马上构建一个ICMP应答包,发送给主机A,其过程和主机A发送ICMP请求包到主机B类似(这时候主机B已经知道了主机A的MAC地址,不需再发ARP请求)
不符合,丢弃 - 不同网段
ping通知系统建立一个固定格式的ICMP请求数据包
ICMP协议打包这个数据包和机器B的IP地址转交给IP协议层(一组后台运行的进程,与ICMP类似)
IP层协议将以机器B的IP地址为目的地址,本机IP地址为源地址,加上一些其他的控制信息,构建一个IP数据包
获取主机B的MAC地址
IP协议通过计算发现主机B与自己不在同一网段内,就直接交给路由处理,就是将路由的MAC取过来,至于怎么得到路由的MAC地址,和之前一样,先在ARP缓存表中寻找,找不到可以利用广播。路由得到这个数据帧之后,再跟主机B联系,若找不到,就向主机A返回一个超时信息。
Linux
awk '{print $1,$4}' log.txt sed -e 4a\newline testfile
SQL
JOIN
参考:https://www.runoob.com/sql/sql-join.html
容器
Pod的创建流程
参考:https://blog.csdn.net/yan234280533/article/details/72567261
具体的创建步骤包括:
- 客户端提交创建请求,可以通过API Server的Restful API,也可以使用kubectl命令行工具。支持的数据类型包括JSON和YAML。
- API Server处理用户请求,存储Pod数据到etcd。
- 调度器通过API Server查看未绑定的Pod。尝试为Pod分配主机。
- 过滤主机 (调度预选):调度器用一组规则过滤掉不符合要求的主机。比如Pod指定了所需要的资源量,那么可用资源比Pod需要的资源量少的主机会被过滤掉。
- 主机打分(调度优选):对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略,比如把容一个Replication Controller的副本分布到不同的主机上,使用最低负载的主机等。
- 选择主机:选择打分最高的主机,进行binding操作,结果存储到etcd中。
- kubelet根据调度结果执行Pod创建操作: 绑定成功后,scheduler会调用APIServer的API在etcd中创建一个boundpod对象,描述在一个工作节点上绑定运行的所有pod信息。运行在每个工作节点上的kubelet也会定期与etcd同步boundpod信息,一旦发现应该在该工作节点上运行的boundpod对象没有更新,则调用Docker API创建并启动pod内的容器。
svc & kube-proxy
参考:https://blog.csdn.net/qihoo_tech/article/details/100166604