唠唠python(4) -- 简化工作

胜兵先胜而后求战,败兵先战而后求胜。 – 孙子兵法

遇到问题

我的女朋友最近生病了,周三下了班就回了家,顺带着还把在公司的一部分工作带了回来。

等我回到家,她已经卧在床上睡一觉了。

过了一会她睡醒了,坐起来跟我说:“工作没做完,你帮我做一下吧。很简单,就是把这张表格里的数字,以10000为单位,上或下取整,填到它下面的格子里。”说罢,就又睡了过去。

怎么计算

我粗略地看了一眼,这是一个excel表格文件,就是下面的这张表格。

待处理表格

简单查看了一下excel的基础知识。这一个一个的格子,叫作“单元格”,哈哈,形象吧。暂时我们只需要这个概念。

这里面有黑色内容的单元格和红色内容的单元格。红色内容的单元格是计算上面的黑色单元格的内容(物料的待收数据)得到的结果。

我们的目标是,输入这个文件,然后让计算机自己经过一系列的计算过程,将表格中的还未计算过的数据按给定的规则计算,将计算结果写到下面一个单元格,并帮我们把处理后表格保存下来。

这个目标实在激动人心!我跟我女朋友确认过,以这次的数据量,如果人工来做,可能需要花费3-4个小时的时间。而对计算机来说,在一分钟内就可以完成,而且可以确保结果的准确性。需要的知识也浅显易懂,如果对相关知识熟练,完全可以在半小时内将我们想要做的事情清楚地告诉计算机。

当然,学习是循序渐进的。在这篇文章中,我们先把目标降低一些:告诉计算机一个待收数量,和一条规则(以10000为单位上取整),让它帮我们计算实际的代收数量。这是我们完成整个目标的第一步,这个技巧也完全可以用在其它类似的工作上。

获取输入

首先,我们需要告诉计算机待收数量。这当然很简单,我们在前面已经说过了。假设待收数量是1234:

1
2
3
>>> 1234
1234
>>>

但是,这样会显得很仓促:1234代表什么呢?我们现在当然知道,它就是我们要求值的数据。但当我们写入到一个文件时,如何把1234传进去呢?

显然,我们可以直接写到文件,比如:

1
print 1234

而此时,如果再重新输入一个数字时,我们就需要打开文件,然后把1234改为新的数字,保存文件,然后运行。修改代码文件很繁琐,而且是很危险的,这还只是一行简单的代码,想想,如果一个代码文件有上百行,我们如何再找到这个数值的位置?会不会小手一抖,把其它行的数据也修改了而自己并没有意识到?繁琐的操作也必然会降低我们的效率。

这时,我们就自然有这么一个需求。

计算机:您好,我最亲爱的某某某,您的待收数量是多少,我来为您计算实际待收数量。

亲爱的某某某:嗯,1234。

计算机:您实际需要待收的数量是10000。

嗯,这就是人们所说的交互,其实就是让人跟计算机的沟通像人与人的沟通一样顺畅。

这时,我们需要知道这么一个东西:

1
2
3
4
>>> int(raw_input("请输入您的待收数量:"))
请输入您的待收数量:1234
1234
>>>

注意,里面的第一个1234是我们自己输入的,后面还跟了一个回车。

int(raw_input("请输入您的待收数量:")),这么大一坨?没关系,先死记下,在之后的文章我们会进一步了解。我们只需要知道,它让计算机询问我们待收数量。

如何计算取整后的值

我们现在用的python是个死脑筋。为什么这么说呢?如果你使用的python是之前文章中链接的python或是系统默认安装的,试试下面这个:

1
2
3
>>> 5 / 2
2
>>>

我们在学校学到的可是5 ÷ 2 = 2.5,现在却得到个2。谁的问题?

语言的问题。语言是有局限的,而当我们输入5 / 2时,python解释给计算机说:“请帮我们计算一下5 ÷ 2的值,取整就可以了,小数点我们就不要了。

语言是在发展的,文章中用的python版本是python2,此时,默认情况下,整数除法的结果是整数,而且是下取整。

现在回到我们的问题:给一个数字,以10000为单位,上取整或下取整。我们假设是上取整,想想应该怎么做呢?

我们把单位缩小,先来看一下以3为单位上取整,我们来取一批数值观察一下。

我们来分别观察一下 待收数量实收数量 的值和它们之间的相互关系格式:

  • 待收数量:1,实收数量:3,待收数量 ÷ 3后下取整:0
  • 待收数量:2,实收数量:3,待收数量 ÷ 3后下取整:0
  • 待收数量:3,实收数量:3,待收数量 ÷ 3后下取整:1
  • 待收数量:4,实收数量:6,待收数量 ÷ 3后下取整:1
  • 待收数量:5,实收数量:6,待收数量 ÷ 3后下取整:1
  • 待收数量:6,实收数量:6,待收数量 ÷ 3后下取整:2
  • 待收数量:7,实收数量:9,待收数量 ÷ 3后下取整:2
  • 待收数量:8,实收数量:9,待收数量 ÷ 3后下取整:2
  • 待收数量:9,实收数量:9,待收数量 ÷ 3后下取整:3

