精华内容
下载资源
问答
  • 演示将后端与前端集成在一起。 要求 python 3.6+和 使用npm的nodejs 安装 Python:将此项目扔到您的web2py应用程序文件夹中 Svelte :(从views/svelte文件夹中)运行npm install和npm run dev (用于开发,实时...
  • 原标题:一个初级python web后端开发工程师的面试总结 作者 AyoCross原文链接:https://blog.csdn.net/ayocross/article/details/56509840先介绍下我的情况:通信背景,工作一年多不到两年。之前一直在做C++的MFC...

    原标题:一个初级python web后端开发工程师的面试总结

    be1395d4c8a74aec8ab7d29d7a77aefa.jpeg

    作者 AyoCross

    原文链接:https://blog.csdn.net/ayocross/article/details/56509840

    先介绍下我的情况:通信背景,工作一年多不到两年。

    之前一直在做C++的MFC软件界面开发工作。公司为某不景气的国企研究所。(喏,我的工作经验很水:1是方向不对;2是行业有偏差)。

    然后目前是在寻找python后端开发这一块的工作,使用的框架为django;

    之前一直通过CSDN以及其他几家技术博客/论坛吸收大家的经验,在感激之余,也想输出点什么,造福大家,因此就有了这篇水文,希望大家能够多多吸取我的经验教训,早日找到一份自己满意的工作!

    面试的几家:北京的两家创业公司,规模均在40-50人之间;果壳(止步于电话面,拉钩投的);知乎(止步于电话面,论坛发帖后的内推);爱奇艺(拉钩上投的);杭州的网易(同学内推)。

    面试这一轮下来,最大的感受就一个:平时一定要坚持每天都码点代码。就算再烂的项目,也要坚持上传github。。真的,只要你能坚持一周有5天以上都能持续上传Git,半年下来,面试官绝对对你刮目相看。

    其他感受:不同的公司着重点都不一样,木桶原理,哪块都不能少。我就是因为平时只关注做自己的小博客系统,而没做其他的部分,导致爱奇艺倒在了手写代码上面…哎,忧伤。。平时多刷刷leetcode,看看剑指offer/面试金典,都是套路啊~~

    面试这几家公司所遇到的面试/笔试题,目前还能记住的如下。虽然可能绝大部分都是基础,但希望大家不要只是看看就过去了,最好还是假装你被问到这个问题,你来把答案说出来或写出来:(不按公司分了)

    Python语法以及其他基础部分

    1.手写快排;堆排;几种常用排序的算法复杂度是多少;快排平均复杂度多少,最坏情况如何优化;

    2.手写:已知一个长度n的无序列表,元素均是数字,要求把所有间隔为d的组合找出来,你写的解法算法复杂度多少;

    3.手写:一个列表A=[A1,A2,…,An],要求把列表中所有的组合情况打印出来;

    4.手写:用一行python写出1+2+3+…+10**8 ;

    5.手写python:用递归的方式判断字符串是否为回文;

    6.单向链表长度未知,如何判断其中是否有环;

    7.单向链表如何使用快速排序算法进行排序;

    8.手写:一个长度n的无序数字元素列表,如何求中位数,如何尽快的估算中位数,你的算法复杂度是多少;

    9.如何遍历一个内部未知的文件夹(两种树的优先遍历方式)

    网络基础部分

    1.TCP/IP分别在模型的哪一层;

    2.socket长连接是什么意思;

    3.select和epoll你了解么,区别在哪;

    4.TCP UDP区别;三次握手四次挥手讲一下;

    5.TIME_WAIT过多是因为什么;

    6.http一次连接的全过程:你来说下从用户发起request——到用户接收到response;

    7.http连接方式。get和post的区别,你还了解其他的方式么;

    8.restful你知道么;

    9.状态码你知道多少,比如200/403/404/504等等;

    数据库部分

    1.MySQL锁有几种;死锁是怎么产生的;

    2.为何,以及如何分区、分表;

    3.MySQL的char varchar text的区别;

    4.了解join么,有几种,有何区别,A LEFT JOIN B,查询的结果中,B没有的那部分是如何显示的(NULL);

    5.索引类型有几种,BTree索引和hash索引的区别(我没答上来这俩在磁盘结构上的区别);

    6.手写:如何对查询命令进行优化;

    7.NoSQL了解么,和关系数据库的区别;redis有几种常用存储类型;

    Linux部分

    1.讲一下你常用的Linux/git命令和作用;

    2.查看当前进程是用什么命令,除了文件相关的操作外,你平时还有什么操作命令;

    (因为我本人Linux本身就很水,只会基本的操作,所以这部分面试官也基本没怎么问。。反正问了就大眼瞪小眼呗)

    django项目部分

    1.都是让简单的介绍下你在公司的项目,不管是不是后端相关的,主要是要体现出你干了什么;

    2.你在项目中遇到最难的部分是什么,你是怎么解决的;

    3.你看过django的admin源码么;看过flask的源码么;你如何理解开源;

    4.MVC / MTV;

    5.缓存怎么用;

    6.中间件是干嘛的;

    7.CSRF是什么,django是如何避免的;XSS呢;

    8.如果你来设计login,简单的说一下思路;

    9.session和cookie的联系与区别;session为什么说是安全的;

    10.uWSGI和Nginx的作用;

    (我发现基本不问django实现细节相关的东西。。或者问也问的很少,哎,之前准备的方向完全错了)

    洋洋洒洒写了一个小时,发现还是有很多细节问题都已经忘了。。哎,自己的笔记做的还是不行。不过这些问题如果你能都答上来,起码我觉得你应该可以去试试面试初级web后端了,good luck!返回搜狐,查看更多

    责任编辑:

    展开全文
  • 详细后端开发知识讲解

    万次阅读 多人点赞 2018-05-15 16:13:07
    前言本片文章面向后端开发,讲述后端在进行开发时所使用的WEB服务器的工作流程,正所谓知根知底,WEB服务器是后端开发人员日常用于调试WEB程序和与前端通讯的一种方式!WEB服务器最为强大的地方是能够执行WEB程序,...

    一. 前言

    本片文章面向后端开发,讲述后端在进行开发时所使用的WEB服务器的工作流程,正所谓知根知底,WEB服务器是后端开发人员日常用于调试WEB程序和与前端通讯的一种方式!

    WEB服务器最为强大的地方是能够执行WEB程序,其WEB程序的编程语言并没有明确的规定,因为只要你所使用的服务器支持这样的程序就可以了!

    WEB服务器更像是一个平台,在此平台上编写软件我们称其为WEB编程,注:WEB编程下有许多规范比如CGI,FastCGI等等,这个是要看服务器的支持范围!

    不同服务器所使用的规范不同,比如JSP服务器只能运行由JAVA EE编写的WEB程序,不能用于运行像C/C++、Python等编程语言编写而成的WEB程序!

    通常情况下的WEB服务器所使用的编程规范均为CGI编程、只能运行CGI规范的程序,除了一些例外的WEB服务器,比如JSP服务器!

    二. CGI规范,WEB服务器执行过程

    什么是CGI规范?

    CGI是Common Gateway Interface的缩写,其意义为公用网关接口,意思可以理解为:在WEB服务器上运行一个程序或脚本,并且WEB服务器要将脚本执行结果返回给浏览器(客户端)!

    规范从何而谈?

    规范的意思是,无论你使用任何语言编写,都必须使用输出函数(cout,printf,print)输出HTML格式的数据信息,WEB服务器根据这些信息传递给浏览器,浏览器HTML树并将其显示到浏览器当中,即为一个WEB页面!

    更加深层次的来说其实,无论你使用什么语言编写,只要在WEB服务器中的配置文件中,使其支持CGI编程,然后将你编译完成的二进制可执行文件后缀名改为.cgi,最后前端页面在使用get或post方法请求这个WEB程序,WEB服务器会自动执行这个程序并将其结果送回给浏览器(TCP/IP协议)!

    实际执行是由操作系统来完成的,只是WEB服务器将程序中打印输出的字符信息给重定向到WEB服务器当中了,即WEB服务器在调用你的CGI程序时会使用一条操作系统都有的命令,重定向:

    >>

    printf或cout等打印函数的底层实现过程是将数据写入到显存中,根据要打印字符的位置并把位置写入到显存下,GPU会根据显存数据在屏幕点亮像素点中对应的二极管(RGB),一般字符字体都是由操作系统来完成的,因为字体的不同,笔画也就不同!printf会把要打印的字符数据转交给操作系统,在从用户态到内核态之间的转换,在到显存,且也要考虑编码的问题,因为不同的编码对应不同的数据,printf只会移交ASCII(最底层是没有字符这个概念的只有二进制码,而二进制码可以转换成ASCII码)码,操作系统需要根据当前程序使用的编码,并将ASCII码转换成当前编码要输出的字符,并且操作系统也要考虑屏幕分辨率,比较分辨率的不同像素点占用就不同!

    其当服务器在执行CGI程序时,也可以不用把程序后缀改为.CGI,你可以在配置文件中增加支持的扩展后缀名:.exe、.py、.c、.elff(ARM可执行文件/Linux可执行文件,Linux就是为ARM设计的)

    注意如果你配置成源文件的格式需要WEB服务器的支持,比如apache服务器,仅支持py文件,apache服务器会自动编译.py文件并执行!

    如果是在Linux或MAC系统下需要设置目录权限:

    chown -R 555 //所有访问权限

    如何接受从服务器传递来的信息?

    当我们前端页面向WEB服务器发送一个请求时(get/post)会有一个传参,里面包含着请求数据,比如:

    https://www.zzhblog.cn/c.cgi/?utm_source=csdnbar

    其意思为,请求www.zzhblog.cn服务器下的c.cgi程序,并向其传递一个参数,参数名为:utm_source,参数数据为:csdnbar

    也有这样的:

    https://www.zzhblog.cn/?utm_source=csdnbar

    没有请求的程序名,其实是WEB服务器后台给隐藏掉了,你可以在自己的WEB后台中配置默认文件,即输入网站地址而无需指定文件名,访问即返回默认文件!

    或者隐藏请求文件名,WEB服务器会把这些信息放到报文头了,浏览器接受到之后会自动隐藏!

    那么我们要怎样得到传递来的信息呢?这里就需要使用CGI提供的模块了,CGI提供了C/C++版的模块和Python等的模块,使用这些模块里的Get方法可以轻而易举的获取后台服务器传递过来的信息,然后在对这些数据进行处理,并把处理结果重定向给WEB服务器,最后WEB服务器将结构返回给浏览器,注意结果必须以HTML格式返回!

    整个执行过程都是经过HTTP协议格式规范来的!

    不过目前有的WEB服务器已经开发出自己的WEB服务器编程语言,也就是说该WEB服务器只能运行指定运行编译的程序,并且该语言下提供了很多较为方便的模块,可以调用直接读取一些相关数据,和处理数据的模块!

    关于C/C++方面的WEB程序开发

    C/C++编写WEB程序开发效率实在是非常之低,因为通常情况下我们做WEB服务器处理,一般都是对字符的解析,而C/C++传递过来的GET或POST数据是一个完整的URL和报文,需要C/C++自己去解析这些数据,不像其他编程语言已经为其解析完成,拿过来直接处理即可,而且C/C++对字符处理方面库支持本身就很差,需要开发人员手动编写字符处理库,所以这也是为什么大家不愿意使用C/C++做WEB服务器开发,因为要写很多代码,即使是由CGI模块的支持,但CGI模块只能用于获取WEB服务器传递过来的数据!

    再则,C/C++本身就是一个不是易学,且要考虑内存泄漏问题的一个编程语言,现在很多编程语言会自动帮你释放不用且丢失的内存,解决内存泄漏,也就是托管式代码平台,经典的有:.net

    C/C++WEB服务器开发效率与其他编程语言对比

    C/C++需要编写很多代码来完成某个任何,极其降低后端开发效率,但是也提高个人编程能力,现在很多编程语言都提供了很多模块,来完成某些任何,甚至可以说不是编程语言,是脚本,专门调用C/C++写的代码,比如Python!

    由于Python简单,模块多,可以简单调用模块处理许多复杂模块,所以很收后端开发人员的欢迎!

    有的时候没有CGI模块,WEB服务器在开发文档中会告诉你,参数会存放在哪儿,哪个临时文件中,或直接利用C/C++传参的方式传递:

    a.out aaa aaa

    a.out代码:

    int main(int x,int *a[]){
    }

    这是最经典的方式,x代表参数数量,a代表参数!

    a一般是个数组指针,指向每个参数!

    for(int i = 0;i < x;++i){
    printf("%s",*a[i]);
    }

    CGI与FastCGI

    CGI程序只能被请求一次,也就是说一次只能执行一个客户端发来的请求,假如说有一百个客户端同时请求这个程序,那么该程序要一个一个的执行!

    FastCGI就是CGI的升级版,该规范可以同时以多线程的方法来执行CGI程序,一百个客户端同时请求CGI程序时,服务器就会同时执行一百个CGI程序来处理这些客户端,可以在WEB服务器的配置文件中修改选择对应的CGI和FastCGI方法,WEB服务器会根据这些方法来做对应的规范!

    执行效率与算法

    在前端把数据传递到后端以后,后端要着手处理这个数据,就拿搜索引擎为例子:当我们在搜索引擎中输入相关数据时,要知道,在庞大的万维网平台中,网页资源几乎数不胜数,每天都会要上亿的新网页诞生。

    搜索引擎中有一个叫蜘蛛的模块,用于将这些数据爬下来,也就是网络爬虫,保存到服务器本地上,假设你的搜索引擎服务器中有数百亿条数据,并且网页路径和域名,网页名在数据库里存储好的,那么当用户在浏览器里输入某个关键字时,就会找到海量的相同数据,那么后端人员要做的是将这些数据以热度并排名按从大到小的方式出现在搜索页面的下拉框里,供用户挑选,那么此时就考虑到算法的要求了,倘若算法太复杂,那么后端执行个一两分钟才返回结果那么用户体验是不是就很差?

     

    三. HTTP协议规范

    这里不做详细介绍,因为博主之前有写过对HTTP/HTTPS协议规范的详细介绍,所以这里简明摘要!

    HTTPS之所以叫HTTPS是因为在使用TCP协议加密时通过SSL算法进行加密,HTTPS传输过程比HTTP要更加耗时!

    其次使用HTTPS握手过程需要证书验证,所以WEB服务器方也必须支持SSL协议!

    在浩荡的互联网中,就像开车一样,当我们开一辆货车运载资源时,难免会遇上堵车,那么此时就需要交通法则,来规定我们怎样传输,从而避免网络堵塞的情况,同时也要避免两辆车互相撞在一起导致数据丢失,发生丢包的状况,所以HTTP协议规范用语规定互联网中应该怎样传输数据,比如HTTP协议规范确定使用TCP协议来传递数据,防止因为网络拥堵或堵塞导致丢包的现象,实则上路线的选择是由猫(调制转换器)来决定的,猫会根据当前连接的线路状况来确定最优的传输路线,而TCP只是规定怎样来完成这次的传输,传输路线是由猫来完成的,以及收,收到之后猫会把数据发送给网卡,网卡解析数据在发送给上层,也就是形成了网络七层的概念!

    以上的APDU、PPDU即为封装,因为上层需要把自己的数据封装到一个包里,然后发给下层,下层在把这个数据拆开翻译意思,在根据意思添加自己的报文格式进去,即形成了APDU、PPDU包格式!

    假如我要向IP为1.0.0的地方发送一个A的字符,那么需要填写IP地址和数据段信息,然后发送给传输层,传输层在把这个数据拆开分析其意思,然后在进行格式转换,压缩,确定传输方式,在传送给下一层,这样做的方法是为了确保不同的数据结果格式上的歧义问题(表示层以后的层格式是统一的,所以需要表示层来统一格式),然后在到物理层在转换成BIT的电路信号方式确定最优路线发送到指定路由下,路由器接收到之后呢,在一步一步按照前面的步骤拆包,一步一步分析包,最终发送到电脑上的指定程序下!

    其实像应用服务器,是没有七层这么个概念的,实则上就三层,应用层选择好路径,数据和方法,表示层分析数据和方法,并对这些格式进行压缩,加密然后传递给传输层,传输层在拆开确定方法,修改报文格式,增加新的包头,直接发送给物理层,由猫直接发送出去,在TCP协议中无需经过HTTP协议,HTTP协议只在WWW开头的万维网域名下有效!

     

    相关连接:HTTP/HTTPS协议原理HTTP/HTTPS协议原理HTTP协议层开发

    展开全文
  • 后端开发框架

    万次阅读 2017-10-22 03:35:32
    Python目前主流的应用包括:Web开发、图形界面开发、系统网络运维、网络编程、科学数字计算、3D游戏开发等。 Python的web框架很多很多,百花齐放。 个人接触最多的是这四个大佬:Django、Flask、Tornado、Aiohttp...

    Python目前主流的应用包括:Web开发、系统网络运维、网络编程、科学数字计算、3D游戏开发等。

    Python的web框架比较多。个人接触最多的是这四个大佬:DjangoFlaskTornadoAiohttp,够用就行,以后就用这四个吧,性能需求小的直接用Django快速搞定。
    Tornado是最早接触的web框架,异步并发首选。Tornado不仅是web框架,还实现了http服务器。由于WSGI是同步模型,Tornado自己实现了一套异步处理,但同时也提供WSGI的接入,只是接入WSGI的部分一律不能使用异步。Tornado其实和一般的web框架不是一个级别的存在,甚至可以充当Nginx的角色,有时候也用来装载Django、Bottle之类的框架。但是据说不建议使用Tornado进行多台服务器的部署。
    然后发现其实Django能够满足大部分自己的需求,功能齐全、易上手。还有Flask也比较灵活。Aiohttp的话,最轻,基于asyncio,可以做出python里面性能极好的后端,但是需要自己写很多封装,封装成一个自己的web框架。
    此外,Bottle、webpy、gevent 等常常有所耳闻。其余的还有web2py、Quixote、Pyramid、Falcon、Muffin、Wheezy Web、Sanic等等,网上随便搜搜就能搜到很多python框架。
    一些对比:介绍两个Python web框架:Django & Tornado

    上面说的都是python框架,其实python用来写web并不是主流,毕竟Ruby和PHP拥有着更大的web生态圈,专注于写网站,Java和C++能写出真正高性能的大型网站。稍微了解下其他语言的web框架:
    Ruby:Rails等。
    PHP:如Laravel、Yii、Symfony、ThinkPHP、Codeigniter等。
    Javascript:Node.js。
    Java:最经典的是Spring系列(许多大型企业用Java)。
    C++:性能可能较好。(鹅厂专注于C++,当然也有历史原因)
    Go:新兴的高性能语言,并发能力较强。

    不过,写后端,本人暂时只用Python的几个常用框架 和 Java的Spring系列即可。

    附一个性能比较:thinkphp 与 tornado 性能测试比较
    个人还是很喜欢tornado的。

    附:python中的同步web与异步web
    同步处理一般基于WSGI。
    异步处理,python2时代主要有三个库:Twisted、Tornado 和 gevent。python3.4开始又出现asyncio的概念,aiohttp则是基于asyncio的http框架。之后又陆续出现了一批基于asyncio的HTTP框架,性能都不弱于Tornado。


    2019年更新:
    目前Go逐渐流行,可以尝试使用Go玩玩啦(当然,用Python做机器学习依然是不错的选择)。

    展开全文
  • python后端开发面试常见问题 (持续更新)

    万次阅读 多人点赞 2021-03-14 15:21:18
    python后端开发面试常见问题   大家好,我叫亓官劼(qí guān jié ),在GitHub和CSDN中记录学习的点滴历程,时光荏苒,未来可期,一起加油~~ 本篇文章将在GitHub和CSDN上持续更新,主要是Python后端开发的...

    python后端开发面试常见问题

      大家好,我叫亓官劼(qí guān jié ),在GitHub和CSDN中记录学习的点滴历程,时光荏苒,未来可期,一起加油~~

    本篇文章将在GitHub和CSDN上持续更新,主要是Python后端开发的一些常见问题,包括Python的一些基础知识,以及面试中常问的计网,数据库,数据结构等一些算法题,总体覆盖面试的大多数问题。

    本文的GitHub地址为:python-development-interview-FAQ

    CSDN地址为:python后端开发面试常见问题 (持续更新)

    如果有帮助的话,可以在GitHub上点个star,支持下。相对来说GitHub更新要比CSDN上更新更快一些。

    创建了个交流群,如果需要可以加群一起交流,Q群545611263(为了避免广告小号,设置了0.1的付费群),也可以加我V:qiguanjie2015


    Python 基础

    0 说明占位符

    • 本文中不特别标注Python版本的,全部默认为Python3

    1 Python类中的方法类型

    在Python类中有四种方法类型,分别是实例方法、静态方法、类方法和普通方法。

    • 实例方法(即对象方法):需要实例化对象之后才能调用,接受的第一个参数self就是对象本身,必须使用实例化对象才可以访问,不能通过类直接访问.
    • 静态方法:可以通过类名直接调用,不需要传递selfcls;也可以在实例化对象后调用
    • 类方法:可以通过类名调用,也可以在实例化对象后调用。类方法需要一个cls参数,在调用时自动传递
    • 普通方法:和正常的函数一样,可以直接调用,但是在类中不建议写这种方法

    测试示例:

    class A(object):
        # 实例方法(对象方法),需要接收一个形参self,即实例对象自己
        def instance_method_fun(self):
            print("instance_method_fun,self is {}".format(self))
        
        # 类方法,需要接收一个形参cls,在调用时自动传递
        @classmethod
        def classmethod_fun(cls):
            print("classmethod_fun, cls is {}".format(cls))
    
        # 静态方法
        @staticmethod
        def staticmethod_fun():
            print("staticmethod_fun")
    
        # 普通方法
        def common_fun():
            print("common_fun")
    
    # A.instance_method_fun() # 报错:TypeError: instance_method_fun() missing 1 required positional argument: 'self'
    A.classmethod_fun() # 输出:classmethod_fun, cls is <class '__main__.A'>
    A.staticmethod_fun() # 输出:staticmethod_fun
    A.common_fun() # 输出:common_fun  (不建议在类中写普通方法)
    
    
    a = A()
    a.instance_method_fun() # 输出:instance_method_fun,self is <__main__.A object at 0x0000018674E1E588>
    a.classmethod_fun()# 输出:classmethod_fun, cls is <class '__main__.A'>
    a.staticmethod_fun()# 输出:staticmethod_fun
    

    2 Python的参数传递类型

    Python中的参数传递是引用传递,即我们可以对传递对象的属性,但是不能改变传递对象的指针。在Python中有一些对象的值是不可以更改的,例如int,float类型。如果在函数体内修改了不可修改对象的值,Python会在一个新的内存地址上创建一个变量,而不是使用原来的变量;如果在函数体内修改一个可修改对象的值,则在原内存地址操作。

    例如:

    def fun1(x):
        x = x + 1
        print("x:{},id(x):{}".format(x,id(x)))
    
    def fun2(x):
        print("b:{},id(b):{}".format(b,id(b)))
        x.append(2)
        print("b:{},id(b):{}".format(b,id(b)))
    
    a = 1
    print("a:{},id(a):{}".format(a,id(a)))
    fun1(a)
    print("a:{},id(a):{}".format(a,id(a)))
    
    b = []
    print("b:{},id(b):{}".format(b,id(b)))
    fun2(b)
    print("b:{},id(b):{}".format(b,id(b)))
    
    # 输出为:
    # a:1,id(a):1860272240
    # x:2,id(x):1860272272
    # a:1,id(a):1860272240
    # b:[],id(b):2262818473288
    # b:[],id(b):2262818473288
    # b:[2],id(b):2262818473288
    # b:[2],id(b):2262818473288
    

    3 协程

    这个是在前不久的面试中才知道有协程这个概念,其实也可以理解为用户线程,相比较内核线程而言,用户线程更加的灵活,并且减少了进出内核态的消耗,缺点是无法利用多核CPU的并行优势。

    4 Python命名中的单下划线(_)和双下划线(__)

    在Python中,双下划线开头和结尾的命名默认为Python的内部变量/方法,用以区分用户变量。例如场景的__init__(),__dict__,__dir__等。

    单下划线开头的命名默认为私有变量,不会在from a import *中被导入

    双下划线开头,但是没有下划线结尾的命名,Python在解释的时候会默认对其进行重命名为_类名__变量

    class A():
        def __init__(self) -> None:
            self._b = "self._b"
            self.__c = "self.__c"
    a = A()
    print(a._b) # 输出:self._b
    # print(a.__c) # 报错:AttributeError: 'A' object has no attribute '__c'
    print(a.__dict__) # 输出:{'_b': 'self._b', '_A__c': 'self.__c'}
    # 我们发现__c变量被自动重命名为_A__c了
    print(a._A__c) # 输出:self.__c
    

    在Python中,当一个文件夹下有一个__init__.py文件,则Python会识别这个文件夹为一个Python包

    5 python字符串传参 %s和format

    %s和format的区别在于,format可以传递列表、元组等类型,而%s不可以传递元组类型(%s可以传递列表类型),所以在日常使用时,使用format更加方便

    6 python 迭代器和生成器

    迭代器是python十分强大的一个功能,迭代器是一个可以记住遍历位置的对象。例如:

    a = [1,2,3,4]
    it = iter(a) # 获取一个迭代器对象
    print(next(it)) # 遍历下一个位置,输出:1
    print(next(it)) # 遍历下一个位置,输出:2
    

    我们也可以使用迭代器来生成一个我们需要的列表,例如:

    a = [i*i for i in range(1,9)] # 使用迭代器生成一个[1,9)的平方的列表
    print(a) # 输出:[1, 4, 9, 16, 25, 36, 49, 64]
    

    在这里如果我们将外面的[]改为(),a获取的将会是一个生成器,而不是迭代器。在python中,使用yield的函数被称为生成器,生成器返回的是一个迭代器的函数,只能用于迭代操作,在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。

    生成器不保留所有的数据信息,而是指记录当前运行的信息。因此生成器就不能直接获取某个下表的值,而是要通过next()或者sent(),亦或是迭代器来依次获取值。

    例如:

    a = (i*i for i in range(1,9)) # 使用生成器生成一个[1,9)的平方的列表
    print(a) # 输出:[1, 4, 9, 16, 25, 36, 49, 64]
    # print(a[2]) # 报错TypeError: 'generator' object is not subscriptable
    it = iter(a) # 获取一个迭代器对象
    print(next(a)) # 输出 1
    print(next(a)) # 输出 4
    print(next(a)) # 输出 9
    print(next(a)) # 输出 16
    print("=================")
    for item in a:
        print(item)
    # 输出:
    # 25
    # 36
    # 49
    # 64
    

    生成器常用场景:例如我们需要生成一个有规律向前推进的列表,或者一个从1到1亿的列表等等,当我们列表中元素数量十分大时,内存会爆栈。但是如何我们元素间是有规律的,则我们可以利用生成器来解决这个问题。

    有需要的话可以参考这篇文章:学点简单的Python之Python生成器

    7 python 装饰器

    装饰器是一个十分常用的东西,经常被用在有切面需求的场景,大家耳熟能详的AOP就是这个,装饰器的主要功能就是为已经存在的函数提供一些可复用的定制化功能。

    装饰器包含很多内容,需要系统的去看,这里不展开。如有需要,可以参考这篇文章:学点简单的Python之Python装饰器与闭包

    8 python 变量中的作用域

    python中变量总是默认本地变量,如果没有,则会创建一个本地变量。在函数中如果要使用全局变量,需要使用gloabl进行声明。例如:

    a = 5
    def fun():
        global a
        a = a + 1
    fun()
    print(a)# 输出:6
    

    9 python 闭包

    python闭包与其他语言的闭包的意思是一样的,即我们在函数定义中引用了函数外定义的变量,并且该函数可以在其定义环境外被执行。简单来说,就是在函数内定义函数,且函数内部定义的函数中使用了外部函数中的变量,且内部函数可以单独的运行。

    这里用语言来描述还是比较的绕,我们可以通过下面这个小例子来更直观的理解:

    # 定义一个函数extern_func
    def extern_func():
        # 在extern_func函数内定义一个空列表list
        list = []
        # 在extern_func函数内定义一个函数inner_func
        def inner_func(name):
            # inner_func函数的功能是在list列表中添加一个name,然后输出list
            list.append(name)
            print(list)
        # exten_func函数的返回值是inner_func的函数体
        return inner_func
    
    # 调用extern_func函数,返回值赋值给ret1,即ret1为inner_func函数体
    ret1 = extern_func()
    ret1('zhangsan')# 调用ret1,在list中添加一个'zhangsan',并输出list
    ret1('lisi')# 调用ret1,在list中添加一个'lisi',并输出list
    
    # 调用extern_func函数,返回值赋值给ret2,即ret2为inner_func函数体
    ret2 = extern_func()
    ret2('wangwu')# 调用ret2,在list中添加一个'wangwu',并输出list
    
    ret1('qiguanjie')# 调用ret1,在list中添加一个'lisi',并输出list
    

    输出为:

    ['zhangsan']
    ['zhangsan', 'lisi']
    ['wangwu']
    ['zhangsan', 'lisi', 'qiguanjie']
    

    我们发现ret1ret2中虽然都是在list中添加一个name并返回,但是ret1ret2是两次调用extern_func( )返回的函数体,他们作用的list是不同的,他们作用的list可以脱离原函数extern_func()而单独使用。这就是函数闭包的简单使用。简而言之就是我们在函数中定义函数,并且使用了外部函数中的部分变量,我们内部的函数在脱离外部函数之后继续执行,且单独作用于外部函数的部分变量。

    闭包一个常见错误:

    我们看下面这个例子

    def func():
        list = []
        for i in range(3):
            def inner_func():
                return i*i
            list.append(inner_func)
        return list
    re1,re2,re3= func()
    print(re1())
    print(re2())
    print(re3())
    

    大家是不是以为三个输出的结果应该是0,1,4?但实际上输出的结果都是4,这是为什么呢?这里我们的i对于inner_func来说是一个外部函数,我们在list中添加是是inner_func的函数体,里面返回的是i*i,但是当我们i变化到2之后,我们才返回list,所以我们输出的三个值才都是4,那如何避免这种情况呢?

    第一种方法,区分变量

    我们使用_i来区分i

    def func():
        list = []
        for i in range(3):
            def inner_func(_i = i):
                return _i*_i
            list.append(inner_func)
        return list
    re1,re2,re3= func()
    print(re1())
    print(re2())
    print(re3())
    

    这里我们在inner_func的参数中定义_i变量,值为当前的i,这时我们将函数体加入list中,就可以保证值不受i值变化的影响,输出为0,1,4。另一种方法就是我们直接在list中存放计算好的值,而不是函数体(这种方法有一定的局限性,和之前的方法就是两种完全不同的方法了):

    def func():
        list = []
        for i in range(3):
            def inner_func():
                return i*i
            list.append(inner_func())
        return list
    re1,re2,re3= func()
    print(re1())
    print(re2())
    print(re3())
    123456789101112
    

    这里我们这里添加到list中的是inner_func(),一旦有()则表明我们这个函数已经运行了,返回的是一个值。

    第二种方法 nonlocal关键字

    那如果我们要在内部函数中使用外部函数中的变量,并进行修改我们应该如何做呢?

    def extern_func(name):
        print('exter_func name is : %s' % name)
        def inner_func():
            name = 'inner_func ' + name
            print('inner_func name is : %s' % name)
        return inner_func
    
    ret = extern_func('qiguanjie')()
    

    如何我们直接修改的话,我们会发现这里编译会报错:UnboundLocalError: local variable 'name' referenced before assignment

    这里报错的意思即我们这里的name变量在使用前未被分配,这就和我们在函数内使用全局变量时要使用globle关键字一样,这里在内部函数中要使用并更改外部函数中的变量,我们需要使用关键字nonlocal,对程序进行修改:

    def extern_func(name):
        print('exter_func name is : %s' % name)
        def inner_func():
            nonlocal name
            name = 'inner_func ' + name
            print('inner_func name is : %s' % name)
        return inner_func
    
    ret = extern_func('qiguanjie')()
    

    此时程序顺利编译,输出结果为:

    exter_func name is : qiguanjie
    inner_func name is : inner_func qiguanjie
    

    10 python lambda函数

    lambda函数即匿名函数,在很多场合都可以使用。lambda 函数比较轻便,即用即仍,很适合需要完成一项功能,但是此功能只在此一处使用,连名字都很随意的情况下。

    例如在sort函数中指定排序的key:

    a = [{"a":13,"b":25,"c":62},{"a":63,"b":215,"c":612},{"a":3,"b":634,"c":216}]
    a.sort(key=lambda x: x['a'])
    print(a) # 输出: [{'a': 3, 'b': 634, 'c': 216}, {'a': 13, 'b': 25, 'c': 62}, {'a': 63, 'b': 215, 'c': 612}]
    a.sort(key=lambda x: x['b'])
    print(a) # 输出: [{'a': 13, 'b': 25, 'c': 62}, {'a': 63, 'b': 215, 'c': 612}, {'a': 3, 'b': 634, 'c': 216}]
    a.sort(key=lambda x: x['c'])
    print(a) # 输出: [{'a': 13, 'b': 25, 'c': 62}, {'a': 3, 'b': 634, 'c': 216}, {'a': 63, 'b': 215, 'c': 612}]
    
    

    11 python中的深拷贝与浅拷贝

    在浅拷贝时,拷贝出来的新对象的地址和原对象是不一样的,但是新对象里面的可变元素(如列表)的地址和原对象里的可变元素的地址是相同的,也就是说浅拷贝它拷贝的是浅层次的数据结构(不可变元素),对象里的可变元素作为深层次的数据结构并没有被拷贝到新地址里面去,而是和原对象里的可变元素指向同一个地址,所以在新对象或原对象里对这个可变元素做修改时,两个对象是同时改变的,但是深拷贝不会这样,这个是浅拷贝相对于深拷贝最根本的区别。

    在深拷贝时,会只拷贝所有元素的值,包括可变对象,也仅拷贝对象中的值,而不是地址。

    import copy
    a = [1,2,3,4,['a','b','c']]
    b = a # 赋值(引用传递)
    c = copy.copy(a)# 浅拷贝
    d = copy.deepcopy(a) # 深拷贝
    
    a.append(5)
    a[4].append('d')
    print("a:{},  id(a):{}, id(a[4]):{}".format(a,id(a),id(a[4])))
    print("b:{},  id(b):{}, id(b[4]):{}".format(b,id(b),id(b[4])))
    print("c:{},     id(c):{}, id(c[4]):{}".format(c,id(c),id(c[4])))
    print("d:{},          id(d):{}, id(d[4]):{}".format(d,id(d),id(d[4])))
    
    # 输出为:
    # a:[1, 2, 3, 4, ['a', 'b', 'c', 'd'], 5],  id(a):1998224934024, id(a[4]):1998224933896
    # b:[1, 2, 3, 4, ['a', 'b', 'c', 'd'], 5],  id(b):1998224934024, id(b[4]):1998224933896
    # c:[1, 2, 3, 4, ['a', 'b', 'c', 'd']],     id(c):1998224936904, id(c[4]):1998224933896
    # d:[1, 2, 3, 4, ['a', 'b', 'c']],          id(d):1998224935752, id(d[4]):1998224957960
    

    12 Python中*args和**kwargs

    *args表示传一个元组给函数,可以同时传递多个参数,这里的args可以替换为其他名称,前面加一个*即可,例如:*para都可以。

    **kwargs表示传一个字典给函数,可以传多个键值对,这里的kwargs同样也可以替换为其他名称,前面有**即可。

    两者的不同如下所示:

    def fun(*args,**kwargs):
      print("args: ",args)
      print("kwargs: ",kwargs)
    
    fun("hello","world","!","this","is","args",a=1,b=2,c=3)
    
    # 输出为:
    # args:  ('hello', 'world', '!', 'this', 'is', 'args')
    # kwargs:  {'a': 1, 'b': 2, 'c': 3}
    

    13 Python中__new____init__的区别

    __new__是静态方法,会返回一个创建的实例

    __init__是实例方法,无返回值

    14 Python中的单例模式

    单例模式是一种特别重要的设计模式,通过单例模式可以保证系统中一个类只有一个实例并且该实例易于被外界访问,方便控制实例个数并节约系统资源。实现单例模式的常用方法如下:

    1 通过import导入

    在Python中使用import来导入一个对象,则是天然的单例模式。因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。例如:

    # a.py中
    class A(object):
        def fun(self):
            pass
    test_a = A
    
    # b.py中
    from a import test_a
    

    2 使用装饰器

    def Singleton(cls):
        _state = {}
        def _singleton(*args, **kargs):
            if cls not in _state:
                _state[cls] = cls(*args, **kargs)
            return _state[cls]
        return _singleton
    
    
    @Singleton
    class A(object):
        a = 1
        def __init__(self, x=0):
            self.x = x
    
    a1 = A()
    a2 = A()
    
    print("id(a1): ",id(a1))
    print("id(a2): ",id(a2))
    
    print("a1.a: ",a1.a)
    print("a2.a: ",a2.a)
    
    a1.a = 2
    print("a1.a: ",a1.a)
    a2.a = 3
    print("a2.a: ",a2.a)
    
    print("a1.a: ",a1.a)
    
    # 输出为:
    # id(a1):  2973113231736
    # id(a2):  2973113231736
    # a1.a:  1
    # a2.a:  1
    # a1.a:  2
    # a2.a:  3
    # a1.a:  3
    

    3 使用类实现

    使用类实现的时候需要加锁,否则在多线程中无法保证单实例

    import time
    import threading
    class Singleton(object):
        _instance_lock = threading.Lock()
    
        def __init__(self):
            time.sleep(1)
    
        @classmethod
        def instance(cls, *args, **kwargs):
            with Singleton._instance_lock:
                if not hasattr(Singleton, "_instance"):
                    Singleton._instance = Singleton(*args, **kwargs)
            return Singleton._instance
    
    
    def task(arg):
        obj = Singleton.instance()
        print(obj)
    for i in range(10):
        t = threading.Thread(target=task,args=[i,])
        t.start()
    time.sleep(20)
    obj = Singleton.instance()
    print(obj)
    
    # 输出:
    # <__main__.Singleton object at 0x0000022E7C561E80>
    # <__main__.Singleton object at 0x0000022E7C561E80>
    # <__main__.Singleton object at 0x0000022E7C561E80>
    # <__main__.Singleton object at 0x0000022E7C561E80>
    # <__main__.Singleton object at 0x0000022E7C561E80>
    # <__main__.Singleton object at 0x0000022E7C561E80>
    # <__main__.Singleton object at 0x0000022E7C561E80>
    # <__main__.Singleton object at 0x0000022E7C561E80>
    # <__main__.Singleton object at 0x0000022E7C561E80>
    # <__main__.Singleton object at 0x0000022E7C561E80>
    

    4 基于__new__方法实现

    当我们实例化一个对象时,是先执行了类的__new__方法(我们没写时,默认调用object.new),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所有我们可以基于这个,实现单例模式

    import threading
    class Singleton(object):
        _instance_lock = threading.Lock()
    
        def __init__(self):
            pass
    
        def __new__(cls, *args, **kwargs):
            if not hasattr(Singleton, "_instance"):
                with Singleton._instance_lock:
                    if not hasattr(Singleton, "_instance"):
                        Singleton._instance = object.__new__(cls)  
            return Singleton._instance
    
    obj1 = Singleton()
    obj2 = Singleton()
    print(obj1)
    print(obj2)
    
    def task(arg):
        obj = Singleton()
        print(obj)
    
    for i in range(10):
        t = threading.Thread(target=task,args=[i,])
        t.start()
    
    # 输出
    # <__main__.Singleton object at 0x0000017B102EA978>
    # <__main__.Singleton object at 0x0000017B102EA978>
    # <__main__.Singleton object at 0x0000017B102EA978>
    # <__main__.Singleton object at 0x0000017B102EA978>
    # <__main__.Singleton object at 0x0000017B102EA978>
    # <__main__.Singleton object at 0x0000017B102EA978>
    # <__main__.Singleton object at 0x0000017B102EA978>
    # <__main__.Singleton object at 0x0000017B102EA978>
    # <__main__.Singleton object at 0x0000017B102EA978>
    # <__main__.Singleton object at 0x0000017B102EA978>
    # <__main__.Singleton object at 0x0000017B102EA978>
    # <__main__.Singleton object at 0x0000017B102EA978>
    

    15 Python中is==的区别

    is是对指针的比较,==是对值的比较。

    a = [1,2,3,4]
    b = [1,2,3,4]
    print(a is b) # 输出 False
    print(a == b) # 输出 True
    

    16 Python3 和Python2的区别

    • Python2的print不用加()而python3需要
    • python2的/表示整除(不加.0的时候),而Python3是除
    • Python3的A / B的返回值类型都是float,而Python2可能是整型
    • python2默认编码是ascii,python3的默认编码是utf-8
    • python3新增了nonlocal关键字,用于实现非局部变量

    等等,这里例举的几个是常见的价格区别。

    17 Python中a += X和a = a + x的区别

    在Python中,a += X和a = a + x的实现机制是不同的,这里分为四种情况。

    • 可变类型
      • a += x:将会在a原地址上进行修改,a的地址不变
      • a = a + x:将会新创建一个对象,名称为a,但是地址与原来的地址不同。
    • 不可变类型
      • a += x:将会新创建一个对象,名称为a,但是地址与原来的地址不同。
      • a = a + x:将会新创建一个对象,名称为a,但是地址与原来的地址不同。

    程序示例:

    a = [1,2,3]
    print("a原地址为:{}".format(id(a)))
    a += [4,5]
    print("进行a += [4,5]操作后的a地址为:{}".format(id(a)))
    a =a + [4,5]
    print("进行a =a + [4,5]操作后的a地址为:{}".format(id(a)))
    
    a = 1
    print("a原地址为:{}".format(id(a)))
    a += 2
    print("进行a += 2操作后的a地址为:{}".format(id(a)))
    a =a + 2
    print("进行a =a + 2操作后的a地址为:{}".format(id(a)))
    

    输出为:

    a原地址为:140591562829000
    进行a += [4,5]操作后的a地址为:140591562829000
    进行a =a + [4,5]操作后的a地址为:140591562984456
    a原地址为:4391820368
    进行a += 2操作后的a地址为:4391820432
    进行a =a + 2操作后的a地址为:4391820496
    

      大家好,我是亓官劼(qí guān jié ),在【亓官劼】公众号、CSDN、GitHub、B站、华为开发者论坛等平台分享一些技术博文,主要包括前端开发、python后端开发、小程序开发、数据结构与算法、docker、Linux常用运维、NLP等相关技术博文,时光荏苒,未来可期,加油~
      如果喜欢博主的文章可以关注博主的个人公众号【亓官劼】(qí guān jié),里面的文章更全更新更快。如果有需要找博主的话可以在公众号后台留言,我会尽快回复消息,其他平台私信回复较慢。
    在这里插入图片描述

    由于学习工作的需要,算法刷题将会逐渐由C++向Python3过度,正在过度中,如实现的不太优美,请见谅。

    本文原创为【亓官劼】(qí guān jié ),请大家支持原创,部分平台一直在恶意盗取博主的文章!!! 全部文章请关注微信公众号【亓官劼】。

    展开全文
  • Python web后端: Django后端开发数据库修改 Django的数据库开发,主要依赖于ORM框架,支持多种数据库,如mysql、sqllite等。 修改数据库分为两个步骤; 1、根据编写的model文件生成可迁移文件0001_initial.py,生成的...
  • 移动和后端开发。 打开CMD或终端,然后运行以下命令。 1套FLASK_APP = main.py 2瓶运行-h your_IPv4_address ->示例:烧瓶运行-h 192.168.1.50 ->注意:对于IPv4地址,请在cmd上输入以下命令:Windows上的ipconfig...
  • 后端开发 (1)

    2017-10-11 10:34:30
    后端开发 HTTP (HyperText Transfer Protocol) Python 系常见 Web 框架 Django 大而全,内部耦合比较紧凑,插件丰富,适合快速开发 Flask 精而简,便于二次开发和扩展开发,生态环境好,插件丰富 Tornado 异步...
  • Python后端开发要求

    2017-08-07 15:44:00
    关于Python后端开发要求 一.对Python有兴趣,熟悉Python(标准库) 最好阅读过源码 了解Python的优化(熟悉pypy更佳) 二.至少至少一门语言(不说“精通”) 起码熟悉其他基本语言 C/C++ Lisp Haskell Scheme ...
  • 后端开发 后端的开发比前端的开发要简单很多,因为开发者只需专注于数据的呈现即可,不必关心显示的逻辑。在众多后端框架中,我选择了开发和学习成本较低的Python语言中的Django框架,同时Python语言与我们的判题...
  • 后端开发入门实战

    千次阅读 2018-07-03 21:18:04
    后端入门实战Flask+Mysql python2.7+flask2.0+pymysql Flask项目结构 系统服务端开发仓库结构 Appserver/ ├── app │ ├── static/ # 静态资源文件夹 │ ├── templates/ # 模板文件夹 │ ├── __init_...
  • app后端开发学Python。Python的优点:1、简单易学Python 编程语言最大的优点之一,是其具有伪代码的特质,它可以让我们在开发 Python 程序时,专注于解决问题,而不是搞明白语言本身。2、开源Python 是 FLOSS(自由/...
  • 自定义User模型:继承自django内置user系统使用shortuuid作为主键model.py文件待解决后端开发准备工作 配置数据库配置模板文件的路径配置时区配置模板的static过滤器配置数据库 DATABASES={'default':{...
  • 一个初级python web后端开发工程师的面试总结

    万次阅读 多人点赞 2017-02-22 22:23:18
    然后目前是在寻找python后端开发这一块的工作,使用的框架为django;之前一直通过CSDN以及其他几家技术博客/论坛吸收大家的经验,在感激之余,也想输出点什么,造福大家,因此就有了这篇水文,希望大家能够多多吸取...
  • /urls.py from django.urls import path, include urlpatterns = [ ... path(<相对路径名>, include('<应用名称>.urls')), # path('pages/', include('pages.urls')), ...
  • go语言之goroute协程_后端开发协程(coroutine)是Go语言中的轻量级线程实现,由Go运行时(runtime)管理。下面就来由go入门教程栏目介绍一下go语言中的goroute协程。 python内置的集成开发工具是什么Python自带的...
  • 阿里云钉钉应用python后端开发之安装MySQL数据库 在本系列文章中,项目需要选择MySQL作为默认数据库。 在python后端开发中,可以选择的数据库有PostgreSQL, MariaDB, MySQL, or Oracle等,一般情况下,PostgreSQL是...
  • 后端开发注意事项(Tornado) 对于实时性要求高的数据,始终使用主库session进行查询访问,而非从库; session在commit前,外部是看不到改变的; 使用 SQLAlchemy ORM 建立数据库模型时,统一使用sqlalchemy....
  • CubicWeb宣扬自己4102不仅是一个Web开发框1653架,而且还是一款语义Web开发框架。CubicWeb使用关系查询语言(RQLRelation Query Language)与数据库之间进行通信。Zope2Zope 2是一款基于Python的Web应用框架,是所有...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,143
精华内容 6,057
关键字:

py后端开发