python 后端开发面经

2019年秋招2020届。主要考虑python研发岗位和后端岗位。

因为许多原因放弃考研,我是半路九月底才开始准备的面试,花了一个月的时间,我个人不算优秀吧,在网络上就算个最差的,估计。

offer有了四五个,从9k-15k都有

都是杭州的公司,我是很喜欢去杭州的那种人

最高的15k还是一家搞电商平台给的,感觉自己不是很喜欢也不是很热门。

现在页找到了12k的,数据处理的一家公司搞python开发的在杭州。

我个人的技术就很多都是和python相关的,但是大二大三搞项目多些,那时候没注意培养自己的算法。

大小公司都有,毕竟技术栈深入的部分还是在项目开发,而不是在算法。所以工作很难找。

110道python面试真题:https://zhuanlan.zhihu.com/p/54430650

后端面试题总汇:https://github.com/yongxinz/back-end-inter...

python_developer:https://github.com/xiandong79/Python_Devel...

各个排序算法图解https://blog.csdn.net/qq_37941471/article/...

刷***面经

武汉森果_面试总结

  • 介绍一下自己,以及自己做过的项目?

  • django的组件是什么?https://www.cnblogs.com/chongdongxiaoyu/p/...第九题

    • django:内部组件
  • Admin组件,是对model中对应的数据表进行增删改查提供的组件

  • model组件:负责操作数据库

  • form组件:1.生成HTML代码2.数据有效性校验3校验信息返回并展示

  • ModelForm组件即用于数据库操作,也可用于用户请求的验证

  • django如何和数据库进行链接的?应该是orm!https://zhuanlan.zhihu.com/p/54430650第三十八题

    • ORM,全拼Object-Relation Mapping,意为对象-关系映射

      实现了数据模型与数据库的解耦,通过简单的配置就可以轻松更换数据库,而不需要修改代码只需要面向对象编程,orm操作本质上会根据对接的数据库引擎,翻译成对应的sql语句,所有使用Django开发的项目无需关心程序底层使用的是MySQL、Oracle、sqlite....,如果数据库迁移,只需要更换Django的数据库引擎即可

  • 三次握手/四次挥手?https://blog.csdn.net/whuslei/article/deta...

    • 三次握手:首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源。Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了。

    • 假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,"告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息"。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,"告诉Client端,好了,我这边数据发完了,准备好关闭连接了"。Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,"就知道可以断开连接了"。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!

    • 建立连接(三次握手):

      第一次:Client----------SYN------------->Server

      第二次:Server---------(ACK+SYN)------------------>Client

      第三次:Client-----------ACK------------------------>Server

      断开连接(四次挥手)

      第一次:Client--------------FIN--------------------->Server

      服务器读通道关闭

      第二次:Server-------------ACK--------------------->Client

      客户机写通道关闭

      第三次:Server-------------FIN---------------------->Client

      客户机读通道关闭

      第四次:Client--------------ACK--------------------->Server服务器写通道关闭

  • tcp?udp?http?ip属于哪些层?作用?https://blog.csdn.net/qq_22238021/article/...

    • 物理层:

      物理层的任务就是透明地传送比特流。物理层还要确定连接电缆插头的定义及连接法。

      数据链路层:数据链路层的任务是在两个相邻结点间的线路上无差错地传送以帧为单位的数据。每一帧包括数据和必要的控制信息。

      网络层:网络层的任务就是要选择合适的路由,使发送站的运输层所传下来的分组能够正确无误地按照地址找到目的站,并交付给目的站的运输层。

      运输层:运输层的任务是向上一层的进行通信的两个进程之间提供一个可靠的端到端服务,使它们看不见运输层以下的数据通信的细节。

      应用层:应用层直接为用户的应用进程提供服务。

    • TCP与UDP基本区别

      1.基于连接与无连接

      2.TCP要求系统资源较多,UDP较少;

      3.UDP程序结构较简单

      4.流模式(TCP)与数据报模式(UDP);

      5.TCP保证数据正确性,UDP可能丢包

      6.TCP保证数据顺序,UDP不保证

  • TCP具体是通过怎样的方式来保证数据的顺序化传输、可靠传输呢?

    • 保证顺序化:

      主机每次发送数据时,TCP就给每个数据包分配一个序列号并且在一个特定的时间内等待接收主机对分配的这个序列号进行确认,如果发送主机在一个特定时间内没有收到接收主机的确认,则发送主机会重传此数据包。接收主机利用序列号对接收的数据进行确认,以便检测对方发送的数据是否有丢失或者乱序等,接收主机一旦收到已经顺序化的数据,它就将这些数据按正确的顺序重组成数据流并传递到高层进行处理。

      (1)为了保证数据包的可靠传递,发送方必须把已发送的数据包保留在缓冲区;

      (2)并为每个已发送的数据包启动一个超时定时器;

      (3)如在定时器超时之前收到了对方发来的应答信息(可能是对本包的应答,也可以是对本包后续包的应答),则释放该数据包占用的缓冲区;

      (4)否则,重传该数据包,直到收到应答或重传次数超过规定的最大次数为止。

      (5)接收方收到数据包后,先进行CRC校验,如果正确则把数据交给上层协议,然后给发送方发送一个累计应答包,表明该数据已收到,如果接收方正好也有数据要发给发送方,应答包也可方在数据包中捎带过去。

    • TCP通过以下几种方式来提供可靠性:

      (1)、应用数据被分割为 TCP 认为最合适发送的数据块。这和 UDP

      完全不同,应用程序产生的数据报的长度将保持不变。(将数据截为合理的长度)

      (2)、当TCP发出一个段后,它启动一个定时器,等待目的端的确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。(超时重传)

      (3)、当TCP收到发自TCP连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒。(对于收到的请求,给出确认响应)(之所以推迟,可能是要对包做完整校验)

      (4)、TCP将保持它首部和数据的校验和。这是一个端到端的校验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段。(校验出包有错,丢弃报文段,不给出响应,TCP发送数据段,超时会重发数据)。

      (5)、既然 TCP 报文段作为 IP 数据报来传输,而 IP

      数据报的到达可能会失序,因此TCP报文段的到达可能也会失序。如果必要的话,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。(对失序数据进行重新排序,然后才交给应用层)。

      (6)、既然 IP 数据报会发生重复,TCP

      的接收端必须丢弃重复的数据(对于重复数据,能够丢弃重复数据)。

      (7)、TCP 能够提供流量控制。TCP

      连接的每一方都有固定大小的缓冲空间。TCP

      的接收端只允许另一端发送接收缓冲区所能接纳的数据。这将防止较快主机导致较慢主机的缓冲区溢出。(TCP

      可以进行流量控制,防止较快主机致使较慢主机缓冲区溢出)。TCP

      使用的流量控制协议是可变大小的滑动窗口协议。

      字节流服务:两个应用程序通过 TCP 连接交换 8 bit

      字节构成的字节流。TCP

      不再字节流中插入记录标识符。我们将这成为字节流服务。

      TCP对字节流的内容不作任何解释::

      TCP对字节流的内容不作任何解释。TCP不知道传输的数据字节流是二进制数据,还是ASCII字符、EBCDIC字符或者其他类型数据。对字节流的解释由TCP连接双方的应用层解释。

  • python中可变数据类型和不可变数据类型?https://zhuanlan.zhihu.com/p/54430650第二十一题

  • 不可变数据类型:数值型、字符串型string和元组tuple

  • 可变数据类型:列表list和字典dict;