我们发现,待收数量 ÷ 3后下取整 的值会随着 实收数量 增长,但并不完全一致,而是相差 2。如果在 ÷ 3 前先将 待收数量 +2,则结果刚好变成了3倍的关系。如下:

  • 待收数量:1,实收数量:3,(待收数量 + 2) ÷ 3后下取整:1
  • 待收数量:2,实收数量:3,(待收数量 + 2) ÷ 3后下取整:1
  • 待收数量:3,实收数量:3,(待收数量 + 2) ÷ 3后下取整:1
  • 待收数量:4,实收数量:6,(待收数量 + 2) ÷ 3后下取整:2
  • 待收数量:5,实收数量:6,(待收数量 + 2) ÷ 3后下取整:2
  • 待收数量:6,实收数量:6,(待收数量 + 2) ÷ 3后下取整:2
  • 待收数量:7,实收数量:9,(待收数量 + 2) ÷ 3后下取整:3
  • 待收数量:8,实收数量:9,(待收数量 + 2) ÷ 3后下取整:3
  • 待收数量:9,实收数量:9,(待收数量 + 2) ÷ 3后下取整:3

也就是说,实收数量 刚好是 (待收数量 + 2) ÷ 3后下取整的3倍,其中的 2 实际上就是由 3 - 1 得来的。我们用数学公式整理一下现在的这个想法:

1
2
3
实收数量
= (待收数量 + 2) / 3 * 3
= (待收数量 + (3 - 1)) / 3 * 3

注意,其中的 / 符号即我们python语言里的除法,它是下取整的。

类比到10000时的情形,我们的公式会变成下面这个样子:

1
实收数量 = (待收数量 + (10000 - 1)) / 3 * 3

实际上,如果我们可以让计算机整数相除时上取整(而不是下取整),公式就会变得异常简单:n 上取整除以 10000 * 10000,在我们学习了后面的更多知识后就可以做到。现在这个公式(n + (10000 - 1)) / 10000 * 10000虽繁琐,但已是我们通过自己仅有的一点计算机知识所能学到的了。

马儿跑起来

下面,我们将之前的分析总结到一个文本文件里:

1
print 10000 * (n + (10000 - 1)) / 10000

将n替换为提示用户输入待收数量:

1
print (int(raw_input("Tell me the quantity: ")) + (10000 - 1)) / 10000 * 10000

将以上内容保存到a.py,然后输入python a.py并回车,试试看:

1
2
3
$ python a.py
Tell me the quantity: 1234
10000

嗯,不错,可以。

一点遗憾

这是我们迈出的很重要的一点,如果你跟下来并且看懂了,这说明我们已经掌握了把自己的思想描述给计算机的技巧。

但这还不完美,离我们的目标自动处理数据并保存结果还是有一定距离的。多远的距离呢,嗯,可能是4-5篇文章吧。不算远,对吧,假定一篇文章40分钟,加起来也就是3-4个小时的样子。想想我们前面提到的,这些数据手工处理都要3-4个小时,太他妈赚了。

当然,3-4个小时是不够的,我们还需要一些时间消化和遗忘。不过,不管怎么算,这都是人生中很成功的一笔交易。

这篇文章中,还有很多有趣的东西被我一带而过了,留到下一篇我们再一起聊聊吧。

已经晚上23了,洗洗睡了。明天又是崭新的一天,啊哈哈。

我的世界(1) - 第一个夜晚

记得那是我来到这个世界的第一天。

我站在呼啸的风中有点瑟瑟,低头时才发现,自己的身体就这样裸露地暴露在空气中。

新奇伴随着陌生,举目四望,空无一人。目所能及之处,低矮的橡树,崎岖不平的草地,隐约能看到几个水塘。我抬起头,看到很远的地方有一个亮白色的圆点。

后来过了很久,我从书上看到,我其他的同类们叫它“日”。“日”,听起来动感十足,看上去也像是在跳动一般。

我四处游荡,想快些了解这个陌生的世界。

我来到水边,看到了朦朦胧胧的倒映的自己:一头杂乱的棕色长发,多毛的灰色脸面。

一切都是新的。一上午走下来,肚子开始咕噜噜地叫,步子也慢慢地沉重下来,眼前的景物越来越不真实。

就在这时,我发现不远处有一只白色的动物在走动,内心有点欣喜,又有点恐惧。

我必须向前,饥饿战胜了一切。

当我慢慢靠近它时,它并没有跑。这给了我很大的信心,我感觉眼角有点湿润。

为了防止它攻击本就虚弱的我,我决定忍着饥饿,在它身边观察上一小会。它长得跟我有点不一样,长着一身绒绒的白色的毛,有着像我一样的灰色的脸,也有像我一样的四肢,但是四肢都是立在地上的。偶尔会“咩咩”地叫几声。

它缓缓的走动,“咩咩”的叫声,让我觉得它不太可能会攻击我。此刻我必须觉得它不会攻击我。

我抄起身边的一根木棒,快步走向前去,将木棒重重地拍在了白色动物的脑袋上。它“咩”地一声大叫,疯狂地朝远处跑去。我也疯狂地追奔过去,又重重地加了一棒。这次它没有再发出“咩咩”的叫声,“噗通”一声倒在了地上。

一棒子,拖走

我开始不顾一切地胡吃乱啃一番,以夺回被饥饿渐渐控制的身体。而此刻我所有的行动,都是出于最原始的本能。

吃过肉以后,身体渐渐地恢复了一些。

许久之后,我知道这是一种叫做“绵羊”的动物。正如其名,这真是一种温柔的动物。

这时,四周开始渐渐地暗了下来。“日”也已变成了暗红色。一阵末名的恐惧开始朝我袭来。

我猜想,黑夜将会彻底摧毁我的视力,这眼前的一切都将会变成未知,我将会陷入永无止境的黑暗。

