1. 怎么提高编程能力逻辑思维能力
思考问题的方式,方向,解决问题的方法,也就是说应该从哪里入手,从哪里着手去解决问题。
每个人都是从零基础开始接触编程的,很多技术大牛总结了很多经验、解决问题的方式。而现在作为一个编程初学者,我们不需要重新造轮子。我们只需要跟随前辈们脚步,避免重复去走他们已经走过的弯路,也可以说我们现在做的一切都是站在巨人的肩膀来进行的。学习前辈们的经验和解决问题的方式,然后结合自身来解决自己的问题,最终融会贯通为自己所用。
建议大家,解决问题的时候,首先要把问题分解。大化小,很多小问题已经有了非常成熟的解决方案,搜索引擎可以解决大部分问题,我们直接拿来用就可以了,并且记住这种解决问题的方案。而剩下解决不了的小问题,我们在进行针对性解决,每一个小问题解决后,一整块大问题就随之解决。
编程思维的训练就是要学习成熟的解决问题的方法:比如if
语句用来做分支判断,循环用来解决反复运算的问题。穷举法、递推、递归、排序、回溯等等(如果需要当专业程序员,需要学习数据结构和算法,设计模式等等,需要学的东西很多很多。但首先要解决的一个问题是自己能写代码解决一般问题。)
训练函数抽象,类抽象解决问题。如对有序数组,查找特定数值,没有经过训练,初学者,直接用循环遍历。如果经过二分法算法的训练,下次碰到这样的问题,就用二分法求解。
(需求->需求分析->设计->编码->测试->交付等)
拿到一个习题,还没有进行分析,就马上敲代码,这个学习方式,是不好的学习方式。
再设计,用哪种数据类型(数据结构)来组织或保存数据,用何种算法来计算效率最高,用面向过程,还是面向对象的编程范式,还是用函数式编程等等。设计后,再编写代码,最后写测试。
如果大家对于学习编程有任何疑问,可以随时咨询我,这是我的V:Zhanlaoshi71 从事IT行业16年,精通八种语言,多跟专业的人交流学习。
只有先经过训练常见的算法,分解问题,会做需求分析,慢慢训练,才会养成自己的思路。没有人一出生会编程,只有经过训练,才会学会编程。很多牛逼程序员用vim,敲的啪啪响,一会儿一屏幕代码,为啥那么熟练使用vim,习惯成自然。当你训练多了以后,学会一定的套路(解决问题的方法),养成独立思考的习惯,假以时日,自然就有思路了。
养成独立思考的习惯,养成切分问题,养成大问题化解小问题,养成套用学过的算法,才会有思路。简单的判断、循环都不会写,就想玩django,何来的思路?
万丈高楼从地起,希望大家脚踏实地实地的从基础训练起,先达到独立写代码解决一般的问题,再谈项目。见过盲目上号称牛逼项目的培训班出来的程序员,
没有学会独立写代码解决一般的问题的能力,开发项目时如狗咬刺猬无从下手。
2. 说说这篇我为什么从python转向go
恩看了这篇我为什么从python转向go,
看来作者也是 KSO 轻办公/企业快盘团队的。作为快盘从无到有时期的工程师之一(总是被潇洒哥说他们改我留下的 bug ),又恰好是
Python/Go 双修(大雾其实我是 Rust 党),其实一开始我是拒绝的,ang ang ang,那就随手写一点把。
一段段来吧,首先作者说 Python 是动态语言
python是一门动态语言,不是强类型系统。对于一个变量,我们有时候压根不知道它是什么类型,然后就可能出现int + string这样的运行时错误。
在python里面,可以允许同名函数的出现,后一个函数会覆盖前一个函数,有一次我们系统一个很严重的错误就是因为这个导致的。
事实上,如果是静态检查,pylint 和 pyflakes 是可以做这件事的,虽然不能和 go
那种静态编译型语言比,但也侍枯足够了。如果没记错的话,阿通当年是要求全组都在提交前做静态检查的。我认为这种问题更多的应该是人员素质上来避免,毕竟葱头
也说过,代码自己写的就要多回头看看,看能不能重构,能不能做更好。不是说偷懒不行,但是从中得出 Python
动态特性太灵活,Python:怪我咯?
另外,函数作为第一对象,在 Python 中是 feature,Go 要写个 mock,简直虐得不要不要的。
其实这个一直是很多人吐槽python的地方,不过想想,python最开始是为了解决啥问题而被开发出来的?我们硬是要将他用到高性能服务器开发上面,其实也是有点难为它。
如果没记错,无论是轻办公还是快盘,是重 IO 不重 CPU,最大耗时是数据块加密老尺洞那块,我在的时候是 java 写的。另外高性能服务器选 Go 也是虐得不要不要的,各种小心翼翼避免 GC。大多数极端情况下,pypy 的性能足矣胜任了,我认为这不算充分条件。
python的GIL导致导致无法真正的多线程,大家可能会说我用多进程不就完了。但如果一些计算需要涉及到多进程交互,进程之间的通讯开销也是不得不考虑的。
其实,Python 有宏可以绕开这个 GIL,但是呢架构设计得好其实可以避免的,到异步那块我会说。
无状态的分布式处理使用多进程很方便,譬如处理http请求,我们就是在nginx后面挂载了200多个django server来处理http的,但这么多个进程自然导致整体机器负载偏高。
但即使我们使用了多个django进程来处理http请求,对于一些超大量请求,python仍然处理不过来。所以我们使用openresty,将高频次的http请求使用lua来实现。可这样又导致使用两种开发语言,而且一些逻辑还得写两份不同的代码。
如果推测没错,你们现在还在用五年前写的 Gateway?那个基于 django route
的流量分发层?四年前我离开的时候已经小范围的使用 Flask+Gevent Demo 测试过了,无论是性能还是负载都比同步模型的 django
有优势。如果还是 django
这套的话,我只能说比较遗憾,毕竟当年金山新员工大赛头牌就是我和几个小伙伴写的实时同步在线文档编辑系统,用的就是这套技术。
因此这是个工程问题,并非语言问题。 Python 提供给了你了这么多工具,硬要选一个传统的,Old fashion 的,Python:怪我咯?
django的网络是同步阻塞的,也就是说,如果我们需要访问外部的一个服务,在等待结果返回这段时间,django不能处理任何其他的逻辑(当然,多线程的除外)。如果访问外部服务需要很长时间,那就意味着我们的整个服务几乎在很长一段时间完全不可用。
为了解决这个问题,我们只能不断的多开django进程,同时需要保证所有服务都能快速的处理响应,但想想这其实是一件很不靠谱的事情。
同步模型并非不行,因为 overhead 足够低,很多业务场景下用同步模型反而会取得更好的效果,比如豆瓣。同步模型最大的问题是对于 IO 密集型业务等待时间足够长,这时候需要的不是换语言 ,而是提醒你是不是架构要改一下了。
虽然tornado是困租异步的,但是python的mysql库都不支持异步,这也就意味着如果我们在tornado里面访问数据库,我们仍然可能面临因为数据库问题造成的整个服务不可用。
tornado 是有这个问题,但是 gevent 已经解决了。我在 node.js 的某问题下曾经回答过,对于 node
而言,能选择的异步模型只有一个,而 Python 就是太多选择了。另外 pypy+tornado+redis
可以随意虐各种长连接的场景,比如我给我厂写过的一个 push service。
其实异步模型最大的问题在于代码逻辑的割裂,因为是事件触发的,所以我们都是通过callback进行相关处理,于是代码里面就经常出现干一件事情,传一个callback,然后callback里面又传callback的情况,这样的结果就是整个代码逻辑非常混乱。
这个还真不是,如果说没有 ES6 的 JavaScript,可能真有 Callback hell,但这是 Python 啊!Python
早就实现了左值绑定唉,yield 那姿势比某些天天吹的语言不知道高到哪里去了,当然我说的是完整版的 Python3 yield。即便是不完整的
Python 2 yield 用于异步表达式求值也是完全足够的,tornado 的 gen.coroutine 啊。
同步形态写异步,在 Python 实力强的公司里面早普及了,这是个工程问题,并非语言问题。当然把这种事怪在 Python 身上,Python:怪我咯?
python没有原生的协程支持,虽然可以通过gevent,greenlet这种的上patch方式来支持协程,但毕竟更改了python源码。另外,python的yield也可以进行简单的协程模拟,但毕竟不能跨堆栈,局限性很大,不知道3.x的版本有没有改进。
无论是 Gevent 还是 Greenlet 均没修改 Python 源码,事实上这货已经成为了 Py2 coroutine 的标准,加上豆瓣开源出来的greenify,基本上所有的库都可以平滑的异步化,包括 MySQL 等 C 一级的 lib。自从用上这套技术后,豆瓣的 Python dev 各种爽得不要不要的。
当我第一次使用python开发项目,我是没成功安装上项目需要的包的,光安装成功mysql库就弄了很久。后来,是一位同事将他整个python目录打包给我用,我才能正常的将项目跑起来。话说,现在有了docker,是多么让人幸福的一件事情。
而部署python服务的时候,我们需要在服务器上面安装一堆的包,光是这一点就让人很麻烦,虽然可以通过puppet,salt这些自动化工具解决部署问题,但相比而言,静态编译语言只用扔一个二进制文件,可就方便太多了。
恰好我又是在开发基于 docker 的平台, docker 还真不是用来做部署这事的。首先, Python 是有 virtualenv
这个工具的,事实上对比包管理和包隔离,Python 比 Go 高得不知道哪里去了。Python 跟 Git 谈笑风生的时候, Go 的 dev
们还得考虑我怎样才能使得 import 的包稳定在一个版本上(当然现在有很多第三方方案)。Virtualenv + Pip 完全可以实现
Python 部署自动化,所以这个问题我认为是,工具链选取问题。毕竟是个十几年的老妖怪了,Python
啥情况没见过啊,各种打包工具任君选择,强行说 Python 部署不方便,Python:怪我咯?
python非常灵活简单,写c几十行代码才能搞定的功能,python一行代码没准就能解决。但是太简单,反而导致很多
同学无法对代码进行深层次的思考,对整个架构进行细致的考量。来了一个需求,啪啪啪,键盘敲完开速实现,结果就是代码越来越混乱,最终导致了整个项目代码
失控。
曾经知乎有个帖子问 Python 会不会降低程序员编程能力,
我只能说这真的很人有关。你不去思考深层次的东西怪语言不行是没道理的,那好,Go 里面 goroutine 是怎么实现的,一个带 socket 的
goroutine
最小能做到多少内存,思考过?任何语言都有自己的优势和劣势,都需要执行者自己去判断,一味的觉得简单就不会深入思考这是有问题的。另外,代码混乱我认为
还是工程上的控制力不够,豆瓣有超过10W行的 Python 实现,虽然不说很完美,大体上做到了不会混乱这么个目标。
还有,C 写几十行搞定的 Python 一行解决这绝对是重大 feature,生产力啊,人员配置啊,招人培养的成本啊,从工程上来说,Python 在这一块完全是加分项,不是每个项目都要求极致的并发,极致的效率,做工程很多时候都是要取舍的。
虽然java和php都是最好的编程语言(大家都这么争的),但我更倾向一门更简单的语言。而openresty,虽然性
能强悍,但lua仍然是动态语言,也会碰到前面说的动态语言一些问题。最后,前金山许式伟用的go,前快盘架构师葱头也用的go,所以我们很自然地选择了
go。
Openresty 用 lua 如果按照动态语言的角度去看,还真算不上,顶多是个简单点的 C。许式伟走的时候大多数都是
CPP,葱头目前我还不知道他创业用的是什么写的,不过他肯定没语言倾向。当年无论是 leo 还是 ufa,一个用 Python 一个用
Java, 他都是从工程实际来选择使用什么样的语言。
error,好吧,如果有语言洁癖的同学可能真的受不了go的语法,尤其是约定的最后一个返回值是error。
这其实是 Go style,无论是 go fmt 还是 error style,Go 其实是想抹平不同工程师之间的风格问题。不再为了一个缩进和大括号位置什么的浪费时间。这种方法并不是不好,只是我个人觉得没 rust 那种返回值处理友善。
GC,java的GC发展20年了,go才这么点时间,gc铁定不完善。所以我们仍然不能随心所欲的写代码,不然在大请求量下面gc可能会卡顿整个服务。所以有时候,该用对象池,内存池的一定要用,虽然代码丑了点,但好歹性能上去了。
1.4 开始 go 就是 100% 精确 GC 了,另外说到卡顿啊,完全和你怎么用对象有关,能内联绝不传引用大部分场景是完全足够的,这样 gc 的影响程度会最低。实在想用池……只能说为啥不选 Java。
天生的并行支持,因为goroutine以及channel,用go写分布式应用,写并发程序异常的容易。没有了蛋疼的callback导致的代码逻辑割裂,代码逻辑都是顺序的。
这是有代价的,goroutine 的内存消耗计算(当然1.3还是1.4开始得到了很大的改善,内存最小值限制已经没了),channel
跨线程带来的性能损耗(跨线程锁),还有对 goroutine 的控制力几乎为 0
等。总之这种嘛,算不上是杀手级特性,大家都有,是方便了一点,但也有自己的弊端。比如我们用 go 吧,经常就比较蛋疼 spawn 出去的
goroutine 怎么优美的 shutdown,反而有时候把事情做复杂化了。
性能,go的性能可能赶不上c,c++以及openresty,但真的也挺强悍的。在我们的项目中,现在单机就部署了一个go的进程,就完全能够胜任以前200个python进程干的事情,而且CPU和MEM占用更低。
我不严谨的实测大概 gevent+py2 能达到同样逻辑 go 实现的 30%~40%,pypy+tornado 能达到
80%~90%,混合了一些计算和连接处理什么的。主要还是看业务场景吧,纯粹的 CPU bound 当然是 go 好,纯粹的 IO bound
你就是用 C 也没用啊。
运维部署,直接编译成二进制,扔到服务器上面就成,比python需要安装一堆的环境那是简单的太多了。当然,如果有cgo,我们也需要将对应的动态库给扔过去。
我们现在根据 glibc 所处的 host 版本不同有2套编译环境,看上去是部署简单了,编译起来坑死你。另外虽然说 disk 便宜,这几行代码就几M了,集群同步部署耗时在某些情况下还真会出篓子。
开发效率,虽然go是静态语言,但我个人感觉开发效率真的挺高,直觉上面跟python不相上下。对于我个人来说,最好的
例子就是我用go快速开发了非常多的开源组件,譬如ledisdb,go-mysql等,而这些最开始的版本都是在很短的时间里面完成的。对于我们项目来
说,我们也是用go在一个月就重构完成了第一个版本,并发布。
3. 网络爬虫 python 毕业论文呢
做爬虫,特别是python写说容易挺容易,说难也挺难的,
举个栗子 简单的:将http://paste.ubuntu.com上面的所有代码爬下来
写个for循环,调用urllib2的几个函数就成了,基本10行到20行以内的代码
难度0
情景:
1.网站服务器很卡,有些页面打不开,urlopen直接就无限卡死在了某些页面上(2.6以后urlopen有了timeout)
2.爬下来的网站出现乱码,你得分析网页的编码
3.网页用了gzip压缩,你是要在header里面约定好默认不压缩还是页面下载完毕后自己解压
4.你的爬虫太快了,被服务器要求停下来喝口茶
5.服务器不喜欢被爬虫爬,会对对header头部浏览器信息进行分析,如何伪造
6.爬虫整体的设计,用bfs爬还是dfs爬
7.如何用有效的数据结构储存url使得爬过的页面不被重复爬到
8.比如1024之类的网站(逃,你得登录后才能爬到它的内容,如何获取cookies
以上问题都是写爬虫很常见的,由于python强大的库,略微加了一些代码而已
难度1
情景:
1.还是cookies问题,网站肯定会有一个地方是log out,爬虫爬的过程中怎样避免爬到各种Log out导致session失效
2.如果有验证码才能爬到的地方,如何绕开或者识别验证码
3.嫌速度太慢,开50个线程一起爬网站数据
难度2
情景:
1.对于复杂的页面,如何有效的提取它的链接,需要对正则表达式非常熟练
2.有些标签是用Js动态生成的,js本身可以是加密的,甚至奇葩一点是jsfuck,如何爬到这些
难度3
总之爬虫最重要的还是模拟浏览器的行为,具体程序有多复杂,由你想实现的功能和被爬的网站本身所决定
爬虫写得不多,暂时能想到的就这么多,欢迎补充
4. Python2.7 中文字符编码,使用Unicode时,选择什么编码格式
关于编码和乱码的问题,我简单讲一下。
通常问这类问题的人是混淆了若干个不同的概念,并且他们自己也没有意识到自己混淆了这些概念的。
终端显示字符的编码(windows下终端是cmd,linux下是各种terminal,远程登录是putty或者xshell)
shell环境的编码。比如中文版windows用的是gbk(向下兼容gb2312),大多数linux发行版使用的是utf-8(LANG=zh_CN.UTF-8)。
文本文件的编码。这个通常取决于你的编辑器,而且有的编辑器支持多种编码的话,你可以在文本开头位置指定编辑器使用特定编码。比如# -*- coding: utf8 -*-,vim看到这行会默认将这个脚本认定为utf-8兼容编码格式。
应用程序的内部编码。一个字符串,作为数据只是一个字节数组,但是作为字符的数组,就有一个解析方式。java和python的内部字符编码是utf-16,python和java都支持用不同的编码来对字节数组进行decode来得到字符数组。
拿题主的问题来解释一下。
我在ubuntu kylin中文环境下默认terminal中做了同样的实验,但是结果和题主恰好相反:
题主现在弄了一个文件,在开始加上了
# -*- coding: utf8 -*-
这下编辑器看到了,知道这文件是utf-8的了。所以编辑器对读入的一坨坨字节用utf-8来解码,对于输出到磁盘的汉字也用utf-8来编码。所以你在文件里面看到的看上去像“汉字”的东西,就和第一种情况下想同了,当然代码就跑得通。
顺便说一下,如果编辑器无视行首这行编码声明,或者编辑器无法支持utf-8格式,那么你弄好的文件在那个编辑器下就会显示乱码,多么简单的道理啊。
终端和环境的编码一致(本机通常是一致的,不一致常常出现在远程登录);如果不一致就需要有编辑器或者文本阅读器做一个兼容两者的转换。
编辑器能够认识文本编码
系统拥有能显示这种字符的字体。
这也就是我为什么一直反对在程序文本中使用除ascii之外的所有编码字符的原因。环境太复杂了,绕开问题远比解决问题轻松。