1、Python面试题总结资料仅供参考1.Python线程池原理? 我理解为线程池是一个存放很多线程的单位,同时还有一个对应的任务队列。整个执行过程其实就是使用线程池中已有有限的线程把任务队列中的任务做完。这样做的好处就是你不需要为每个任务都创立一个线程,因为当你创立第100个线程来执行第100个任务的时候,可能前面已经有50个线程结束工作了。超过最大值的线程能够排队,但她们要等到其它线程完成后才启动。因此重复利用线程来执行任务,减少系统资源的开销。2.Python合并字典,相同key的value如何相加?利用collections.Counter可轻松办到x=apple:1,banana:2y=
2、banana:10,pear:11fromcollectionsimportCounterX,Y=Counter(x),Counter(y)z=dict(X+Y)zapple:1,banana:12,pear:11另一种写法fromcollectionsimportCounterdict(Counter(x)+Counter(y)(合并两个字典的方法方法1:dictMerged1=dict(dict1.items()+dict2.items()方法2:dictMerged2=dict(dict1,*dict2)方法2等同于:dictMerged=dict1.copy()dictMerged.u
3、pdate(dict2)或者dictMerged=dict(dict1)dictMerged.update(dict2)3.解释GUI和GPL?GUI图形用户界面(GraphicalUserInterface,简称GUI,又称图形用户接口)是指采用图形方式显示的计算机操作用户界面。GPL(GNU通用公共许可证)GPL同其它的自由软件许可证一样,许可社会公众享有:运行、复制软件的自由,发行传播软件的自由,获得软件源码的自由,改进软件并将自己作出的改进版本向社会发行传播的自由。4.简述爬虫的基本步骤和流程?网络爬虫的基本工作流程如下:1.首先选取一部分精心挑选的URL;2.将这些URL放入待抓取U
4、RL队列;3.从待抓取URL队列中取出待抓取在URL,(解析DNS,而且得到主机的ip,)并将URL对应的网页下载下来,存储进已下载网页库中。另外,将这些URL放进已抓取URL队列。4.分析已抓取URL队列中的URL和其中的有价值的数据,将新的URL,放入待抓取URL队列,将数据存储起来,从而进入下一个循环。5.你们公司的业务中,并发能达到多少?6.如何循环抓取一个网站的1000张图片?流程大概是这样找到所有页数-遍历所有的页数-遍历当前页的所有相册(给每个相册建立一个目录)-遍历当前相册的所有图片(遍历此相册的所有页(遍历当前页的所有照片并找到图片的url)-获得图片url就存起来,然后经过
5、图片url下载图片。-引用计数当图片下载量达到1000张时,停止爬取。7.如果对方网站能够反爬取,封ip怎么办?1、放慢抓取速度,减小对于目标网站造成的压力。可是这样会减少单位时间类的抓取量。2、第二种方法是经过设置代理IP等手段,突破反爬虫机制继续高频率抓取。可是这样需要多个稳定的代理IP。代理IP能够搜索到免费的,可是可能不太稳定,也有收费的,可是不一定划算,也可能不是长久之计。普通的基于ADSL拨号的解决办法一般,在抓取过程中遇到禁止访问,能够重新进行ADSL拨号,获取新的IP,从而能够继续抓取。可是这样在多网站多线程抓取的时候,如果某一个网站的抓取被禁止了,同时也影响到了其它网站的抓取
6、,整体来说也会降低抓取速度。一种可能的解决办法同样也是基于ADSL拨号,不同的是,需要两台能够进行ADSL拨号的服务器,抓取过程中使用这两台服务器作为代理。假设有A、B两台能够进行ADSL拨号的服务器。爬虫程序在C服务器上运行,使用A作为代理访问外网,如果在抓取过程中遇到禁止访问的情况,立即将代理切换为B,然后将A进行重新拨号。如果再遇到禁止访问就切换为A做代理,B再拨号,如此重复。如下图:使用A为代理,B拨号:8.简述移动端app数据的抓取流程1、例如:爬取手机淘宝,核心还是一个WEB页面:2、有很多资讯类的APP,核心都是一个WEB页面。直接用爬虫的方法抓就能够了。3、非WEB页面的APP
7、,用APP自动化的一些东西试试4、不然就只有抓包了。9.是否了解Python的函数参数传递的机制?python的参数传递机制具有值传递(int、float等值数据类型)和引用传递(以字典、列表等非值对象数据类型为代表)两种基本机制以及方便的关键字传递特性(直接使用函数的形参名指定实参的传递目标,如函数定义为deff(a,b,c),那么在调用时能够采用f(b=1,c=2,a=3)的指定形参目标的传递方式,而不必拘泥于c语言之类的形参和实参按位置对应)除此之外,python中还允许包裹方式的参数传递,这未不确定参数个数和参数类型的函数调用提供了基础:deff(*a,*b)包裹参数传递的实现是在定义
8、函数时在形参前面加上*或*,*所对应的形参(如上面的a)会被解释为一个元组(tuple,而*所对应的形参(如上面的b)会被解释为一个字典。10.是否了解*args和*kwargs的用法?当函数的参数不确定时,能够使用*args和*kwargs,*args没有key值(列表),*kwargs有key值(字典)。11.是否了解Python中的单例模式。有哪几种实现?单例模式是一种常见的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。经过单例模式能够保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例
9、模式是最好的解决方案。单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创立这个实例;三是它必须自行向整个系统提供这个实例。在Python中,单例模式有以下几种实现方式。方法一、实现_new_方法,然后将类的一个实例绑定到类变量_instance上;如果cls._instance为None,则说明该类还没有被实例化过,new一个该类的实例,并返回;如果cls._instance不为None,直接返回_instance,代码如下:?12345678910111213141516171819classSingleton(object):def_new_(cls,*args,*kwarg
10、s):ifnothasattr(cls,_instance):orig=super(Singleton,cls)cls._instance=orig._new_(cls,*args,*kwargs)returncls._instanceclassMyClass(Singleton):a=1one=MyClass()two=MyClass()#one和two完全相同,能够用id(),=,is检测printid(one)#29097904printid(two)#29097904printone=two#Trueprintoneistwo#True方法二、本质上是方法一的升级版,使用_metacl
11、ass_(元类)的高级python用法,具体代码如下:?12345678910111213141516171819202122classSingleton2(type):def_init_(cls,name,bases,dict):super(Singleton2,cls)._init_(name,bases,dict)cls._instance=Nonedef_call_(cls,*args,*kwargs):ifcls._instanceisNone:cls._instance=super(Singleton2,cls)._call_(*args,*kwargs)returncls._in
12、stanceclassMyClass2(object):_metaclass_=Singleton2a=1one=MyClass2()two=MyClass2()printid(one)#31495472printid(two)#31495472printone=two#Trueprintoneistwo#True方法三、使用Python的装饰器(decorator)实现单例模式,这是一种更Pythonic的方法;单利类本身的代码不是单例的,通装饰器使其单例化,代码如下:?12345678910111213141516171819defsingleton(cls,*args,*kwargs):
13、instances=def_singleton():ifclsnotininstances:instancescls=cls(*args,*kwargs)returninstancesclsreturn_singletonsingletonclassMyClass3(object):a=1one=MyClass3()two=MyClass3()printid(one)#29660784printid(two)#29660784printone=two#Trueprintoneistwo#True12.是否了解Python垃圾回收机制?Python中的垃圾回收是以引用计数为主,标记-清除和分代收
14、集为辅。引用计数最大缺陷就是循环引用的问题,如果一个对象的引用数为0,Python虚拟机就会回收这个对象的内存。因此Python采用了辅助方法。13.是否了解read,readline和readlines三者的区别是什么?read读取整个文件readline读取下一行readlines读取整个文件到一个迭代器以供我们遍历(读取到一个list中,以供使用,比较方便)14.是否了解Post和Get的区别是什么?(Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE。URL全称是资源描述符,我们能够这样认为:一个URL地址,它用于描述一个网络上的资源
15、,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的查,改,增,删4个操作。)1.根据HTTP规范,GET用于信息获取,而且应该是安全的和幂等的。(1).所谓安全的意味着该操作用于获取信息而非修改信息。换句话说,GET请求一般不应产生副作用。就是说,它仅仅是获取资源信息,就像数据库查询一样,不会修改,增加数据,不会影响资源的状态。*注意:这里安全的含义仅仅是指是非修改信息。(2).幂等的意味着对同一URL的多个请求应该返回同样的结果2.根据HTTP规范,POST表示可能修改变服务器上的资源的请求。以新闻网站为例,读者对新闻发表自己的评论应该经过POST实现,因为在评论提交
16、后站点的资源已经不同了,或者说资源被修改了。上面大概说了一下HTTP规范中GET和POST的一些原理性的问题。但在实际的做的时候,很多人却没有按照HTTP规范去做,导致这个问题的原因有很多,比如说:1.很多人贪方便,更新资源时用了GET,因为用POST必须要到FORM(表单),这样会麻烦一点。2.对资源的增,删,改,查操作,其实都能够经过GET/POST完成,不需要用到PUT和DELETE。3.另外一个是,早期的WebMVC框架设计者们并没有有意识地将URL当作抽象的资源来看待和设计,因此导致一个比较严重的问题是传统的WebMVC框架基本上都只支持GET和POST两种HTTP方法,而不支持PU
17、T和DELETE方法。区别:(1.GET请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连,如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0%E5%A5%BD。如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其它字符,则直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。POST把提交的数据则放置在是HTTP包的包体中。2.GET方式提交的数据最多只能是1024字节
18、,理论上POST没有限制,可传较大量的数据)以上这句是我从其它文章转过来的,其实这样说是错误的,不准确的:(1).首先是GET方式提交的数据最多只能是1024字节,因为GET是经过URL提交数据,那么GET可提交的数据量就跟URL的长度有直接关系了。而实际上,URL不存在参数上限的问题,HTTP协议规范没有对URL长度进行限制。这个限制是特定的浏览器及服务器对它的限制。IE对URL长度的限制是2083字节(2K+35)。对于其它浏览器,如Netscape、FireFox等,理论上没有长度限制,其限制取决于操作系统的支持。注意这是限制是整个URL长度,而不但仅是你的参数值数据长度。见参考资料5(
19、2).理论上讲,POST是没有大小限制的,HTTP协议规范也没有进行大小限制,说“POST数据量存在80K/100K的大小限制”是不准确的,POST数据是没有限制的,起限制作用的是服务器的处理程序的处理能力。15.是否了解Cookie和Session的区别是什么?(1)cookie数据存放在客户的浏览器上,session数据放在服务器上(2)cookie不是很安全,别人能够分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session(3)session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用C
20、OOKIE(4)单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K。(5)因此:将登陆信息等重要信息存放为SESSION;其它信息如果需要保留,能够放在COOKIE中1,session在服务器端,cookie在客户端(浏览器)2,session默认被存在在服务器的一个文件里(不是内存)3,session的运行依赖sessionid,而sessionid是存在cookie中的,也就是说,如果浏览器禁用了cookie,同时session也会失效(可是能够经过其它方式实现,比如在url中传递session_id)4,session能够放在文件、数据库、或内存中都能
21、够。5,用户验证这种场合一般会用session因此,维持一个会话的核心就是客户端的唯一标识,即sessionid16.是否了解Python2.7.x与Python3.x的主要差异?使用_future_模块print函数IntegerdivisionUnicodexrangeRaisingexceptionsHandlingexceptionsnext()函数和.next()方法For循环变量和全局命名空间泄漏比较不可排序类型经过input()解析用户的输入返回可迭代对象,而不是列表17.Python的数据类型Python提供的基本数据类型主要有:布尔类型、整型、浮点型、字符串、列表、元组、集合
22、、字典等等。18.tuple和list的区别列表里的内容是能够改变的,增删改都能够,tuple则不行不可变的tuple意义就在于因为不可变,因此代码更安全。如果可能,能用tuple就尽量用tuple。19.Yield的用法带有yield的函数在Python中被称之为generator(生成器)。当这个函数在被调用的时候,这个函数在遇到yield的时候会停止运行,并返回一个迭代器。其具体功能是能够当return使用,从函数里返回一个值,不同之处是用yield返回之后,能够让函数从上回yield返回的地点继续执行。也就是说,yield返回函数,交给调用者一个返回值,然后再“瞬移”回去,让函数继续运
23、行,直到下一跳yield语句再返回一个新的值。20.IfIwanttodebugmypythonscripts,whichmoduleIshouldimport(C)(如果我想调试我的python脚本,我应该导入模块)A.pydebugB.debugC.pdbD.pydb21.Whichoneiscorrectforthefollowingscript.(C)(下列哪一个是正确的脚本)fruitlist=apple,mango,banana,orangeprintfruitlist1:3A.apple,mango,bananaB.mango,banana,orangeC.mango,banan
24、aD.apple,mango22.Whichoffollowingoptionsisnotpythondatatype?(A)(以下哪个选项不是python数据类型)A.charB.intC.floatD.list23.whatkingofdatathatcPickle.dumpstoreinfile?D(cpickle.dump存储在文件中的什么样的数据)A.ObjectB.StringC.ArrayD.Allofabove注:在python中,一般能够使用pickle类来进行python对象的序列化,而cPickle提供了一个更快速简单的接口,如python文档所说的:“cPickle-A
25、fasterpickle”。cPickle能够对任意一种类型的python对象进行序列化操作,比如list,dict,甚至是一个类的对象等。而所谓的序列化,我的粗浅的理解就是为了能够完整的保存并能够完全可逆的恢复24.whichoffollowingoptionsispythonmutabledatatype?(D)(下列选项哪一个是python的可变数据类型)A.intB.floatC.tupleD.list25.whichoffollowingoptionsisunabletocreatedict?(C)(以下哪个选项是无法创立dict类型) A.dict1=B.dict2=3:3C.di
26、ct3=1,2,3:uestc#TypeError:unhashabletype:listD.dict4=(1,2,3):usetc26.Howtointerpretthefollowingimplementationoftheresult?(B)(如何解释以下的实现结果吗)print1.2-1.0=0.2FalseA.TherealizationofPythonerror#Python的实现错误B.Floatcouldnotbeaccuratelyexpressed#浮点数不能准确表示C.Booleanoperationcannotbeusedforfloating-datatypecomp
27、ar#布尔运算不能用于浮点数据类型进行了D.Pythonwillbenon-zeronumberasFalse#Python将非零数字是错误的27.whatwouldthefollowingcodeyield?()(下面的代码会产生什么)word=abcdefghijprintword:3+word3:abcdefghij28.Createanewlistthatconvertsthefollowinglist(num_string)ofnumberstringtoalistofnumber?(创立一个新的列表,将列表(num_string)数的字符串列表的数字)Note:PleaseuseL
28、istComprehensionExpression(注意:请使用列表理解表示式)num_strings=1,21,53,84,50,66,7,38,9New_num=int(i)foriinnum_strings29.whatwillbetheoutputofthefollowing?(写出下面的输出)deffunc(x,*y,*z):Printzfunc(1,2,3)答:30.HowtoimportmethodAandBfrommoduleM.(如何从模块M导入方法A和B)fromMimportA,B31.Howtoprint“Thisprogramcanprinthelloworldon
29、screen.”(如何打印出“Thisprogramcanprinthelloworldonscreen.”)defprintHello():ThisprogramcanprinthelloworldonscreenPrint“helloworld”答:printHello._doc_32.建立一个用于下载文件的线程池,活动线程数为5.Download_urls=“”,“”,“”,33.有多少种设计模式,实现其中一个设计模式?设计模式共23种分三类设计模式主要分三个类型:创立型、结构型和行为型。其中创立型有:一、Singleton,单例模式:保证一个类只有一个实例,并提供一个访问它的全局访问点
30、二、AbstractFactory,抽象工厂:提供一个创立一系列相关或相互依赖对象的接口,而无须指定它们的具体类。三、FactoryMethod,工厂方法:定义一个用于创立对象的接口,让子类决定实例化哪一个类,FactoryMethod使一个类的实例化延迟到了子类。四、Builder,建造模式:将一个复杂对象的构建与她的表示相分离,使得同样的构建过程能够创立不同的表示。五、Prototype,原型模式:用原型实例指定创立对象的种类,而且经过拷贝这些原型来创立新的对象。行为型有:六、Iterator,迭代器模式:提供一个方法顺序访问一个聚合对象的各个元素,而又不需要暴露该对象的内部表示。七、Ob
31、server,观察者模式:定义对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知自动更新。八、TemplateMethod,模板方法:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,TemplateMethod使得子类能够不改变一个算法的结构即能够重定义该算法得某些特定步骤。九、Command,命令模式:将一个请求封装为一个对象,从而使你能够用不同的请求对客户进行参数化,对请求排队和记录请求日志,以及支持可撤销的操作。十、State,状态模式:允许对象在其内部状态改变时改变她的行为。对象看起来似乎改变了她的类。十一、Strategy,策略模式:定义一系列的算
32、法,把她们一个个封装起来,并使她们能够互相替换,本模式使得算法能够独立于使用它们的客户。十二、ChinaofResponsibility,职责链模式:使多个对象都有机会处理请求,从而避免请求的送发者和接收者之间的耦合关系十三、Mediator,中介者模式:用一个中介对象封装一些列的对象交互。十四、Visitor,访问者模式:表示一个作用于某对象结构中的各元素的操作,它使你能够在不改变各元素类的前提下定义作用于这个元素的新操作。十五、Interpreter,解释器模式:给定一个语言,定义她的文法的一个表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。十六、Memento,备忘录模式
33、:在不破坏对象的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。结构型有:十七、Composite,组合模式:将对象组合成树形结构以表示部分整体的关系,Composite使得用户对单个对象和组合对象的使用具有一致性。十八、Facade,外观模式:为子系统中的一组接口提供一致的界面,fa?ade提供了一高层接口,这个接口使得子系统更容易使用。十九、Proxy,代理模式:为其它对象提供一种代理以控制对这个对象的访问二十、Adapter,适配器模式:将一类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作那些类能够一起工作。二十一、Decrator
34、,装饰模式:动态地给一个对象增加一些额外的职责,就增加的功能来说,Decorator模式相比生成子类更加灵活。二十二、Bridge,桥模式:将抽象部分与它的实现部分相分离,使她们能够独立的变化。二十三、Flyweight,享元模式:使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。一般物件中的部分状态是能够分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。代理模式,Python实现:classInterface:defRequest(self):return0classRealSubje
35、ct(Interface):defRequest(self):printRealrequest.classProxy(Interface):defRequest(self):self.real=RealSubject()self.real.Request()if_name_=_main_:p=Proxy()p.Request()34.用匿名函数写一个功能?print(lambdax:x*x)(4)35.爬取淘宝的流程36.MySQL和mongodb的区别mongodb与mysql命令对比传统的关系数据库一般由数据库(database)、表(table)、记录(record)三个层次概念组成,M
36、ongoDB是由数据库(database)、集合(collection)、文档对象(document)三个层次组成。MongoDB对于关系型数据库里的表,可是集合中没有列、行和关系概念,这体现了模式自由的特点。37.分析日志的过程先考虑最简单的情况,在数据规模比较小的时候,可能是几十MB、几百MB或者几十GB,总之就是在单机处理尚能忍受的时候。一切都很好办,现成的各种Unix/Linux工具awk、grep、sort、join等都是日志分析的利器,如果仅仅是想知道某个页面的PV,一个wc+grep就能搞定。如果有稍复杂的逻辑,那就使用Python,配合正则表示式,基本就能够解决所有的问题。38
37、.爬虫的主要模块urlliburllib2BeautifulSouprequestsscrapy39.怎样验证URL是否存在URL不存在,可能时两种情况网页在服务器上不存在服务器不存在第一种异常发生时,爬虫程序(urllib模块)会返回HTTP错误,urlopen函数会抛出”HTTPError”异常使用异常处理try:Html=urlopen(URL)exceptHTTPErrorase:print(e)第二中情况urlopen会返回一个None对象,能够增加一个判断语句检测返回的html是不是NoneIfhtmlisNone:print(“URLisnotFound”)else:#程序继续4
38、0.什么是进程池和线程池这两个问题有一定的相似度,在面向对象程序编程中,对象的创立与析构都是一个较为复杂的过程,较费时间,因此为了提高程序的运行效率尽可能减少创立和销毁对象的次数,特别是一些很耗资源的对象创立和销毁。因此我们能够创立一个进程池(线程池),预先放一些进程(线程)进去,要用的时候就直接调用,用完之后再把进程归还给进程池,省下创立删除进程的时间,不过当然就需要额外的开销了利用线程池与进程池能够是管理进程与线程的工作交给系统管理,不需要程序员对立面的线程、进程进行管理41.解释负载均衡和集群网络的负载均衡是一种动态均衡技术,常见的实现方式是经过一些工具实时地分析数据包,掌握网络中的数据
39、流量状况,把任务合理均衡地分配出去。这种技术基于现有网络结构,提供了一种扩展服务器带宽和增加服务器吞吐量的廉价有效的方法,加强了网络数据处理能力,提高了网络的灵活性和可用性。日常生活中到处都能看到“负载均衡”,一个超市的收营员高峰期只能服务10位顾客,当做活动时有20位顾客需要服务的话可能就会排长队,这样购物体验将会很差(就像客户抱怨系统/网站访问太慢)。最简单的办法就是再招个营业员,重新开通一个出口。负载均衡的核心就是“分摊压力”。所谓集群是指一组独立的计算机系统构成的一个松耦合的多处理器系统,它们之间经过网络实现进程间的通信。应用程序能够经过网络共享内存进行消息传送,实现分布式计算机。通俗
40、一点来说,就是让若干台计算机联合起来工作(服务),能够是并行的,也能够是做备份。1、以下print将输出什么,为什么a = 1def fun(a): a = 2fun(a)print aa = def fun(a): a.append(1)fun(a)print a对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是能够修改的对象。第一个例子里函数把引用指向了一个不可变对象,当函数返回的时候,外面的引用没半毛感觉.而第二个例子就不一样了,函数内的引用指向
41、的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改.2、Python中单下划线和双下划线分别代表什么_init_:一种约定,Python内部的名字,用来区别其它用户自定义的命名,以防冲突._foo:一种约定,用来指定变量私有.程序员用来指定私有变量的一种方式._foo:这个有真正的意义:解析器用_classname_foo来代替这个名字,以区别和其它类相同的命名3、什么是闭包当一个内嵌函数引用其外部作作用域的变量,我们就会得到一个闭包. 总结一下,创立一个闭包必须满足以下几点:必须有一个内嵌函数内嵌函数必须引用外部函数中的变量外部函数的返回值必须是内嵌函数4、自己写一个闭包的实例
42、def lazy_sum(*args): def sum(): ax = 0 for n in args: ax = ax + n return ax return sum5、三次握手客户端经过向服务器端发送一个SYN来创立一个主动打开,作为三次握手的一部分。客户端把这段连接的序号设定为随机数 A。服务器端应当为一个合法的SYN回送一个SYN/ACK。ACK 的确认码应为 A+1,SYN/ACK 包本身又有一个随机序号 B。最后,客户端再发送一个ACK。当服务端受到这个ACK的时候,就完成了三路握手,并进入了连接创立状态。此时包序号被设定为收到的确认号 A+1,而响应则为 B+1。6、class Person: name=aaap1=Person()p2=Person()p1.name=bbbprint p1.nameprint p2.nameprint Person.namep1.name=bbb是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,p1.name一开始是指向的类变量name=aaa,可是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量,self.name不再引