恐惧一下子包围了我,而且我对这种处境无能为力。无力感在慢慢侵入我的身体,此刻,我必须要找到暂时躲避这种未知恐惧的地方。

我四下环顾一周,发现了一个山洞。我来到这个山洞前,向里望去,没有发现其它生物。我必须在视力完全丧失前将洞口堵住,以确保没有未知的生物闯进来。

我匆忙地捡起些石头,趁着还有一点点光亮,快速地将洞口堵住,只留下一个小口,让我可以知道外面的情况,以免记不得山洞的出口,最后可能把自己也遗忘在山洞里。

我蜷缩在狭小的山洞里,突然听到有什么东西碰到草地的“簌簌”声,过了一会,看到一个绿色的怪物,吓得我喘气都缓慢了下来。幸运的是,它没有看到山洞中的我。当看着它越走越远时,我被自己感动了。

如果夜晚来临时,有哪怕一丝光,像太阳那样,可以照亮我的四周,该有多好?!

山洞里一片漆黑,只能听到我自己的心跳。抬起头时,从留下的小口处向上望去,我惊喜地发现了头顶上方,遥远的地方闪着一些明亮的小东西。后来我惊喜地知道,那叫做“星空”。

如果我离它们足够近,是不是就可以感受到光亮。

我决定,如果能活下来,一定要想办法去到那个明亮的小东西那里。它们给了我生的希望。

明亮的小东西成群结队地缓慢移动,在暗蓝色的背景下,承载了我无限的想像。一切也在不知不觉间发生了微妙地变化,时间缓慢移动,暗蓝的背景在慢慢地变得明亮,最后仿佛像我刚来时的样子。

我鼓起勇气,打算到外面看看情况。我缓慢地挪开堆在洞口的几块石头,朝外面望去。四下都是我刚来到这里的情景。远处一片绯红,“日”出现了,并且缓缓升起。

世界再一次在我的眼中模糊了。

唠唠python(3) -- 保存计算过程

昨天的文章,我们学会了跟计算机进行简单的语言交流和用计算机来做简单的算术。我们发现,计算机用来做简单的算术还是很方便的。但不知你是否注意到了,每次当我们退出翻译器时,我们之前的数据就消失了。

消失比错误更可怕,它代表着我们已不能确定对错,而且就算错了,错误的根源也无从找起。

多可怕!

奇怪的翻译器

在上一篇文章里,我们通过实验,得知,在python翻译器里输入"hello",翻译器给我们回复了一个'hello'。有的朋友可能已经注意到了,输出的hello两边有一对'

1
2
3
>>> "hello"
'hello'
>>>

不对呀,我们输入的是",结果里带的却是'?!

先别慌,我们说在python里,一句许两边要带",实际上,'"在python里面功能是一样的。没错,"hello"'hello'并没有什么本质的区别。

那现在问题来了:

  1. 为什么python的输出里要带一对'呢?
  2. 我就是不想看到这个',怎么办?

跟计算机打招呼做算术题是一码事

没错,在python翻译器看来,在对待这两者时,处理方式是一样的。

想想我们在做1+1时,翻译器做了什么?它把我们输入的文字翻译给计算机,并将结果显示给我们。

那当我们输入"hello"时,翻译器又做了什么?它把我们输入的文字翻译给计算机,并将结果显示给我们。

看到了吗,这两个答案其实是一致的。不同之处在于值本身,一个值是一句话,而另一个值是一个数字。

试想,如果把"hello"换成"1",而翻译器显示了一个1,我们就不知道这是一句话还是一个数字了。所以,结果,跟我们的猜想一致。

1
2
3
>>> "1"
'1'
>>>

现在问题1的答案已经很清晰了,为什么python的输出里要带一对'呢?这代表求值的结果是一句话,而非一个数字或者其它什么。

主动地表达我们的意图

对,是时候表达我们的想法了。

之前,我们是把python翻译器当作一个计算器,对一句话的计算也好,对一个算术表达式的计算也罢。

对一句话求值,所得的结果是一句话。为了表明它是一句话,结果的两边加了一对'

现在,我们要对计算机提出更高的要求。我们不需要计算机帮我们对一句话求值,我们想直接把一句话显示到屏幕上。这也就是问题2的答案,显示意味着我们不再需要知道这是一句话或一个数字,而是想知道这个值表达的是什么。"1"1你都给我显示1就好了,我知道是什么意思。

1
2
3
>>> print "hello"
hello
>>>

我们告诉翻译器,帮我们显示一句话"hello",计算机显示给我们一个没有"hello

需要注意的是,这里的print "hello"仍然会求值并将值显示出来。但因为这里的值是空的,所以我们只看到了hello

hello是求值过程中产生的输出,而求值没有结果

保存我们的计算过程

前面说,我们有时需要查错,所以需要保存计算过程

保存计算过程还有一个更重要的意义,因为我们的目标,是让计算机帮我们更高效的工作,如果不能重复的使用我们之前使用过的计算过程,意味着工作不仅没有高效起来,反而更加低效了。

所以保存我们的计算过程,就显得十分之必要。

从前面我们输入过的代码来看(对,我们已经是在写代码了),代码的表现形式非常简单,都是文字,或者说文本。也就是说,只要我们把以上的代码记录到文本文件里面就完成了保存计算过程的目标。

保存计算过程就是这么简单。

