常见面试题总结(1)
程序员文章站
2022-03-03 18:32:42
...
1、写一个程序交换两个变量的值?
方法一:使用加减法进行交换
1 #main方法
2 def main():
3 #提示用户输入的数据信息
4 numOne=int(raw_input("请输入第一个数字:"))
5 numTwo=int(raw_input("请输入第二个数字:"))
6
7 #打印数据信息
8 print("交换前的数据分别为:%d,%d"%(numOne,numTwo))
9
10 #进行数据的交换
11 numOne=numOne+numTwo
12 numTwo=numOne-numTwo
13 numOne=numOne-numTwo
14
15 #打印数据信息
16 print("交换后的数据分别为:%d,%d"%(numOne,numTwo))
17
18 #程序入口
19 if __name__ == '__main__':
20 main();
方法二:使用异或法进行交换
1 #main方法
2 def main():
3 #提示用户输入的数据信息
4 numOne=int(raw_input("请输入第一个数字:"))
5 numTwo=int(raw_input("请输入第二个数字:"))
6
7 #打印数据信息
8 print("交换前的数据分别为:%d,%d"%(numOne,numTwo))
9
10 #进行数据的交换
11 numOne=numOne^numTwo
12 numTwo=numOne^numTwo
13 numOne=numOne^numTwo
14
15 #打印数据信息
16 print("交换后的数据分别为:%d,%d"%(numOne,numTwo))
17
18 #程序入口
19 if __name__ == '__main__':
20 main();
------------------------------
2、在Python中,类和对象有什么区别?对象如何访问类的方法?对象和类能否互相访问对方的方法或者属性?
答:
类是一类对象的集合,是一个模版,封装了对象的属性和方法,是实例对象产生的工厂,类可以产生多个实例对象
主要特点:
class语句创建类对象并将其赋值给变量名;
class语句内的赋值语句会创建类的属性;
类属性提供对象的状态和行为;
对象是类的实例,由类的构造函数生成,实例化类的属性和方法
主要特点:
像函数那样调用对象会创建新的实例对象;
每个实例对象继承类的属性并获得了自己的命名空间;
在方法内对self属性做赋值运算会产生每个实例自己的属性
对于实例的属性和方法,只能由实例调用,类不可以调用
对于类的属性和方法,类和实例对象都可以去调用
3、用Python编写一个简单的socket程序,服务器想客户端发送一句话“Python is not hard”,客户端回送一句话“life is short,please use python”
1 #coding=utf-8
2
3 #引用对应的包
4 import socket
5 import sys
6 import threading
7 from time import sleep
8
9
10 #线程:模拟udp服务器向客户端发送一句话:Python is not hard
11 class ServerThread(threading.Thread):
12 #重写对应的构造方法
13 def __init__(self, port):
14 threading.Thread.__init__(self)
15 self.port = port
16
17 #进行run方法的重写操作
18 def run(self):
19 #创建udp服务器套接字
20 self.serverSoc=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
21
22 #元组,存储服务器端ip地址和端口号
23 self.locker = ('192.168.241.128',self.port)
24
25 #绑定服务器ip和端口
26 self.serverSoc.bind(self.locker)
27
28
29 #元组,存储要发送的指定客户端的ip地址和端口号,客户端指定端口号为8080
30 self.sendAddr = ('192.168.241.128',8080)
31
32
33 print("服务器开启")
34
35 sleep(1)
36
37 #变量,存储要发送的内容
38 self.sendDate = 'Python is not hard'
39
40 #进行数据向客户的发送
41 self.serverSoc.sendto(self.sendDate,self.sendAddr)
42
43 #阻塞,接受客户端回发回来的数据信息
44 self.recvDate,self.recvAddr = self.serverSoc.recvfrom(1024)
45
46 print("客户端:%s"%(self.recvDate))
47
48 #关闭套接字
49 self.serverSoc.close()
50
51
52 #线程:模拟udp客户端接受服务器发送的数据,并且恢复一句“life is short,please use python”
53 class ClientThread(threading.Thread):
54 #重写对应的构造方法
55 def __init__(self,port):
56 threading.Thread.__init__(self)
57 self.port = port
58
59 #重写对应的run方法
60 def run(self):
61 #创建udp客户端套接字
62 self.clientSoc = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
63
64 #元组,存储客户端ip地址和端口号,指定客户端端口号为8080
65 self.locker = ('192.168.241.128',8080)
66
67 self.sendAddr = ('192.168.241.128',self.port)
68
69 #绑定
70 self.clientSoc.bind(self.locker)
71
72 print("客户端开启")
73
74 # # #阻塞,等待接受服务器发送过来的数据信息
75 # self.recvDate = self.clientSoc.recvfrom(1024)
76 # print(type(self.recvDate)) #属性测试
77 # #服务器发送过来的数据为:('Python is not hard', ('192.168.241.128', 8080))
78 # print("服务器发送过来的数据为:%s"%(str(self.recvDate)))
79
80 #接受对应发送过来的数据信息
81 self.recvDate,self.recvAddr = self.clientSoc.recvfrom(1024)
82
83 print("服务器发送过来的数据为:%s"%self.recvDate)
84
85 #回发的数据信息
86 self.sendDate = ''
87
88 if(self.recvDate == 'Python is not hard'):
89 #回发的数据信息
90 self.sendDate = "life is short,please use python"
91
92 #客户端向服务器回复
93 self.clientSoc.sendto(self.sendDate,self. sendAddr)
94
95 #关闭套接字
96 self.clientSoc.close()
97
98
99 #main函数
100 def main():
101 #变量接受udp服务器指定端口号
102 port=int(sys.argv[1])
103
104 #多线程创建udp服务器和udp客户端
105 serverThread=ServerThread(port)
106 clientThread=ClientThread(port)
107
108 #开启线程
109 serverThread.start()
110 clientThread.start()
111
112
113
114 #程序入口
115 if __name__ == '__main__':
116 main()
4、请说明线程、进程的区别?分别说出它们通信的方式?
答:
进程:是CPU资源分配的最小单位;进程是系统进行资源分配和调度的一个独立单位,虚拟的内存空间,大小为4G
线程:是CPU调度的最小单位;线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
#程序上下文:执行一段程序代码时,当得到CPU的时候,相关的资源必须也已经就位,然后cpu开始执行。除了cpu以外所有的调用资源,就构成了这个程序的执行环境,及程序上下文。
#当这个程序执行完了,或者分配给他的cpu执行时间用完了,那它就要被切换出去,等待下一次cpu的资源的分配。在被切换出去的最后一步工作就是保存程序的上下文,因为这个是它下一次被分配到cpu资源执行的运行环境,必须保存。在cpu开来所有的任务都是一个一个轮流执行的,具体的轮流方法:先加载程序A的上下文-执行程序A-保存程序A的上下文,调入下一个要执行的程序B的上下文-执行程序B-保存程序B的上下文…依次执行下去
#进程和线程就是对应CPU时间段的描述。
#进程:包括上下文切换的程序执行时间总和=cpu加载上下文+cpu执行+cpu保存上下文(及cpu资源分配的最小单位)
#线程:由于进程的颗粒度太大,每次都要有上下文的调入、保存、调出。如果我们把进程比喻为一个在电脑上运行的软件,那么一个软件的执行不可能是一条逻辑执行的,必定有多个分支和多个程序段,就好比要实现程序A,实际上分成a、b、c等多个块组合而成。那么这里具体的执行就可能变成:程序A得到CPU--CPU加载程序A的上下文开始执行--程序A的a小段,然后执行程序A的b小段,然后执行程序A的c小段--最后CPU保存A的上下文
这里的a、b、c就是线程,也就是说线程是共享进程的上下文环境,更为细小的cpu时间段(及调度cpu的最小单位)
区别细节:
1、调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
2、并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
3、拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.
4、系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销
进程和线程的关系:
1、一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
2、资源分配给进程,同一进程的所有线程共享该进程的所有资源。
3、处理机分给线程,即真正在处理机上运行的是线程。
4 、线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。
线程是指进程内的一个执行单元,也是进程内的可调度实体.
进程通信:
进程间的通信方式:
1.管道(pipe)及有名管道(named pipe):
管道可用于具有亲缘关系的父子进程间的通信,有名管道除了具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。
2.信号(signal):
信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一致的。
3.消息队列(message queue):
消息队列是消息的链接表,它克服了上两种通信方式中信号量有限的缺点,具有写权限得进程可以按照一定得规则向消息队列中添加新信息;对消息队列有读权限得进程则可以从消息队列中读取信息。
4.共享内存(shared memory):
可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据得更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。
5.信号量(semaphore):
主要作为进程之间及同一种进程的不同线程之间得同步和互斥手段。
6.套接字(socket);
这是一种更为一般得进程间通信机制,它可用于网络中不同机器之间的进程间通信,应用非常广泛。
线程:锁机制、条件变量、队列
5、请说出长连接、短连接的区别?以及应用场景?
答:
TCP协议:三次握手—数据传输—四次挥手。
长连接:链接—传输数据—保持连接—传输数据--…--直到一方关闭连接,client向server发起连接,server接受client连接,双方建立连接。Client与server完成一次读写之后,它们之间的连接并不会主动关闭,后续的读写操作会继续使用这个连接。
短链接:链接—传输数据—关闭连接,client向server发起连接请求,server接到请求,然后双方建立连接。client向server发送消息,server回应client,然后一次读写就完成了,这时候双方任何一个都可以发起close操作,不过一般都是client先发起close操作
应用场景:
1.长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况,。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。
2. 像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。
------------------------------
6. Mysql的常用的引擎用哪些?Innodb和MYSAM的区别?
答:
MyISAM:这个是默认类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法.与其他存储引擎比较,MyISAM具有检查和修复表格的大多数工具. MyISAM表格可以被压缩,而且它们支持全文搜索.它们不是事务安全的,而且也不支持外键。如果事物回滚将造成不完全回滚,不具有原子性。如果执行大量的SELECT,MyISAM是更好的选择
MEMORY:在功能等同于MyISAM,但由于数据存储在内存(不是磁盘)中,速度很快(特别适用于临时表)
InnoDB:这种类型是事务安全的.它与BDB类型具有相同的特性,它们还支持外键.InnoDB表格速度很快.具有比BDB还丰富的特性,因此如果需要一个事务安全的存储引擎,建议使用它.如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表,
------------------------------
7. http协议常用的请求方式有几种?常见的状态码有哪些,各表示什么含义?
答:
GET: 请求指定的页面信息,并返回实体主体。
HEAD: 只请求页面的首部。
POST: 请求服务器接受所指定的文档作为对所标识的URI的新的从属实体。
PUT: 从客户端向服务器传送的数据取代指定的文档的内容。
DELETE: 请求服务器删除指定的页面。
1 100 (继续) 请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。 2 101 (切换协议) 请求者已要求服务器切换协议,服务器已确认并准备切换。 3 4 2xx (成功) 5 表示成功处理了请求的状态代码。 6 7 代码 说明 8 200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。 9 201 (已创建) 请求成功并且服务器创建了新的资源。 10 202 (已接受) 服务器已接受请求,但尚未处理。 11 203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。 12204 (无内容) 服务器成功处理了请求,但没有返回任何内容。 13 205 (重置内容) 服务器成功处理了请求,但没有返回任何内容。 14 206 (部分内容) 服务器成功处理了部分 GET 请求。15 16 3xx (重定向) 17 表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。18 19 代码 说明 20300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。 21 301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。 22 302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。 23 303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。 24 304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。 25 305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。 26 307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。27 28 4xx(请求错误) 29 这些状态代码表示请求可能出错,妨碍了服务器的处理。30 31 代码 说明 32 400 (错误请求) 服务器不理解请求的语法。 33 401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。 34 403 (禁止) 服务器拒绝请求。 35 404 (未找到) 服务器找不到请求的网页。 36 405 (方法禁用) 禁用请求中指定的方法。 37 406 (不接受) 无法使用请求的内容特性响应请求的网页。 38 407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。 39 408 (请求超时) 服务器等候请求时发生超时。 40 409 (冲突) 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。 41 410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。 42 411 (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。 43 412 (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。 44 413 (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。 45 414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。 46 415 (不支持的媒体类型) 请求的格式不受请求页面的支持。 47 416 (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。 48 417 (未满足期望值) 服务器未满足”期望”请求标头字段的要求。49 50 5xx(服务器错误) 51 这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。52 53 代码 说明 54 500 (服务器内部错误) 服务器遇到错误,无法完成请求。 55 501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。 56 502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。 57 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。 58 504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。 59 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。
8.CSS中display的值,并说出他们的作用?还有position的值的区别?
display属性:
none 此元素不会被显示。
block 此元素将显示为块级元素,此元素前后会带有换行符。
inline 默认。此元素会被显示为内联元素,元素前后没有换行符。
inline-block 行内块元素。(CSS2.1 新增的值)
list-item 此元素会作为列表显示。
run-in 此元素会根据上下文作为块级元素或内联元素显示。
compact CSS 中有值 compact,不过由于缺乏广泛支持,已经从 CSS2.1 中删除。
marker CSS 中有值 marker,不过由于缺乏广泛支持,已经从 CSS2.1 中删除。
table 此元素会作为块级表格来显示(类似 <table>),表格前后带有换行符。
inline-table 此元素会作为内联表格来显示(类似 <table>),表格前后没有换行符。
table-row-group 此元素会作为一个或多个行的分组来显示(类似 <tbody>)。
table-header-group 此元素会作为一个或多个行的分组来显示(类似 <thead>)。
table-footer-group 此元素会作为一个或多个行的分组来显示(类似 <tfoot>)。
table-row 此元素会作为一个表格行显示(类似 <tr>)。
table-column-group 此元素会作为一个或多个列的分组来显示(类似 <colgroup>)。
table-column 此元素会作为一个单元格列显示(类似 <col>)
table-cell 此元素会作为一个表格单元格显示(类似 <td> 和 <th>)
table-caption 此元素会作为一个表格标题显示(类似 <caption>)
inherit 规定应该从父元素继承 display 属性的值。
position 属性值的含义:
1、static:元素框正常生成。块级元素生成一个矩形框,作为文档流的一部分,行内元素则会创建一个或多个行框,置于其父元素中。
2、relative:元素框偏移某个距离。元素仍保持其未定位前的形状,它原本所占的空间仍保留。
3、absolute:元素框从文档流完全删除,并相对于其包含块定位。包含块可能是文档中的另一个元素或者是初始包含块。元素原先在正常文档流中所占的空间会关闭,就好像元素原来不存在一样。元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框。
4、fixed:元素框的表现类似于将 position 设置为 absolute,不过其包含块是视窗本身。
------------------------------
9. 请写出输出结果:
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
1 2 1
3 2 3
------------------------------
10.请用基于队列的方式写出生产者消费者模型?
1 #coding=utf-8
2 #引入对应的包
3 import threading
4
5 from Queue import Queue
6
7 from time import sleep
8
9 #线程生产者
10 class Producer(threading.Thread):
11 #重写run方法
12 def run(self):
13 global g_queue
14
15 while True:
16 if con.acquire():
17 #判断是否停止生产,获取队列中的数量
18 if g_queue.qsize() < 20:
19
20 #每次生产5个产品
21 for i in range(5):
22 g_queue.put("产品")
23
24 print("生产出5个产品,产品总量:%d"%g_queue.qsize())
25 else:
26 con.wait()
27 print("停止生产")
28
29 con.release()
30 sleep(1)
31
32
33 #线程消费者
34 class Consumer(threading.Thread):
35 #重写run方法
36 def run(self):
37 global g_queue
38
39 while True:
40 if con.acquire():
41 #判断是否停止消费
42 if g_queue.qsize()>5:
43 #进行消费
44 for i in range(3):
45 g_queue.get()
46
47 print("消费3 总数:%d"%g_queue.qsize())
48
49 if g_queue.qsize()<20:
50 con.notify()
51 con.release()
52 sleep(1)
53
54 #全局变量
55 con=threading.Condition()
56 #g_num=600
57 #创建一个队列
58 g_queue=Queue()
59
60
61 #main函数
62 def main():
63 pro=Producer()
64 pro.start()
65 con=Consumer()
66 con.start()
67
68 #程序入口
69 if __name__ == '__main__':
70 main()
上一篇: 传智健康项目讲义第十章 四