01 Preface 一切与自学相关的技巧都是老生常谈。 因为啊,历史上留下来的所有关于自学的技巧,都是人类史上最聪明的人留下来的 —— 你我这样的人,照做就可以了…… 现在你明白怎么回事儿了吧? 千万不要一不小心就把自己搭进去…… 02 Proof-of-work 最主要是要有学习过的记录: 比如学习这本书就可以通过github来体现, 那么关于git的学习就要通过 Pro Git来进行 在这里我学会了如何向别人的github项目来进行修改并且提交! Fork——修改——commit——pull request 这样看来我之前做了太多的无用功了 git学习之Progit: https:///book/zh/v2 git的常用操作命令如下: 03 Part.1.A.better.teachyourself 最有用的一段话: 自学能力是唯一值得被不断磨练的长技。 磨练出自学能力的好处在于,无论这世界需要我们学什么的时候,我们都可以主动去学,并且还是马上开始 —— 不需要等别人教、等别人带。 靠什么呢?人么,一个都靠不上。到最后,我觉得只有一样东西真正可靠 —— 自学能力。于是,经年累月,我磨练出了一套属于我自己的本领:只要我觉得有必要,我什么都肯学,学什么都能学会到够用的程度…… 编程,我不是靠上课学会的;英语,不是哪个老师教我的;写作,也不是谁能教会我的;教书,更没有上过师范课程;投资,更没人能教我 —— 我猜,也没人愿意教我…… 自己用的东西自己琢磨,挺好。 04 Part.1.B.why.start.from.learning.coding 学校里的课本,都很严谨 —— 任何概念,未经声明就禁止使用。所以,学完一章,就能学下一章;跳到某一章遇到不熟悉的概念,往前翻肯定能找到……在学校里习惯了这种知识体系的人,离开学校之后马上抓瞎 —— 社会的知识结构不仅不是这样的,而且几乎全都不是这样的。工作中、生活里,充满了各式各样的**“过早引用”**。为什么总是要到多年以后你才明白父母曾经说过的话那么有道理?为什么总要到孩子已经长大之后才反应过来当初自己对孩子做错过很多事情?为什么在自己成为领导之前总是以为他们只不过是在忽悠你?为什么那么多人创业失败了之后才反应过来当初投资人提醒的一些观念其实是千真万确的?—— 因为很多概念很多观念是“过早引用”,在当时就是非常难以理解……自学编程在这方面的好处在于,在自学的过程中,其实你相当于过了一遍“模拟人生” —— 于是,面对同样的“过早引用”,你不会觉得那么莫名其妙,你有一套你早已在“模拟人生”中练就的方法论去应对。 尽量只靠阅读学会编程,哪怕仅仅是入门,这个经历和经验都是极为宝贵的。(哎,我看了太多视频真的浪费了很多时间啊) 05 Part.1.C.must.learn.sth.only.by.reading 习得自学能力的终极目标就是:有能力只靠阅读就能习得新技能。 滚蛋吧:不是什么东西都可以从书本里学到的! 一技傍身的人,总是不愁生活…… 那些靠阅读机器算法推送的内容而杀时间的人,恰恰就是因为他们有阅读能力才去不断地读,读啊读,像是那只被打了兴奋剂后来死在滚轮上的小白鼠。如果这些人哪怕有一点点自学能力,那么他们很快就会分辨出自己正在阅读的东西不会刺激自己的产出,只会消磨自己的时间;那么,他们就会主动放弃阅读那些杀时间的内容,把那时间和精力自然而然地用在筛选有繁殖能力的内容,让自己进步,让自己习得更多技能上去了。 所以,只要你有一次“只靠阅读习得一项新技能”的经验,你就变成另外一个人了。你会不由自主、哪怕下意识里都会去运用你新习得的能力…… 从这个角度看,自学很上瘾!能上瘾,却不仅无害,还好处无穷,这样的好事,恐怕也就这一个了罢。 我有很多偶像,英国数学家乔治·布尔就是其中一个 —— 因为他就是个基本上只靠阅读自学成才的人。十八、九岁,就自学了微积分 —— 那是将近两百年前,没有 Google,没有 Wikipedia…… 然后他还自己创办了学校,给自己打工…… 从来没有上过大学,后来却被皇家学院聘请为该学院第一个数学教授。然后,人家发明的布尔代数,在百年之后引发了信息革命…… 达芬奇也是这样的人 —— 要说惨,他比所有人都惨…… 因为几乎从一开始就貌似没有谁有资格有能力教他。 讲真,你没有选择,只靠阅读习得新技能,这是你唯一的出路。 06 Part.1.D.preparation.for.reading 编程既不是文科也不是理科…… 它更像是“手工课”。你越学就越清楚这个事实,它就好像是你做木工一样,学会使用一个工具,再学会使用另外一个工具,其实总共就没多少工具。然后,你更多做的是各种拼接的工作,至于能做出什么东西,最后完全靠你的想象力……十来岁的孩子都可以学会的东西,你怕什么? 别怕,无论说给自己,还是讲给别人,都是一样的,它可能是人生中最重要的鼓励词。 07 Part.1.E.1.entrance Last Checkpoint: 14 hours ago “速成”,对绝大多数人[1]来说,在绝大多数情况下,是不大可能的。编程如此,自学编程更是如此。有时,遇到复杂度高一点的知识,连快速入门都不一定是很容易的事情(所以我经常想快速掌握什么什么,甚至连难度都不进行评估一下,想来有点天真哦,早些时候遇到简单的东西,凭借一点小聪明还是可以的,到后来,发现需要真才实学的时候,真的已经需要大智慧了!) (只有当自己已经掌握了自学的方法之后再去谈速成才是有意义的!) 有本书可以闲暇时间翻翻,The Logician and the Engineer: How George Boole and Claude Shannon Created the Information Age。可以说,没有乔治·布尔的布尔代数,没有克劳德·香农的逻辑电路,就没有后来的计算机,就没有后来的互联网,就没有今天的信息时代 —— 世界将会怎样? 最重要的差异在于计算机能做布尔运算(Boolean Operations) (所以这里的逻辑就是:布尔的布尔代数——香浓的逻辑电路——互联网——信息时代) 计算器和计算机都是电子设备,但,计算机更为强大的原因,用通俗的说法就是它“可编程”(Programable) —— 而所谓可编程的核心就是布尔运算及其相应的流程控制(Control Flow);没有布尔运算能力就没有办法做流程控制;没有流程控制就只能“按顺序执行”,那就显得“很不智能”…… 08 Part.1.E.2.values-and-their-operators 我们可以把函数看作是“子程序”; 在 Python 中每个函数都有返回值,即便你在定义一个函数的时候没有设定返回值,它也会加上默认的返回值 None……(请注意 None 的 大小写!) 回到最开始:从结构上来看,一切的计算机程序,都由且只由两个最基本的成分构成: 运算(Evaluation) 流程控制(Control Flow) 1 2 09 Part.1.E.3.controlflow 任何进步,无论大小,其实都相当不容易,都非常耗时费力 —— 在哪儿都一样。(我不知道自己为什么会有如此想法,而且根深蒂固,之前一直以为这些东西都很是轻松,简单到轻而易举,这样的想法对我而言简直就是灾难!) 包含了分支与循环 —— 无论多复杂的流程控制用这两个东西就够了,就好像无论多复杂的电路最终都是由通路和开路仅仅两个状态构成的一样 Python 语言中,for 循环不使用其它语言中那样的计数器,取而代之的是 range() 这个我称其为“整数等差数列生成器”的函数 Range()函数 :只有一个参数的时候,这个参数被理解为 stop,生成一个从 0 开始,到 stop - 1 的整数数列.这就解释了为什么有的时候我们会在 for … in range(…): 这种循环内的语句块里进行计算的时候,经常会在变量之后写上 1,因为我们 range(n) 的返回数列中不包含 n,但我们有时候却需要 n 写嵌套的判断语句或循环语句的时候,最常用 pass,因为写嵌套挺费脑子的,一不小心就弄乱了。所以,经常需要先用 pass 占位,而后逐一突破 for 更适合处理序列类型的数据(Sequence Type)的迭代,比如处理字符串中的每一个字符 ,比如把 range() 返回的数列当作某种序列类型的索引。while 更为灵活,因为它后面只需要接上一个逻辑表达式即可 10 Part.1.E.4.functions 在函数定义中,带有 = 的,即,已为其设定了默认值的参数,叫做 Keyword Arguments(关键字参数),其它的是 Positional Arguments(位置参数)。(位置参数:就是因为位置不一样就说明意义不一样,有位置决定其参数的值) 11 Part.1.E.5.strings 字符串属于有序容器。 字符串里的每个字符,对应着一个从 0 开始的索引。比较有趣的是,索引可以是负数 我们可以使用索引操作符根据索引提取字符串这个有序容器中的一个或多个元素,即,其中的字符或字符串。这个“提取”的动作有个专门的术语,叫做“Slicing”(切片)。索引操作符 [] 中可以有一个、两个或者三个整数参数,如果有两个参数,需要用 : 隔开 在 Python 中,字符串是一个对象 —— 更准确地讲,是 str 类(Class str)的对象 这些写在对象内部的函数,有个专门的名称,类的方法(Method) 12 Part.1.E.6.containers 包括字符串、由 range() 函数生成的等差数列、列表(List)、元组(Tuple)、集合(Set)、字典(Dictionary)。 遇到由不同类型数据构成的列表,我们更可能做的是想办法把不同类型的数据分门别类地拆分出来,整理清楚 —— 这种工作甚至有个专门的名称与之关联:数据清洗。 初学者总是很好奇 List 和 Tuple 的区别。首先是使用场景,在将来需要更改的时候,创建 List ;在将来不需要更改的时候,创建 Tuple。其次,从计算机的角度来看,Tuple 相对于 List 占用更小的内存 创建空集合的时候,必须用 set(),而不能用 {} Map 是容器中的单独一类,映射(Map)容器。映射容器只有一种,叫做字典(Dictionary)。先看一个例子: 枚举:迭代的同时获取索引 13 E.7.files 如果把字母 a 计为 1、b 计为 2、c 计为 3 …… z 计为 26,那么: knowledge = 96 hardwork = 98 attitude = 100 14 Part.1.F.deal-with-forward-references 首先是要学会一个重要的技能: 读不懂也要读完,然后重复很多遍。从一开始就要做好将要重复很多遍的准备,从一开始就要做好第一次只能读懂个大概的准备 失败的原因竟然是因为“太仔细了' 但是:但是,若是为了习得新技能去阅读,就要施展“只字不差地阅读”这项专门的技能。 绝大多数自学能力差的人,都是把一切都当作小说去看,随便看看,粗略看看……(简直就是我本人了) 好的记忆力很重要,反复做整理归纳总结,记不住才怪呢 自学能力强的人有个特点,就是不怕麻烦。小时候经常听到母亲念叨,“怕麻烦!那还活着干嘛啊?活着多麻烦啊!” —— 深刻 先关注使用再研究原理 尊重前人的总结和建议 15 Part.2.A.clumsy-and-patience 反复学,最锻炼的是“归纳整理”的能力。而且,最有意思的,这在大多数情况下还是自动发生的 —— 只要你不断重复,你的大脑会在不自主之间把那些已经掌握的知识点与当前尚未掌握的知识点区分开来,前者处理起来轻松容易,甚至可以跳过;后者需要投入更多的注意力去仔细处理…… 在这个过程中,绝大多数的归纳整理工作自动完成了。最后再加上一点“刻意的、收尾性的归纳总结整理工作” —— 大功告成 一般手艺性的东西:主要靠时间 以用带练 —— 在不断应用的过程中带动刻意练习。 首先要明白,这肯定是个比“天真的想象”要长得多的过程。其次要明白,并且要越来越自然地明白,哪儿哪儿都需要很多重复。读,要读很多遍;练,要练很多遍;做,要做很多遍…… 绝对不做预算不够的事情。——做好这个就能超过一大部分的人了 学完了也就学完了,真没地儿用。没地儿用,当然就很少练 于是,我学的时候重复得比别人多;练的时候重复得比别人多;到最后用得也相对比别人多很多 —— 这跟是否有天分或者聪明与否全然没有关系 人生很长,何必惊慌——反正,这事儿跟天分与智商几乎没有任何关系。 16 Part.2.B.deliberate-practicing 手艺这个东西,尤其需要刻意练习。我们说,手艺么,主要是靠时间…… 这里的“时间”,准确地讲,就是“刻意练习”的时间,而不是任何时间 最有用的道理最没人听 下面也是我最困惑的地方 而那些看起来“一出手就是高手”的人,则恰恰相反,他们不仅花很多时间刻意练习,还总是刻意思考在哪些地方尤其要刻意练习 —— 就是这一点差别造成了那么大的差距 不做刻意练习的人就是在混时间 准备个专门的地方记录:我现在用的最多的就是 iPhone 上的 Notes,一旦遇到什么“疑似需要刻意练习”的点,就顺手记录在那里以防不小心忘记或者不小心遗漏。而后有时间的时候就拿出来看看,排列一下优先级,琢磨一下刻意练习的方式,而后找时间刻意练习,如此这般,做到“尽量不混日子”…… 凡事儿,就怕琢磨…… 17 Part.2.C.why-start-from-writing-functions —————————20190408——————————— 18 Part.2.D.2-aargs这里的知识还蛮重要的,需要返回来再学习哦1 带一个星号的参数,英文名称是Arbitrary Positional Arguments 带两个星号的参数,一会儿会讲到,英文名称是Arbitrary Keyword Arguments 在函数内部,位置参数被当作容器处理,所以,在调用函数的时候,可以吧一个容器传递给函数的位置参数。 在定义可以接收一系列值的位置参数时,建议在函数内部为该变量命名时总是用复数,因为函数内部,总是需要 for 循环去迭代元组中的元素,这样的时候,名称的复数形式对代码的可读性很有帮助 关键字参数是可以接受很多值的!两个星号,在函数内部处理关键字参数的时候,用的是对字典的迭代方式,所以在调用函数的时候也可以直接使用字典的形式! 关于参数的顺序:位置参数、一颗星的位置参数、关键字参数、两颗星的关键字参数 19 Part.2.D.3-lambda 匿名函数,一般是很小的函数,如下: lambda x, y: x y 1 先写上 lambda 这个关键字,其后分为两个部分,: 之前是参数,之后是表达式;这个表达式的值,就是这个函数的返回值。 20 Part.2.D.4-recursion 递归函数:在自身内部调用自己的函数 在函数内部绝对不调用全局变量。即便是必须改变全局变量,也只能通过函数的返回值在函数外改变全局变量 地柜的三个原则:(1)根据定义,递归函数必须在内部调用自己; (2)必须设定一个退出条件; (3)递归过程中必须能够逐步达到退出条件…123 归函数是程序员为了自己方便而使用的,并不是为了计算机方便而使用 —— 计算机么,你给它的任务多一点或者少一点,对它来讲无所谓,反正有电就能运转,它自己又不付电费… 理论上来讲,所有用递归函数能完成的任务,不用递归函数也能完成,只不过代码多一点,啰嗦一点,看起来没有那么优美而已 21 Part.2.D.5-docstrings 其实就是函数的说明书,必须在函数定义的内部语句块的开头而且需要注意保持一样的缩进。 书写规范: (1)无论是单行还是多行的 Docstring,一概使用三个双引号扩起; (2)在 Docstring 内部,文字开始之前,以及文字结束之后,都不要有空行; (3)多行 Docstring,第一行是概要,随后空一行,再写其它部分; (4)完善的 Docstring,应该概括清楚以下内容:参数、返回值、可能触发的错误类型、可能的副作用,以及函数的使用限制等等; (5)每个参数的说明都使用单独的一行…… 1 2 3 4 5 22 Part.2.D.6-modules 任何一个可以被调用的.py文件都可以被称为模块 基本就是import相关的东西 23 Part.2.D.7-tdd 算法:解决问题的步骤 这一节没有什么特别需要注意的东西 24 Part.2.D.8-main 当 Python 文件被当作模块,被 import 语句导入时,main() 函数不被直接运行; 当 Python 文件被 python -m 执行的时候,main() 才被执行。12 25 Part.2.E.deliberate-thinking 这东西能用在哪儿呢? 找活干,是应用所学的最有效方式,有活干,所以就有问题需要解决,所以就有机会反复攻关,在这个过程中,以用带练… 劳者多能 —— 你看,都想反了吧? 26 Part.3.A.conquering-difficulties 这一章讲的东西蛮好的,我自己好像也指导但就是讲不出来。 然而,相信我,所有的难点,事实上都可以被拆解成更小的单元,而后在逐一突破的时候,就没那么难了。逐一突破全部完成之后,再拼起来重新审视的时候就会发现那所谓的难常常只不过是错觉、幻觉而已 —— 我把它称为困难幻觉。 有什么必要干前功尽弃的事情呢?要么干脆别学算了,何必把自己搞成一个半吊子? “突然”之间一切都明了了! 开始“自学”的活动,本质上来看,和断奶其实是一回事儿。 幽默与生动,是要自己去扮演的角色;有趣与欢乐,是要自己去挖掘的幸福 平静地接受了它枯燥的本质;其次,就是经过多次实践已然明白,无论多枯燥,总能读完;无论多难,多读几遍总能读懂…… 于是,到最后,只不过是习惯了而已。 27 Part.3.B.1.classes-1 (需要继续看) 面向对象编程: 面向对象编程(OOP),是使用对象(Objects)作为核心的编程方式。进而就可以把对象(Objects)的数据和运算过程封装(Encapsulate)在内部,而外部仅能根据事先设计好的界面(Interface)与之沟通。 属性:必要的特征,通常是名词 方法:必要的行为,通常是动词 28 Part.3.B.2.classes-2 (需要继续看) ———初始化相关: Class里面的self的意思:这里的 self 就是个变量,跟程序中其它变量的区别在于,它是一个系统默认可以识别的变量,用来指代将来用这个 Class 创建的 Instance 在 Class 的代码中,如果定义了 init() 函数,那么系统就会将它当作用来 Instance 在创建后被初始化的函数。这个函数名称是强制指定的,初始化函数必须使用这个名称;注意 init 两端各有两个下划线 _。(所以就是在实例化一个class之后真的需要给初始化一下) 比如实例化后g = Golem(‘Clay’),那么当g被创建的时候,g就需要被初始化 ———继承相关: Interface:界面 Attributes:属性 Methods:方法 私有变量是两个下划线开始的,不能被外部引用 作用域哪里不太明白,先这样吧回过头再看! 29 Part.3.B.3.decorator-iterator-generator (需要继续看几遍) 函数工具:迭代器、生成器、装饰器。都是真正掌握Python的关键 迭代器(Iterator): 生成器(generator): 生成器表达式: 用生成器创造的迭代器(Iterator) 若是用了方括号,那就是用生成器创造的列表(List)—— 当然用花括号 {} 生成的就是集合(Set)…… 修饰器(Decorator) 函数也是对象,所以可以作为其他函数的参数或者返回值 装饰器的操作符 装饰器我还没遇到过,所以暂时还不晓得有啥用哦,完了再来看几次! 30 Part.3.B.4.regex 最强大且不可或缺的文本处理工具,用处就是在文本中扫描/搜索(Scan/Search)与某一规则(Pattern)匹配(Match,即,与规则一致)的所有实例,并且还可以按照规则捕获(Capture)其中的部分或者全部,对它们进行替换(Replece)。 正则表达式本质上是个独立的语言,短小却格外强悍 —— 乃至于,如果你竟然没学会它的话,你的之前学的编程技能干脆与残疾无异。 一个正则表达式(Regular Expression)通常被称为一个模式(Pattern)。 一个规则表达式(Regular Expression)通常被称为一个规则(Pattern)。 我们可以用书写特定的规则,用来在文本中捕获与规则一致的字符串,而后对其进行操作…… 正则化主要就是用来处理字符串文本咯?? 聊天机器人什么的~~~ 31 Part.3.B.5.bnf-ebnf-pebnf 巴克斯诺尔范式:暂时不接触吧 32 Part.3.C.breaking-good-and-bad 自学的重要技巧:把那些很难的任务无限拆分 —— 直至每个子任务都很小,小到都可操作为止。 编程,更多是拿着纸笔梳理细节的工作。一旦所有的细节都想明白了,落实成代码其实是飞快的 —— 越是工程量大的项目越是如此。 庄辰超认为,成功是不能复制的,失败是可以复制的 33 Part.3.D.indispensable-illusion 只有真正掌握了那个技能之后,那个技能才会“变”成刚需 要学,想学,那就自顾自去学吧,用不着征求别人的意见! 做个自驱动的人,而非被外部驱动的被动的人。 找活干 一切的技能都是刚需。 34 Part.3.E.to-be-thorough 全面——自学的境界 全面,是掌握一门手艺的基本。 所谓的不混时间,无非就是刻意练习、追求全面。 绝对不能只靠一本书 多读几本书。狠一点,就是多读很多本书。 教是最好的学习方法。 尽快开始整理归纳总结 一定要自己动手去做…… 有同学问,你就一定要耐心讲讲 —— 对自己有好处。 35 Part.3.F.social-selfteaching 当我们看到另外一个人正在做什么的时候,镜像神经元会尽力给我们足够的刺激,让我们“体验”那个人的感受。 No matter what you choose, build stuff and be around smart people. 我个人最看重的个人品质之一,就是有没有像样的作品 学就学得全面; 做就做得完整。 1 2 给自己足够长的时间去学;在充足“预算”之下耐心地练;不断找活干,以用带练;然后,最重要的是,一定要尽快尝试着做出属于自己的完整作品,无论大小。只有这样,你才是个值得被交往的人。 36 Part.3.G.the-golden-age-and-google 能 Google 出答案的问题,就不需要去麻烦别人。 37 Part.3.H.prevent-focus-drifting 好奇心越重的人,越是容易被注意力漂移所拖累。 把“全面完整”放到最高优先级 注意力要放在该放的地方上 |
|