不过这里还有几点需要补充说明一下:

  1. 对文件名的要求:文件名要以.py结尾,以表明文件里存放着用python语言写成的”小诗”或”文章”。如果你不知道什么名字好听,a.py或者b.py都是不错的选择。
  2. 执行时要注意,执行的结果,更遵循主动地表达我们的意图,而不是直接求值并显示值。这里可能不太好理解,在python翻译器里求值时,翻译器会直接显示求值结果,但是,当直接执行保存在文件里的代码时,求值结果不会再直接显示,而是需要我们使用前面提到的print来告诉计算机显示。

重复使用计算过程

我们先来实践一下保存我们的计算过程

还记得上一篇文章中提到的那个神密的黑色窗口吗。打开黑色窗口后,输入notepad a.py(windows)或nano a.py(其它系统)并回车,这会创建一个新的名为a.py的文件。打开文件后输入以下内容并保存。这样,我们的计算过程就被保存到了a.py这个文件。

1
print "hello"

接下来,我们就可以使用这个计算过程了。

在黑色窗口内输入python a.py并回车,即可看到类似我们之前的输出了。

1
2
C:\> python a.py
hello

这个命令跟之前请出翻译时使用的命令,唯一区别在于这里多了一个文件名。

只是显示一个"hello",未免显得单调乏味。但是实际上,这代表着我们已经可以完成一个简单系统hello的从开发到运行的整个过程了。

当然,这还远远不够。我们需要这个系统能接收用户的输入(有可能是按钮点击、文字输入或者游戏手柄按键输入等),并可以通过复杂的计算过程,最后得到我们想要的结果(有可能是一个处理过的excel文件,或者一张图片,一封邮件等)。

当然,丰富多样的输入,复杂计算,不同载体的输出,也都是十分简单的。想想我们输出hello的过程吧,与此大同小异,只是对一些新鲜事物更熟悉的过程。

下一篇,我们就来利用已经学过的知识,与计算机这个古板的老朋友一起合作,来抽象一部分我们繁琐的工作。

唠唠python(2) -- 初识ABC

一周又过去了,时间过的真快。冰心奶奶说昙花只在夜里开,而且花期极短,开放时能听到“簌簌”的声音。时间有没有声音呢?

重新认识计算机语言

python的作者叫“吉多”(听起来像名贵犬种)。

我们之前说“吉多创造了python语言,并教会了计算机使用这门语言”,其实这样说法不太准确。

事实上,计算机只认得一种叫做不可描述的语言,而且我们人类是无法搞懂的。所谓的教会计算机使用一门语言,其实是我们请了一个翻译,将我们能认识的语言翻译成计算机能懂的不可描述语言。

请个翻译

“请翻译”,就是我们在计算机中装一个翻译软件,跟有道词典这种翻译工具类似。区别是,有道词典翻译给我们自己,python翻译器翻译给计算机。

请个python翻译很简单,如果你是windows(瘟到死)系统,戳此链接,就可以从官方下载到一个安装包,双击就可以安装了。

如果不是windows系统,恭喜你,你的系统已经默认安装python了。

跟计算机打个招呼

记得自己在幼儿园时,看到其他小朋友玩得不亦乐乎,非常想跟他们一起玩耍,却因生性羞怯,扭捏着不好意思向前。很多时候,我拒怕新东西,拒绝探索这个世界。但真当我们迈出了第一步,世界在我们心中的印象就更加清晰了。

打招呼,虽然是交往的一小步,却是我们人生的一大步。

计算机刚诞生的时候,它是个庞然大物。跟这个怪物打招呼,可不是件容易的事。

但世界在发展,现今已有各种各样的计算机语言,沟通变得前所未有的简单。

就我们使用的python语言来说,与计算机沟通只需要简单两步就可以了。

  1. 安装一个翻译器。如果你是windows系统,下载链接已在上面给出,如果你已经下载并安装,恭喜你第一步已经完成了;非windows用户可以直接跳过这一步。

  2. 唤醒这个翻译器。这一步也非常简单。对于windows系统,点击开始 -> 运行,输入cmd并键入回车,这时系统会打开一个神秘的黑色窗口;如果是其它系统的用户,找到一个叫做终端的软件打开,也是一个黑色窗口。然后,在黑色窗口里,输入python并键入回车,如果出现下面的文字,表明已经成功唤醒我们的python翻译器了。

1
2
3
4
Python 2.7.13 (default, Dec 17 2016, 23:03:43)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

这一坨东西我们不用理会,只要确保不是Bad command or file name或者是带有error字眼的语句,就表明我们已启动成功了。

失败了怎么办?可以搜索一下或者给我发邮件,我会对你负责的!

现在输入一个"hello"看会发生什么。

1
2
3
>>> "hello"
'hello'
>>>

我们输入了一个"hello",它又回给了我们一个'hello'

这样无聊的结果也真是令人感动,完全没有一波三折的快感,跟琐碎的生活一样枯燥。

无聊的背后有什么有意思的东西

太他妈没劲了。

非也。

我们刚才跟计算机打了个招呼,神奇的是,他听懂了,并回应了我们。而无聊的是,我们给他什么,他就回给我们什么。

我们看到了>>>这个符号,它的意思是,“跟我说点什么吧,我在听着呢”。多忠诚!

我们输入的hello两边有一对"号,这表明我们在说一句话,而不是要计算机帮我们做个算数题。

那现在我们可以让他帮我们做算数题吗?当然可以!

学习简单算术

刚才我们给计算机一句话,他又把这句话回复给了我们。有点无聊。

下面我们来做点更有意义的事,让计算机帮我们做个算数题。

