01 转变学习思维 首先想说的第一点:转变学生时代的学习思维! 不要把编程学习当做学生时代的应试考试来学了,三年模拟五年高考那一套在这里是行不通的! 技能学习理论为辅实践为主,因为实际操作经验,这些细节在书上是没办法体验到的。 理解代码比记住代码更重要,我们能理解代码是干什么用的就可以了。 拿游泳来说吧,需要预习吗?需要背动作要领吗? 基本不用吧,几岁大点的小孩都会游呢!都是是通过在水里的反复练习,教练手把手地传授动作,一点一点提高熟练度学会的。 02 不要说我会什么 “我会什么”这句话,其实是最虚飘飘的东西,但你要说,XX著名项目作者,那我一听就知道了。 ① 学编程最快的捷径就是苦敲代码,积累代码量,一门语言写几万行的代码量,就上手了。 有问题,先文档,再stackoverflow,再技术文章。 ② 增加自己的项目经验,面试的时候这就是加分宝典! 提到的积累代码量也好,基础也好,最终都是为“项目”、为“产品”服务的。 敲黑板!没有项目经验就造项目经验,有空多逛逛github!github上遍地的源码分享,都可以为你所用。 github搜索项目: ③ 多结交一些同行大神,多认识一些人脉,不管怎样,直接通过人往往要比那些通过流程走容易的多。 ④ 编程是一个需要不断学习训练的过程,尤其是新手需要尝试多种学习方式并总结出最适合自己的方式。 03 多修炼内功 这里的内功指——底层技术; 两点原因:
换代这么快的今天,是无法把每一个框架/工具都学习一遍的,底层技术就是你快速上手的瑞士军刀。
你怎么和别人拉开差距?单纯就靠使用框架的能力么?这些随便从培训班抽一个人可能都会做的工作无法成为你的核心竞争力。 为什么有的人学编程特别快? 可能不是因为他有多聪明,而是他内功扎实,也就是对计算机的知识体系有一定程度上的理解。 比如在你懂了计算机网络之后,就可以很快理解 RESTAPI,GraphQL,RPC 之间的异同,也可以明白即时通讯协议 XMPP,MQTT 的优劣。 比如你了解 Lambda 演算,编译原理,形式语言,也就能理解一个语言为什么要这么设计语法,为什么不能这么写。 比如你懂了数据结构,你就能理解数据库,搜索引擎中的细节原理。 所以你眼中的聪明人真的是天才么? 不排除真的有天才,但我想更多的是普通人,只不过他学的稍微比你多一点,知识体系比你更系统一点罢了。 04 不要小瞧基础 没有基本功的积累,很快就会在某个阶段由于功底不够而无法再继续后面的学习。 Python必备基础:
专业深入方向的比如:
05 良好的编码习惯 Python好上手,但在Python中编写错误的代码也很容易。 比如下面的这些“糟糕的做法”最好远离: Import* 是一种惰性行为,不仅会污染当前的命名空间,还会使代码检查工具(如 pyflakes)无效。 在随后查看代码或调试的过程中,通常很难从一堆 import* 中找出第三方函数的来源。 错误演示 def use_mutable_default_param(idx=0, ids=[]): ids.append(idx) print(idx) print(ids) use_mutable_default_param(idx=1)use_mutable_default_param(idx=2) 输出结果 1[1]2[1, 2] 最关键的原因是: ① 函数本身也是一个对象,默认参数被绑定到函数对象。 ② append 方法将会直接修改对象,因此下次调用该函数时,绑定的默认参数不再为空列表。 正确操作 def donot_use_mutable_default_param(idx=0, ids=None): if ids is None: ids = [] ids.append(idx) print(idx) print(ids) 在 Python 中,允许对元组类型执行解包操作: # human = ('James', 180, 32)name, height, age = human 这种做法比编写name=human[0] 要聪明得多,但是, 如果你之后需要在 human 中插入性别数据 sex,那么所有的解包操作都需要修改,即使 sex 不会在某些逻辑中使用。 # human = ('James', 180, 32)name, height, age, _ = human# or# name, height, age, sex = human 有几种方法可以解决这个问题: ① 使用 name=human[0] 编程方式,然后在需要性别信息的地方插入 sex=human[3] ② 使用 dict 代表 human ③ 使用 namedtuple # human = namedtuple('human', ['name', 'height', 'age', 'sex'])h = human('James', 180, 32, 0)# then you can use h.name, h.sex and so on everywhere. 下面这样的代码经常看到: d = {}datas = [1, 2, 3, 4, 2, 3, 4, 1, 5]for k in datas: if k not in d: d[k] = 0 d[k] += 1
更简单优雅地实现这样的功能: default_d = defaultdict(lambda: 0)datas = [1, 2, 3, 4, 2, 3, 4, 1, 5]for k in datas: default_d[k] += 1 再看看如下代码: # d is a dictif 'list' not in d: d['list'] = []d['list'].append(x) 可以使用一行代码替换 # d is a dictd.setdefault('list', []).append(x) 同样,以下两种编程方式具有强烈的 C 风格: # d is a dictfor k in d: v = d[k] # do something # l is a listfor i in len(l): v = l[i] # do something 最好是以更pythoni的方式编写 # d is a dictfor k, v in d.iteritems(): # do something pass # l is a listfor i, v in enumerate(l): # do something pass 实际上,enumerate 还有另一个参数,表示序列号的起始位置。如果你希望序列号从 1 开始,则可以使用 enumerate(l, 1)。 这种代码很常见: search_list = ['Jone', 'Aric', 'Luise', 'Frank', 'Wey']found = Falsefor s in search_list: if s.startswith('C'): found = True # do something when found print('Found') break if not found: # do something when not found print('Not found') 事实上,使用 for...else 会更优雅 search_list = ['Jone', 'Aric', 'Luise', 'Frank', 'Wey']for s in search_list: if s.startswith('C'): # do something when found print('Found') breakelse: # do something when not found print('Not found') 循环内的多层函数调用带来以下两个隐藏的风险: ① Python 中没有内联函数,因此函数调用会产生一定的开销; 特别是当逻辑简单时,开销的比例将是相当大的。 ② 当你稍后维护代码时,你可能会忽略在循环中调用了该函数; 因此,在函数内部,将倾向于添加一些具有更大开销但不必每次都调用的函数。 例如 time.localtime(); 如果它是一个简单的循环,我认为大多数程序员都会将 time.localtime() 编写在循环之外,但如果引入多层函数调用则不会。 所以我建议如果不是特别复杂的逻辑,它应该直接写在循环内部而不是使用函数调用。 如果必须包装一层函数调用,则应该在函数的命名或注释中提示后续维护者:此函数将在循环内使用。 06 学会看代码 几年编程开发经验领悟到的一点: 学会看代码、知道如何调试代码非常重要! 刚开始学习编程,看到代码报错,就会茫然失措,脑子中立马闪出一个'funck'。纳闷为什么会报错? 会看代码不仅指认识就行,会看代码包含:分析代码编写的逻辑;尝试发现代码里的错误,寻找修复bug的方法..... 不要过于依赖教程给你提供的解决方案!要知道如何解决问题以及自己发现解决方案。 在自己编写还比较困难的时候,就先学习别人写的代码!先临摹,再创作。 最好是找大咖的代码来学习,学习其中的逻辑,学习举一反三! 其实解决编程代码问题也是有套路的,这个套路就是: 能不用百度就别用百度,你要学会在全球最大的技术问答平方:stackoverflow上搜索问题的答案。 从解决掉的每条错误消息中学习,不要只是修复错误就完事了,了解总结正在修复的代码有什么问题,下次再碰到同类错误就能够更快地修复错误。 07 多总结 分享 输出 我个人解决这个问题的办法就是做思维导图; 这个能帮助我快速清晰的把知识框架和内容过一遍,结合自己的理解和补充整理下来,然后逐步的充实自己的知识体系。 分享的话写博客、做开源项目都是很好的方式; 将自己学到的东西分享出来,一方面能检验自己是否掌握,另一方面还能加深自己的理解和认识。 比如学完之后做了一个笔记:对象详解 1)对象的组成: 对象=属性+方法 对象是由属性和方法组成的,属性可以理解为对象有什么,方法可以理解为对象能做什么。 2)对象的属性有哪些特征 对象的属性可以是抽象的属性 比如说洗衣机是一个对象,而且洗衣机是有颜色的,那么颜色就是一个属性,但是颜色却是个抽象的概念,因为它可以是红色、白色、黑色、蓝色等颜色。 3)对象的属性可以是另一个对象 比如说计算机是一个对象,而计算机有硬盘,那么硬盘就是计算机的一个属性,所以说对象的属性可以是另一个对象。 4)大对象由小对象所组成 比如说鼠标是一个对象,鼠标的滚轮是一个对象,鼠标里面的单片机是一个对象等等,这时候你会发现,鼠标这个大对象是由多个小对象组成的~ 总之,就像剑客对其兵刃的喜爱一样,投入精力不断打磨,总是有回报的。 |
|