如何让一个list变为空,很大的list?我回答的是将list的长度设为0,然后还要回答一个。

数据库类型有哪些?https://blog.csdn.net/op_zoro/article/deta...

  • 非关系数据库可以做什么?其中关系数据库不可以吗?为什么?非关系数据库和关系数据库的区别。https://blog.csdn.net/flyingshadower/artic...

    • 一、关系型数据库

      关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织

      优点:

      1、易于维护:都是使用表结构,格式一致;

      2、使用方便:SQL语言通用,可用于复杂查询;

      3、复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。

      缺点:

      1、读写性能比较差,尤其是海量数据的高效率读写;

      2、固定的表结构,灵活度稍欠;

      3、高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈。

      二、非关系型数据库

      非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。

      优点:

      1、格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。

      2、速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;

      3、高扩展性;

      4、成本低:nosql数据库部署简单,基本都是开源软件。

      缺点:

      1、不提供sql支持,学习和使用成本较高;

      2、无事务处理;

      3、数据结构相对复杂,复杂查询方面稍欠。

      非关系型数据库的分类和比较:

      1、文档型

      2、key-value型

      3、列式数据库

      4、图形数据库

  • 用过哪些python包?os、sys、numpy、markdown、math、datetime等等

字节跳动一面面经总结

  • 介绍一下自己,以及自己做过的项目?

  • 介绍一下django项目的整体架构、实现的过程、数据在上面传输的过程?

  • django你还了解多少?https://github.com/xiandong79/Python_Devel...

  • 输入url之后显示的网页的全过程?https://blog.csdn.net/qq_21993785/article/...

    • 域名服务器dns解析url:

    • 浏览器搜索自己的DNS缓存(维护一张域名与IP地址的对应表)

      若没有,则搜索操作系统中的DNS缓存(维护一张域名与IP地址的对应表)

      若没有,则搜索操作系统的hosts文件(Windows环境下,维护一张域名与IP地址的对应表,位置一般在

      C:WindowsSystem32driversetchosts)

      若没有,则操作系统将域名发送至 本地域名服务器-

      -(递归查询方式),本地域名服务器

      查询自己的DNS缓存,查找成功则返回结果,否则,(以下是迭代查询方式)

      4.1 本地域名服务器

      向根域名服务器(其虽然没有每个域名的具体信息,但存储了负责每个域,如com、net、org等的解析的顶级域名服务器的地址)发起请求,此处,根域名服务器返回com域的顶级域名服务器的地址

      4.2 本地域名服务器

      向com域的顶级域名服务器发起请求,返回baidu.com权限域名服务器(权限域名服务器,用来保存该区中的所有主机域名到IP地址的映射)地址

      4.3 本地域名服务器 向baidu.com权限域名服务器发起请求,得到www.baidu.com的IP地址

      本地域名服务器

      将得到的IP地址返回给操作系统,同时自己也将IP地址缓存起来

      操作系统将 IP 地址返回给浏览器,同时自己也将IP地址缓存起来

    • 三次握手

    • 建立tcp链接并发送http请求

    • 服务器收到请求并相应http请求

    • 1.负载均衡

      网站可能会有负载均衡设备来平均分配所有用户的请求。即对工作任务进行平衡,分

      摊到多个操作单元上执行,如图片服务器,应用服务器等。

      2请求处理阅读请求及它的参数和 cookies

    • 浏览器解析html代码并请求代码中的资源

    • 断开tcp链接,四次挥手

    • 浏览器对页面渲染呈现给用户

  • 输入url之后显示的网页的全过程?以及详细的如何实现的?-----我只回答了大概的概念,细致的问我我全不知道了。卒!

  • 域名解析的过程?

    • 如上
  • 三次握手/四次握手的过程?

  • 为什么要三次握手和四次挥手?

    • 通过第一次握手,B知道A能够发送数据。通过第二次握手,A知道B能发送数据。结合第一次握手和第二次握手,A知道B能接收数据。结合第三次握手,B知道A能够接收数据。

      至此,完成了握手过程,A知道B能收能发,B知道A能收能发,通信连接至此建立。三次连接是保证可靠的最小握手次数,再多次握手也不能提高通信成功的概率,反而浪费资源。

    • B收到确认信号,断开连接,而A在一段时间内没收到B的信号,表明B已经断开了,于是A也断开了连接。至此,完成挥手过程。

      可能有捧油会问,为什么2、3次挥手不能合在一次挥手中?那是因为此时A虽然不再发送数据了,但是还可以接收数据,B可能还有数据要发送给A,所以两次挥手不能合并为一次。

      挥手次数比握手多一次,是因为握手过程,通信只需要处理连接。而挥手过程,通信需要处理数据+连接。

  • 数据在tcp/udp网络上传输是如何实现可靠的?

    • 如上
  • 服务器上为什么要进行反向代理?不进行反向代理外面访问端口就不能访问了吗?

    • 不是的,首先。nginx反向代理可以降低上游服务器的负载

    • 一般来说公网延迟高,客户端与nginx之间的请求连接走公网,nginx先把这些请求缓存住,等这些请求数据全部完成之后nginx再向内网服务器请求,降低公网网络延迟成本,同时也降低一个连接占用服务端程序的时间。

      原因:因为tcp不一定一次就能把全部数据传输完毕,所以一个连接可能需要等待很久才能把所有需要的数据都传输完毕,而这样的空闲连接如果都直接连接到服务器上的话,会加重服务器负担,而nginx在这方面做了很大的优化,可以承载更多的连接,空闲连接也不会占据太多内存,所以nginx作为反向代理能降低上游服务器的负载。

  • get/post区别?

    • GET请求的数据会附在URL之后、GET方式提交的数据最多只能是1024字节",因为GET是通过URL提交数据,那么GET可提交的数据量就跟URL的长度有直接关系了。而实际上,URL不存在参数上限的问题,HTTP协议规范没有对URL长度进行限制。这个限制是特定的浏览器及服务器对它的限制。

    • 理论上讲,POST是没有大小限制的,HTTP协议规范也没有进行大小限制

      POST的安全性要比GET的安全性高。

    • 注意:这里所说的安全性和上面GET提到的“安全”不是同个概念。

    • 上面“安全”的含义仅仅是不作数据修改,而这里安全的含义是真正的Security的含义,比如:通过GET提交数据,用户名和密码将明文出现在URL上,因为(1)登录页面有可能被浏览器缓存,(2)其他人查看浏览器的历史纪录,那么别人就可以拿到你的账号和密码了,除此之外,使用GET提交数据还可能会造成Cross-site

      request forgery攻击。

    • get是向服务器发索取数据的一种请求,而Post是向服务器提交数据的一种请求,在FORM(表单)中,Method默认为"GET",实质上,GET和POST只是发送机制不同,并不是一个取一个发!

  • nginx作用?谁来做监听?

    • 反向代理

      正向代理:某些情况下,代理我们用户去访问服务器,需要用户手动的设置代理服务器的ip和端口号。

      反向代理:是用来代理服务器的,代理我们要访问的目标服务器。

      代理服务器接受请求,然后将请求转发给内部网络的服务器(集群化),

      并将从服务器上得到的结果返回给客户端,此时代理服务器对外就表现为一个服务器。

      Nginx在反向代理上,提供灵活的功能,可以根据不同的正则采用不同的转发策略,如图设置好后不同的请求就可以走不同的服务器。

    • 负载均衡

    • 负载均衡:多在高并发情况下需要使用。其原理就是将数据流量分摊到多个服务器执行,减轻每台服务器的压力,多台服务器(集群)共同完成工作任务,从而提高了数据的吞吐量。

    • Nginx可使用的负载均衡策略有:轮询(默认)、权重、ip_hash、url_hash(第三方)、fair(第三方)

    • 动静分离

      Nginx提供的动静分离是指把动态请求和静态请求分离开,合适的服务器处理相应的请求,使整个服务器系统的性能、效率更高。

      Nginx可以根据配置对不同的请求做不同转发,这是动态分离的基础。静态请求对应的静态资源可以直接放在Nginx上做缓冲,更好的做法是放在相应的缓冲服务器上。动态请求由相应的后端服务器处理。

  • nginx还了解多少?

  • 装饰器的作用?

    • 比如有一个函数func(a, b),它的功能是求a,b的差值,我现在有一个需求,就是想对函数功能再装饰下,求完差值后再取绝对值,但是不能在func函数内部实现,这时候就需要装饰器函数了,比如func decorate(func)函数,将func函数作为参数传递给decorate函数,由decorate来丰富func函数,丰富完成后再返回给func,此时func的功能就丰富了。
  • 进程和线程?两个的区别?

    • 进程:

      1、操作系统进行资源分配和调度的基本单位,多个进程之间相互独立

      2、稳定性好,如果一个进程崩溃,不影响其他进程,但是进程消耗资源大,开启的进程数量有限制

      线程:

      1、CPU进行资源分配和调度的基本单位,线程是进程的一部分,是比进程更小的能独立运行的基本单位,一个进程下的多个线程可以共享该进程的所有资源

      2、如果IO操作密集,则可以多线程运行效率高,缺点是如果一个线程崩溃,都会造成进程的崩溃

      应用:

      IO密集的用多线程,在用户输入,sleep

      时候,可以切换到其他线程执行,减少等待的时间

      CPU密集的用多进程,因为假如IO操作少,用多线程的话,因为线程共享一个全局解释器锁,当前运行的线程会霸占GIL,其他线程没有GIL,就不能充分利用多核CPU的优势

  • 同进程中的不同线程如何通信?

    • 进程间的通信方式

      • 管道( pipe

      ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。

      • 有名管道 (namedpipe) :

      有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。

      • 信号量(semophore ) :

      信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

      • 消息队列( messagequeue ) :

      消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

      • 信号 (sinal ) :

      信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

      • 共享内存(shared memory )

      :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的

      IPC

      方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。

      • 套接字(socket ) :

      套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。

    • 线程间的通信方式

      • 锁机制:包括互斥锁、条件变量、读写锁

        *互斥锁提供了以排他方式防止数据结构被并发修改的方法。

        *读写锁允许多个线程同时读共享数据,而对写操作是互斥的。

      *条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。

      • 信号量机制(Semaphore):包括无名线程信号量和命名线程信号量

      • 信号机制(Signal):类似进程间的信号处理

      线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。

  • 线程共享堆栈吗?

    • 同一个进程中的线程是共享数据段的,进程是操作系统分配资源的单位,

      而线程是操作系统真正调度的单位,创建线程时并不会对数据线程进行重新分配。

      线程有自己的threadID、栈和寄存器集合的值,这些在线程上下文切换时,操作系统都会做好相应的保存后才能切换,栈和寄存器的值以及程序计数器的值表明了当前线程的执行过程,对这些进行保存就能保存好执行的现场,以便下次返回时继续执行。

      线程共享的内容包括:

    • 1.进程代码段

    • 2.进程数据段

    • 3.进程打开的文件描述符、

    • 4.信号的处理器、

    • 5.进程的当前目录和

    • 6.进程用户ID与进程组ID

    • 7.堆

    • 线程独有的内容包括:

    • 1.线程ID

    • 2.寄存器组的值

    • 3.线程的栈

    • 4.错误返回码

    • 5.线程的信号屏蔽码

  • **手撕代码:实现一个装饰器缓存上次函数运行的结果缓存10s?(只实现了装饰器、缓存函数运行结果失败,当时有点紧张没想出来吧。)


import sys, re, time, hashlib, pickle

cache = {}

def is_obsolete(entry, duration):

    d = time.time()-entry['time']

    return d > duration

def compute_key(function, args, kwargs):

    key = pickle.dumps((function.__name__, args, kwargs))

    return hashlib.sha1(key).hexdigest()

def memoize(duration=10):

    def _memorize(function):

        def __memorize(*args, **kwargs):

            key = compute_key(function, args, kwargs)

            if key in cache :

                print ('have been on cache')

                # return cache[key]['value']

            else: 

                result = function(*args, **kwargs)

                cache[key] = {'value': result, 'time': time.time()}

                print('get in cache')

                return result

        return __memorize

    return _memorize

@memoize(10)

def testadd(a, b):

    # time.sleep(2)

    return a+b

def dec1(func):

    print("1111")

    def one():

        print("2222")

        func()

        print("3333")

    return one

def dec2(func):

    print("aaaa")

    def two():

        print("bbbb")

        print("test test")

        print("cccc")

    return two

# @dec1

@dec2

def test():

    print("test test")

test()
  • 手撕代码:实现数字反转包括复数,范围-2147483648 < x < 2147483647

class Solution(object):

    def reverse(self, x):

        if -10 < x < 10:

            return x

        str_x = str(x)

        if str_x[0] != "-":

            str_x = str_x[::-1]

            x = int(str_x)

        else:

            str_x = str_x[:0:-1]

            x = int(str_x)

            # x = -x

        return x if -2147483648 < x < 2147483647 else 0

def testtest():

    x = input("输入一个数组、以空格隔开 arr :")

    arr = list(map(int, x.split(" ")))

    n = input("输入一个整数 n:")

    n = int(n)

    res = [arr[i:i + n] for i in range(0, len(arr), n)]

    print(res)

# if __name__ == '__main__':

#     # s = Solution()

#     # reverse_int = s.reverse(-123)

#     # print(reverse_int)

杭州铕人/览众数据

重复题目不再写

  • **python垃圾回收https://zhuanlan.zhihu.com/p/54430650

    (91题)++https://blog.csdn.net/xiongchengluo1129/ar...**

  • 红黑树介绍:https://www.cnblogs.com/skywang12345/p/324...

  • 软件工程的单例模式/软件工程有哪些模式

    • 单例模式:单例模式是设计模式中最常用的一种模式。一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。

    • 举个例子,一个项目就相当于一个教室,你需要找到学生必须找班主任,班主任的设计就是这种对象,只能有一个,但是能访问到所有学生。而且班主任类,不能继承和重写,就只有一个

    • 软件工程有:单例模式,工厂模式

    • 工厂模式大致可以分为三类: 1、简单工厂模式 2、工厂方法模式

      3、抽象工厂模式。 这三种模式逐步抽象,并且更具有一般性。

      工厂模式有一种非常形象的描述,建立对象的类就像一个工厂,而需要被建立的对象就是一个个产品,在工厂中加工产品,使用产品的人不用关心产品是如何生产出来的。在软件中使用工厂模式的好处就是降低了模块之间的耦合。

      一、简单工厂模式:

      简单工厂模式是工厂模式中最简单的一种,他可以用比较简单的方式隐藏创建对象的细节,一般只需要告诉工厂类所需要的产品类型,工厂类就会返回需要的产品对象。

      二、工厂方法模式:

      由于简单工厂模式违反了开闭原则,所以工厂方法模式的出现了,工厂方法模式是在简单工厂模式的基础上,对”工厂”添加了一个抽象层,将工厂的动作抽象出来,作为抽象类,而具体的行为由工厂类的子类去实现,让工厂类的子类决定去生产什么类型的产品。

      三、抽象工厂模式:

      工厂方法模式和简单工厂模式都适用于”产品种类结构单一”的场合,为一类产品提供创建的接口。

  • django项目从访问到响应的整个过程https://www.cnblogs.com/shangjunnihao/p/11...

  • 手撕代码:括号匹配


class SStack(): #定义一个栈用来存放匹配的括号,因为括号匹配相当于一个栈 先进后出的过程

    def __init__(self):

        self.x = []

    def is_empty(self):

        return self.x == []

    def top(self):

        return self.x[-1]

    def push(self, elem):

        self.x.append(elem)

    def pop(self):

        return self.x.pop()  # 移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。

def check(text):

    all = "()[]{}"  # 定义所有括号

    left = "([{"  # 左括号

    dict0 = {")": "(", "]": "[", "}": "{"}  # 用字典存放匹配规则

    def test(text):  

        i, text_len = 0, len(text)  

        while True:

            while i < text_len and text[i] not in all:  

                i += 1

            if i >= text_len:  

                return

            yield text[i], i  # 在输入的文本中找到括号并yield一个 (括号,位置)的元组

            i += 1

    st = SStack()

    for text0, i in test(text):

        if text0 in left:  # 首先找到左括号

            st.push(text0)

        elif st.pop() != dict0[text0]:  # 如果是右括号,就栈顶元素进行匹配检查

            print("false")

            return False  # 遇到不匹配的,就直接退出函数,结束匹配

    print("true")  # 如果函数还能够执行到这里说明所有的括号都是匹配的

    return True

x = input("输入一个检查的内容:")

check(x)

这里我只记得了几个典型得公司,其他公司的内容离不开数据结构,计算机网络。基本上都是这些东西。

深一点的了解一下软件工程的用例方式。

还有许多涉及到的算法题我会一一上传,当时我只记下了我写的解答源码,具体题目还需要解析一哈,(我忘记了~~)

前前后后面了大概15-20个公司吧,基本的内容都离不开我在前面头部发的几个github链接。这里只是针对我个人经验总结了一下。

再其他公司除了许多算法题,很多都是现在在leetcode上见到过的。

很后悔当初第一二次就面试了字节头条,没准备好,也是瞎投的没抱希望 毕竟都10月了当时。

这里就不推荐什么的了,但是大家如果准备面试刷leetcode的话,跟着热题,分类题来刷吧!!(ง •_•)ง

本作品采用《CC 协议》,转载必须注明作者和本文链接
文章!!首发于我的博客Stray_Camel(^U^)ノ~YO
本帖由系统于 4年前 自动加精
讨论数量: 14

后续代码存在硬盘里,忘记放哪了,如果找到会第一时间更新在我的博客https://boywithacoin.cn/

4年前 评论

感觉本科面python还是挺少见的,岗位也不多,我们学校到大四才开了一门python的选修课,基本都是java/c/前端,而且大公司还是好的,可以春招再面一波,看你的项目经历之类的,简历写出来应该还是很有竞争力的。

4年前 评论
娃哈哈店长 (楼主) 4年前
娃哈哈店长 (楼主) 4年前
娃哈哈店长 (楼主) 4年前
娃哈哈店长 (楼主) 4年前
娃哈哈店长 (楼主) 4年前
巫乐 (作者) 4年前
娃哈哈店长 (楼主) 4年前
娃哈哈店长 (楼主) 4年前

你好楼主,本人对py真的喜欢,但是方向不知道如何找,目前已是实习阶段,大学没有认真学习。只是了解py的一些基础,想问如何找py相关工作以及当今py学习哪个方向比较有前景?

1年前 评论
娃哈哈店长 (楼主) 11个月前
娃哈哈店长 (楼主) 11个月前

老哥,我今年应届毕业生,正在找Python开发的工作,是不是要完蛋了。。。。

7个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!