我女朋友帮我举了个例子:我们需要一种元器件956包,每包10000个,每个0.0016元,那么总共需要多少钱呢?

好便宜啊!嗯,我觉得是个好例子,python已经开始辅助我们工作了。

在我的印象里,10以内的加减乘除运算是最开始接触的算术题,部分甚至可以借用手脚辅助完成。说到乘除法,小九九还算简单,更像是语言,靠记忆。但是100以内的乘除法,对我来说已经有相当的难度了。

我记忆还算不错,对于加减乘除,当初还有一句口决,叫做先乘除后加减,如果先加减怎么办呢,用括弧()

我们可算是非常幸运的,在甚至还不明白为什么要学这种鸟玩意的很多年前,就已经掌握了算数的基本原则。python里面的简单算术,甚至都不需要我们再学一遍了。

现在,我们只需要告诉python翻译器元器件总价格的计算公式,python就可以翻译给计算机做运算了。我们来试一下:

1
2
3
>>> 956 * 10000 * 0.0016
15296.0
>>>

哇噻,我们的计算机计算非常迅速,一下子就帮我们算出了答案。果真是人如其名,这是一只战斗鸡。

记得以前,我参加珠心算那会儿,试题里有很大一部分,是多个多位数字求和,做得多了很容易出现一种自我怀疑:好像有一位记错了?不过对计算机来说,只要我们输入的正确,可以完全相信它的计算结果。我们负责精确地表达,它负责精确地执行。

上面虽然只有乘法,但+ - x ÷聪明的我们已无师自通了(其实多年前,我们就已经掌握了)。需要注意的是,计算机语言多用*来代表x,而用/来代表÷

举个例子,(0.31 + 0.43) * ((0.26 + 0.45 - 0.31) / 0.47),看明白了这个公式计算的是什么,我就不用再叨叨了。

唠唠python(1) -- 开学典礼

为谁而写

有一天,我女朋友跟我说,你帮我处理一个电子表格吧。

最开始,我做了一个vba(一种计算机语言)脚本,觉得不行。因为使用起来太过繁琐,这可能会让她崩溃,也可能会让我在回答各种问题的过程中崩溃。

之后又写了一个python(另一门我们将要详细讨论的计算机语言)脚本,还是不行。要使用这个脚本,需要学会安装python这个软件,然后安装一大堆额外的东西。这也太他妈不方便了。我是不会把这么一个鸟东西给出去的。

后来我想到了最佳的解决方案:让她学习一点计算机语言。“一点”以足以应对这种简单繁琐的操作。但是我找到的资料都不是很理想,很少有面向非计算机专业的。

这些文章就是为这类人群准备的,我们(请允许我角色带入)没有系统地学习过计算机方面的知识,而又在日常生活工作中经常用到计算机,我们试图通过与计算机更有效地沟通,来提高自己的工作效率。但是报个班又太不值,毕竟班里大部分同学当初是奔着程序员梦进去的。

简而言之,这一系列文章是为非计算机专业而又意识到计算机的重要性,想要快速与计算机建立高效沟通以提高工作效率的人准备的。

与其它同类文章有什么不一样

在网上已有非常非常多的《python从入门到出家》类的文章或教程。

他们有的打着“简单”、“易学”的愰子,随便翻一下,里面充斥着“条件语句”、“函数”、“异常”等看上去屌炸天的词汇,全然不顾我们的感受。

他们并没有站到我们的角度来思考问题。现阶段,我们并不想知道“异常”是个什么东西,而只想尽快让计算机帮我们计算出这批元器件缺少的数量,然后去补货。

这些词汇和程序员式的思考方式,严重阻碍了我们的学习过程,损耗我们的注意力。很可能有那么一天,在我们尝到与计算机高效交互的甜头前,终于忍受不了各种纠缠在一起的专业名词,而选择了结束这个恼人的过程。然后留下一种感觉,“程序员都他妈是神经病”。

当然,这篇文章只是提供另一种学习python的体验,而上面所说的这种情况也只是一种假设。如果你愿意听一个人每天唠叨几句(有可能只是十分、二十分钟),自己同时又能有所收获,以至最后竟然能流畅地与计算机沟通,那你就可以继续往下看了。

这里没有乱七八糟的词汇,我希望自己能以一个中年大妈唠家常的姿态给大家讲述一下与隔避老王沟通的技巧。所以你也不用有什么负担。

我是中年大妈,不要有压力

为什么是python语言

计算机语言,说白了,就是我们与计算机沟通的工具。比如,我们跟邻居沟通用汉语,而跟美国人沟通用英语。我们与计算机沟通,用的是计算机和我们都可以听得懂的语言。

计算机就像一个语言天才,它精通多种语言。不幸的是,没有一种是我们人类的语言。也就是说,要想与计算机流畅地沟通,除了学习它使用的语言,我们别无他法。

计算机语言有很多种,比如A语言、B语言、C语言等。甚至我们可以创造一门我们自己的语言来教会计算机,然后用这门语言与它沟通。正如我们的祖先创造了汉语,并让它普及于世一样。

既然计算机能使用这么多语言,我们想要与它沟通,自然最好是选择一门学习起来相对容易的语言。python语言就具有这样的特质,它真正的简单易学,而且学习曲线可以非常平缓。也就是说,我们完全可以一边享受它给我们带来的切实好处,一边进一步的学习以更好地与计算机沟通。

我能得到什么

想像一下,如果你学会了一门外语,就可以流畅地与老外沟通交流,还可以更方便地在国外打到车。节省了你的时间和精力,你可以多喝几杯茶了。

这些文章里没有语法结构、俚语俗语,当然并不是说它们不重要,你可能以后会感兴趣。这里更多的是教你在异国他乡(计算机的世界),更好的打到车,更快地找到饭店,或者是雇佣一个保姆帮你打扫卫生。

你可以用你的想象力去工作,把自己从繁琐的工作中解放出来吧。 – 这是我承诺给你的,学不会不收费。

简单了解python语言

终于讲到我们的python语言了,这篇文章只是开个头,我们只要有一点印象就可以了。

就像前面提到的:“我们可以创造一门我们自己的语言来教会计算机,然后用这门语言与它沟通。”python语言就是这样诞生的,作者创造了它,并教会了计算机使用这门语言。

关于python的介绍其实就这么多,下一篇文章我们就可以用这门语言跟计算机进行简单的沟通了。是的,计算机语言就是这么容易使用。

“安静”的三mămă

我的三mămă

有一次回老家过年,听到门外狗叫。我探出头去,第一次看到三mămă。面无表情,行走缓慢。

那时刚好年尾,仿佛有做不完的活。炸年货,打扫卫生,blahblah一大堆。

她还没走到屋来,我娘说,她是你三mămă。平时不怎么说话,顶多挤出一个“嗯”字。我们要炸东西,你跟她聊一会。

进屋后,她一言不发。我当时找了一句话(忘记说的啥了),她果然回答了我,用了一个小心翼翼的“嗯”字。

我猜想可能是三mămă大脑的某一处没有发育完善。

我的内心是崩溃的,当时想跟她说一句,“你有毛病啊”。但是碍于她辈份在那,我自然不能将我的这股子劲表现给她。

我的同事

有一次,我看到一个同事。我就跟个傻逼似的直勾勾盯着他看,一言不发。可能是看得他发毛了,就对我点了个头,“嗯”。

而就在那一刻,我产生了一种似曾相识的感觉。

我突然醒悟,其实我恰好也是这样的一个“有毛病”的人。为了展现友好(而并非发自内心),就冲着同事傻呵呵的笑,却更显局促。

而这次我有了一个明显的优势,我不再像上次那样隔了辈份,而终于可以理直气壮的指着自己的鼻子说:“你有毛病啊!”

她就是放大了的我

是的,三mămă让我看到了自己的某一面,而她恰是我那一面的极致。

有时候我们混在人群里,可能都忘记了自己是怎么一回事。而恰好有些纯粹的人(也可能是先天原因),让我们重新认识到了那部分不易觉察的自己。

遇见三mămă让我感觉很幸运,却为我们的个性日渐模糊而感到悲凉。

一方面,我看到了做到极致的好处,不管极致的好或是极致的坏,当被用来做参考时,都是不用费太多脑力的。

另一方面,我们身体或者心灵的某处,可能会因各种原因而被深埋。感受它,接受它的好与坏,就变得很重要。

我决定,要认真的与自己相处。你有多好,你有多坏,你都是我的一部分,我始终爱你。所以,不要因害怕而隐藏自己。

撞残的飞机

昨晚做了一个梦,买了一架小型私人飞机,然后在屋外试飞,云里雾里,怡然自得。结果在降落的时候撞到了院里的墙壁,把飞机屁股撞烂了一块。而后又试飞了一次,结果在降落的时候又撞到了墙壁,这次屁股都给撞冒了烟,感觉到当时心里难受极了。

为什么要把这些没头脑的破梦记录下来

梦到底是什么呢?它其实是我们潜意识的表现。说到潜意识就有趣了,在晴天白日,它就像是潜入水下的怪物,我们很难察觉。而梦很妙,在梦里,这些怪物们会浮出水面,变换一种形式出现在我们面前。

对,变换一种形式,所以它要告诉我们的,并非显而易见的。所以,就有了周公解梦。

记得小时候,过年我们买了一个日历,一日一页,每页一个周公解梦。那时,我每做一个梦,都要去翻找对应的那一页,看看这个梦到底是什么意思。结果最后把日历翻得破烂不堪。这是我对梦的一个很早的记忆。

如何通过梦找到另一个更真实的自己

梦的意义,就是帮我们找到那个潜藏的、不易觉察的自己。它更真实,因为它是我们身体放松状态下的感受,受到的压力更小,所以更容易舒展自己。

它在帮我们找到更真实的自己。这听起来太棒了,我们自己就会引导自己找到更真实的自己。

但是实现起来却没那么容易,它需要练习,如何练习呢?

首先,我觉得《周公解梦》有时是靠谱的,但有时是不靠谱。“有时不靠谱”就意味着它不靠谱。虽然听起来有点让人沮丧,但还好,我们可以参考一下,毕竟还有我们自己把关一下。

然后,我认为心理学对解梦很重要,同时它又是我们了解自己的另一种途径。这觉得这就是科学的好处,让不够清晰明确的概念慢慢形成体系框架,使得后来人可以通过在前人的基础上进一步完善,科学得以继续往前发展。人类终于通过自己的方法,即科学,实现了跨越时间的,前辈与后辈的合作。

这个梦到底意味着什么呢

回到我这个梦,对我来说到底意味着什么呢?

我利用网络,查看了梦的解释,五花八门,什么大难临头,什么胜利凯旋,什么人际关系转好。这叫人怎么信,又怎么能安抚我那不平静的心。

我在梦里有一种事物被破坏的感觉,自己心爱的东西被自己毁坏了,有一种说不出的难受。

飞机对我来说,是一个“挑战”的意象。

于是,我回想起了这个阶段做的事情,最近在做一个编辑器插件,用来辅助之前开发的一个系统。开发用的语言是自己之前没怎么用过的,语法结构、常用库啥的都得学习。这么想来,我是很担心这个项目会失败的。但因平日忙工作,可能这个担心自己并没有很清楚的意识到,而在梦里,另一个自己告诉我,我其实挺担心这个项目会被我搞砸的,尤其是别人没做过的东西。其实是担心搞一个新的方向的失败,它个梦就是现实的心理状态的一个投射。

所以这个挑战的意象,我觉得更像是挑战自己的内心,而非现实的处境。

写到这里的时候,我感到了幸运。毕竟是在做自己之前未尝试过的东西。失败其实并不可怕,我们又做了一个方面的尝试。

Git之对象数据库

数据库,顾名思义,即存储数据的仓库。

我们的Git是一个关系型对象数据库,怎么理解呢,它主要管理对象及对象之间的关系。而对象间的关系,组成了一个图结构。

图结构

我们先来看一下Git里对象的关系是怎样的。如下图。

git-objects.png

这是我用git-show-objects工具生成的某个Git仓库的对象关系。

矩形框(包括折角矩形框)即我们要研究的对象,而椭圆形是我们的指针。下面我们来分别看一下Git里的对象和指针。

对象

Git中的对象主要分两大类:不可变对象可变对象

不可变意味着,如果对象的某个域要发生变化,我们会创建一个新的对象,而不是修改原来的对象。

这就有几个很有意思的事情:

  1. 频繁创建对象会占用大量磁盘,但它会带来更好的灵活性和可跟踪性
  2. 不可变的对象更安全,可以共享使用,这在一定程度上又节省了磁盘

对于可变对象,由于其域可变,故我们是决不可能用它来保存历史的,但是保存临时的或一次性的数据则非常理想。

不可变对象

Git的图结构主要是由不可变对象组成的,Blob、Tree和Commit是我们接触最多的三类不可变对象。

Blob

Blob对象用来保存我们项目文件的内容,对应上图中的折角矩形。

有一点比较关键,Blob对象只保存文件内容。这就意味着,如果我们有两个不同的文件,而其内容竟然一致,好了,我们只会生成一个Blob对象。

Tree

Tree对象用来保存我们项目目录的内容,对应上图中的蓝文字矩形。

跟Blob对象一样,如果我们有hello1/dir和hello2/dir两个目录,而两个目录的内容竟然递归相同,那我们的两个dir只需要一个Tree对象就可以了。

Tree对象内保存着一个列表,它的每一项,都是一个文件名+Blob对象目录名+另一个Tree对象(子目录)。

Commit

Commit对象用来保存我们的提交动作,对应上图中的橘红色矩形。

Commit对象里保存的信息比Blob和Tree都要多,因为它已经是我们经常访问到的对象了。

Commit对象里有我们想知道的作者提交时间 信息,它还保存着此次提交的父提交。当然,父提交有可能是两个,三个或百八十个,只要你喜欢。

可变对象

Git中的可变对象最典型的就是Index对象,它是一个全局对象,或称其为单例对象。

Index对象维护着当前Git对应的文件及状态,是我们操作Git的入口。它维护一个列表,每一项包含了文件的mode对应的Blob文件对应路径和一些Git自己使用的标记。

指针

上面提到保存着父提交保存着对应的Blob,那这些是以何种类型保存到对象的域的呢?

答案是哈希值

我们知道,在计算机中,一个对象是有一个内存地址对应的,而Git的对象,用的是对象的哈希值。即,Git计算某个对象的哈希值,使用此值作为文件的路径,并将对象的内容序列化后存储到该路径。

实际上,Git将其要维护的对象统一存放在项目根目录的.git/objects/位置,并以对象哈希值的前两个字符作目录名,剩余字符作文件名,生成对象目录。

我们之前说,Index对象是我们操作Git的入口。指针,即是我们访问对象的入口。

Git中的指针直接或间接指向Commit对象,分为常量指针和变量指针。它们对应上图中的椭圆形标记。

变量指针

随着我们对Git的操作,变量指针的指向有可能发生变化。

Head、Remote

变量指针就像我们的书签,标记着我们当前看到了哪一页。

最典型的变量指针是Head(Remote),也即是我们常说的分支。如上图中的heads/master,它对应我们本地的master分支。

HEAD是一个特殊的指针,跟Index相似,它有且只有一个,顺着它指的方向,我们总可以找到一个Commit。

这里要注意,HEAD正常情况下是指向Head的,但上图中它直接指向了某个Commit,这就是Git里面的游离态(detached)。

常量指针

常量指针是一旦创建,就很少发生变化的指针。注意,是很少,并非没有。

Tag

Tag是常量指针的典型,它主要充当我们的标记笔,考试画重点必备。

例如,我们可以用它来标记一个稳定的发行版本对应的Commit,以供伙伴们检出或下载。

常用操作

git init

初始化仓库,主要是初始化.git/目录,创建Index对象、HEAD指针,以准备接下来的工作。

init.png

git add

创建Blob对象,并将对应文件添加到Index对象。

add.png

git commit

递归创建Tree对象,创建Commit对象,并保存根目录对应的Tree对象。更新HEAD指向的指针的指向。

commit.png

问题

此时,一个简单的提交就完成了。当然,这连一个开始都够不上。

如果这三个命令你都理解了,不仿实操一下以下几个问题:

  1. fast-forware是如何操作的?
  2. 上面提到过detached,它有什么问题,应该如何避免?
  3. 根据Git的实现原理,如何设计系统可以更好的利用磁盘空间?

其实第三个问题恰是我们设计简洁系统的一个原则。

参考

根本停不下来?可以看一下maryrosecook写的《git from the inside out》,如果看英文费劲也可看一下我的粗陋翻译《彻底理解git》。

自己创建一个测试仓库,使用git-show-objects工具,边做边观察一下发生了什么。

为什么我不使用JetBrains的屌炸天编辑器

首先解释一下,JetBrains并没有出过一款叫做“屌炸天”的编辑器。

作为一个提到编辑器圣战内心就无比激动的码农,我使用过JetBrains的大部分产品,从开始的PhpStorm,到PyCharm、Intellij IDEA、CLION、android studio,这些产品我都有摸过。

JetBrains生产的编辑器无疑是非常贴心的,代码补全、智能提醒、强大的重构功能,等等一大坨超级特性曾经让我爱不释手。

说到曾经,为什么是曾经爱不释手呢?

有一段时间,我的主要工作集中在脚本开发上。这让我第一次意识到了这种大型IDE的笨重。

后来,我开发一个基于django的系统,最初使用的是vim + 自已找的一大批插件。系统开发完后,我想起了被遗忘在角落的PyCharm。这时,我打算重新拾起这个屌炸天的编辑器。

此时,我已经是vim的重度用户了。为了延续vim那妙不可言的触感,我在PyCharm里安装了IdeaVim。不过用了没多久,就感觉哪里不对劲起来。

好了,BB了这么多,以下才是文章内容。

为什么我不使用JetBrains的屌炸天编辑器?

真的很棒

JetBrains的编辑器真的很棒,界面非常漂亮,而且非常智能,就像你编码时有一个专家在你身边一样。

如果是初学者,你值得拥有。

启动慢

启动真的非常非常慢。

emacs对此有理:别看我启动慢,但我一天只启动一次,启动一次在里面宅一天。

但是你JetBrains不行啊,尤其是对于运维开发的同学,很多时候是跟脚本打交道,而且要跨机器,JetBrains做不到。

我不习惯把一个笨重的软件放那里放一天,除非8个小时中我要在里面呆6个小时。

编辑体验不够流畅

有的人可以做到,主动关闭自己的听觉,这时他们就真的听不到了。

如果你做不到,你要想想,敲个字符它就给你跳个小灯泡,还主动问你要不要来杯咖啡是个什么意思。

我以前一直觉得vim的界面可真够简陋的,给我显示个文件夹图标吧,或者让我在编辑器里起个bash玩?

搞飞机!编辑器是用来编辑的,NERDTree还帮我们实现了一些文件浏览的功能,还不知足!

我以前有一种想法,一定要让编辑器最节省按键。所以搞了一套非常神奇的一字码快捷键的代码片断来自动补全。

但是当我思考编辑器想要给我什么的时候,我还是被自己吓了一跳。

编辑器帮我把我头脑中的想法通过指尖表达出来,并纠正校对。从这个角度讲,如果为了省个按键,把if定义成了i,那么在之后的时间里,我们的思维势必会被这个i扭成一团。流畅地表达想法很重要,最好是一气哈成。

JetBrains的界面真的是太棒了,但是感觉自己游在里面,注意力都被目的之外的东西分散了。

然而还是得看习惯

如果你是一个已脱离智能提示这种高级趣味的码农,如果你已有足够的经验来判断是非,还是建议你多用用朴实无华的编辑器(绝不包括notepad)。

当然,还是一个习惯问题,我的老大就在用JetBrains的产品,我有很多优秀的同事也在用。

这不是选举,你也不必投票。

所以JetBrains产的编辑器真的非常棒

闲暇时,我还是会打开PyCharm,欣赏一下这惊艳的UI,然后关掉它,想想生活真是很美好!

16年逝,17年始

屎屎屎,都是屎。。。

一年又转一年,感觉白驹过隙的,是否又废了这365天,过成了一个老爷爷老太太的模样?

关键字:读书

16年的关键字该是读书,虽然量不大,但还是开了个好头。也多亏自己这浮躁的嫉妒心被《微信读书》抓个正着。

认知:钱到底是什么

16年,自己的认知发生了很大的变化,特别是对钱的认识上。

之前晚上转火车都不舍得花钱住店。

16年去过几次海底捞,终于明白海底捞对我意味着什么了。

钱是等价交换物,是一把衡量价值的尺子。

对个人来说,比钱更珍贵的东西,我现在找到了这么几样:时间、精力、好心情。

16年第一次在得到上,狠下心订阅了400块的专栏。其实,没过几个星期,我就知道,花出去的钱已经变换成更重要的知识回赠回来了。

这几样比钱更重要的东西,成了我在kindle花几百块买电子书的理由:随着互联网的开放,我们当然可以找到大部分资源,但是找资源的过程中,我们有可能会失去比金钱更重要的东西,时间,精力。

关于“老好人”

年底最大的收获是,下定了决心,不再做一个虚假的“老好人”。

转头一看,却也已经带着这个面具欢快的生活了二三十年。“老好人”并非一条不归路,但走地越久,越像是一个干瘪的僵师,倒更像是老人家说的,离坟墓越来越近。

不要为难自己,做更真实的自己。