按 ‘ on my mind ’ 分类归档

程序员入伙书——函数初步

以前的几个章节里,大家一定常见到print(…)、range(…)、max(…)之类的结构,它们是什么呢?

它们叫函数。不用管这个名字听起来多么奇怪,和数学上的函数、方程的概念多么不同,先接受这个名字,后面我会说这个名字的来历。

比如说,我们在《程序在干什么?》一节的最后一段举过一个求平方根的例子,后来在《初涉算法》一节讲解过它。就拿这个程序为例,如果现在我想求(根号2 + 根号3) x (根号5 – 根号7),该怎么写程序?

当然我们可以把这个例子复制粘贴四遍,第一遍求根号2,第二遍求根号3,第三遍求根号5,第四遍求根号七,然后用这四个中间结果算出最后的值。

这个思路能干活,可就是直觉太傻太啰嗦。四段程序只有喂给它们的数字的差别,实在是太浪费了。所以人们想,可以引入数学上的函数y = f(x)概念,定义好这个函数的公式(f)之后,把参数(x)喂给它,让同一段代码对参数进行运算,运算结果放在y里,这样岂不节约?

好主意!我们现在把求平方根的算法定义成一个函数:

>>> def mysqrt(n):
    high = max(1, n)
    low = 0
    while True:
        result = (high + low) / 2
        if abs(result * result - n)  < n * 1E-8:
            break
        if result * result > n:
            high = result
        else:
            low = result
    return result

>>>

这段程序里最关键的是第一行,以关键字def引导的函数名mysqrt,其后以括号包围要传递给这个函数的参数n,最后是冒号表示:以下的缩进内容是用来定义这个函数的算法。

最后一行return result也很重要,见到return语句时,程序就会返回到使用函数的那个位置,在相应的mysqrt(x)的地方,放上本次运行得到的result值。这个值被称为返回值

说得再多不如实际做一次:
猛击阅读全文

咽嘘呵吸嘻吹呼

话说长安浓雾不散,唐王遣使到翠屏山芭蕉洞,借扇扇风。铁扇公主沉吟道:“扇子但与你不妨,有一事若交代不周,须害了天使性命。”使者问是哪般,那罗刹女言:“我看贵界尘土弥天蔽地。这扇子平日只杏叶大小,倘要扇风,须先变大。朱雀大街上,凡人念起这变大的咒语啊,必先一口土呛杀,奈何?”

又一则:话说斗战胜佛闲来无事到红尘走走,忽见翠屏山芭蕉洞口,铁扇公主携那回家探亲的善财童子,戚戚哀哀呜呜咽咽。行者心惊,落下云头忙问缘故。那罗刹女哭云:“三天前唐皇遣人来借扇子,只说求雨借风。我想那扇子是传家至宝,着老牛押运,谁承想到了地头,老牛要把扇子变大,刚念半句口诀,一口土呛到丹田,筋脉尽断,至今人事不省。哇哇我的老牛啊,你撇下我孤儿寡母这可怎么办哪……”

如何把话说明白?

把话说明白,容易也不容易。

我曾经旁听过一个电话会议,这一头是技术人员,那一头不是,二十五分钟过去了,双方互相没听懂对方想要什么,眼看离会议结束还有五分钟,我只好出声,花五分钟把俩人搞定了。双方的英语和口音也许是造成沟通障碍的原因之一,但我认为一定不是主要原因。

我以前做过售前支持,长期的摸爬滚打中,不知不觉地形成了一套把话说明白的方法,这里总结一下,分享给大家看看。篇幅所限,这文章只谈怎么把话说清楚,而非“销售技巧”一类的煽情指南。

一、要人明白,必须自己先明白。

否则,就是“以己昏昏,使人昭昭”了。曾经有同事问我:如果一样东西,你自己不是很清楚,老板非要你出去讲给客户,怎么讲?我说:没法讲,非讲不可的话,我只讲我清楚的那部分,并在开头就诚恳地告诉客户,有些地方我是不明白的,希望得到他们的指点,如果大家都不明白,我会搜集他们的问题回去,日后一一作答。

二、自己明白之后,却要从不明白的人的角度来讲。

当一个人沉浸在话题内部时,听众就站在了他的对面,他和听众就有了对立的视野,他从里头向外看,听众从外往里瞧,不同的视角,使得他使用的话语、词汇,难以被听懂。

以上两点是最基本的原理,推论如下:

我不想把事情泛道德化,但我的观察是,说不明白话的人,一般相当自私。养心是很重要的,学会站在别人的角度去看去想。自己慷慨了,心胸宽了,不知不觉地,说话就好懂了。

尽量不使用只有自己明白的术语和行话,如果必须要用,就得用一两句话描述,这个术语在外行人眼里是干什么用的。

有时,不但要考虑别人的思路,也要考虑他们的身体条件,跟小孩和残疾人说话时,要想,依他们的身高,看到的世界是什么样?当说“前后左右”这些相对方位词时,要事先约定一个共同认知的参照物。当说“东西南北”前,要问自己:你的听众对这个城市熟悉吗?

说事情要学会分层说,先说主干,再说主干有几个分支,把同一层的各个分支全部点名后,才能向深处展开。记得时时提醒听众,现在的位置在哪儿。千万别在第一个分支就开始往话题深处扎猛子,过早地钻进小巷子,会让自己都迷路的。

和“这个东西是什么”同等重要的,是“这个东西不是什么”。和“这个东西能做什么”同样重要的,是“如果没有它,会出什么事”。

太艰深的预设条件、却和主线关系不大的,要及时对听众说:这个不需要了解太深,已经证明是成立的,知道结论就可以了。

暂不需要听众听懂的,要记得告诉他们:眼前不需要使劲听,后头我会再细讲。真的,听也是很耗力气的,不要磨到正题时,把听众的力气耗光了。

介绍精神层面的抽象概念时,要学会用物质世界的事物来类比。要分清楚大家的共识和自己的见解,不要挟带私货。

学会打比方很重要。很多人以为自己不会打比方,其实,当你真正了解一个事物时,你的大脑就不会使用文字来记录,而是使用画面或声音、生活里的瓶瓶罐罐、道路车马、柴米油盐来表述它。打比方,就是把这些瓶瓶罐罐描述给听众的过程,告诉你的听众,你的眼帘里浮现的是什么。

举个例子:

我的公司是向市场提供金融数据的。这些金融数据通过网络传进我们的处理器,把它们分类,使它们更有条理,再通过网络发布到各交易所、各银行去。因为网络和数据处理都是自动化的,所以我们需要计算机程序员。我们这座楼里有两种程序员:一种做网络,类似于修路的,让装载数据的卡车在上面跑。另一种,就是开车运数据的了。负责修路的人们不在乎头顶上的车运的是什么货,路不要断掉、路面别塌陷就成。开车的人也不在乎路面是石板的还是柏油的,只要装车的时候是一群猪,到货的时候别是一筐白菜就行。就是说,这两种程序员,一种保证数据能传进来送出去,另一种负责数据本身是合理正确的。

再举个例子:

面前的这件器物叫甗,念“演”。一眼看去,就会立刻注意到,这个细腰把它分成上下两部分。名字很难写很神秘,其实它就是个蒸锅,下面这个胖腿的部分叫做“鬲”(念“利”),负责烧开水,上面这个小圆锅叫“甑”(念“增”),如果可以拿回家,你就可以在甑里放小笼包子。平时咱们蒸包子还需要什么?要当心包子掉到烧开水的锅里去。古人也想到这点了,在这个细腰的地方有个铜箅子,蒸汽可以上来,包子不会掉下去。

为公司内刊写的电影推荐

in-time-movie-poster

时间规划局

这是一个虚构的社会,其中时时看到的,却是现实世界的影子。“时间就是生命”、“时间就是金钱”在这部电影里,完全是赤裸裸的事实。

但如果你以为这是部讲述人生道理的励志片,那就错了。试想,一个人无忧无虑地活到二十五岁,忽然在一天早晨醒来时,看到自己手臂上出现了一个还剩一年的倒计时,从此就要为了延续自己和家人的生命去打工,挣来的每分“工钱”都是分分秒秒的时间,喝杯咖啡要付四分钟,乘公交要刷掉两小时,房租要缴八天,连讲“价钱”都要度量一下,讲价花的时间到底值不值。这样的世界大概不会出现拖延症患者的。

影片里的世界有两个城区。一个城区,人们已经对横死街头的路人司空见惯,却时刻在体验家人离世之痛。当母亲无“钱”乘坐涨价了的公交车,在空荡荡的大街上一路狂奔后,和儿子手指相触的刹那,死在儿子的怀里——刚刚被别人赠予一百年生命的怀里时,那是何等的悲恸。在另一个城区里,庆生的礼物随意就是十年,赌场里的赌注,动辄是几百年的生命。“朱门酒肉臭,路有冻死骨”,恐怕是最精准的写照了。

还好,出现了从纸醉金迷当中厌离的智者,揭露这世界的种种不公的来源,把自己的生命悉数赠给了路见不平的好汉。他留给好汉的最后一句话,就是“Don’t waste my time”。一个贫民窟里杀出来的罗宾汉,再加上一个叛逆豪门的古惑女,把这荒唐的世界打了个天翻地覆。

感想和微量剧透:

  • 这虚拟的世界里,公务员真的很廉洁啊,虽然身份是“时间管理者”,他自己的“存款”却只有一天的生命。节俭一点的同僚,省吃俭用地好不容易攒了五年。
  • 穷人的一边,走路都一路小跑的。富人的天堂里,一切都是慢慢悠悠的。俺自己平时在公司里走路连跑带颠,莫非是天生的穷命?……囧
  • 把一百万年的积蓄放在了一个存折里,实在是太没有风险防范意识了。如果是俺这种天生穷命的,就会多买几个冰箱,再把屋子里全做上暗格。
  • 每个人的容颜都驻在二十五岁上,萍水相逢的男男女女,怎样避免不知不觉的乱伦呢?
  • 当时间成了生命的时候,排在你身后领“工钱”的、或者已经坐在公交车上、等你上车的乘客,就是你最大的敌人,他们的眼神就够杀了你的。
  • 统治的极致,是让大家忙着去谋生,没空去想为毛活得这么苦,难怪这片子,咱们不引进呢——谢绝喝茶。

一切都是“如梦如幻”的

form-emptiness

一个人,每到老师批评她的行为时,就滚刀肉地说“一切都是如梦如幻的,不要往心里去嘛。”

按:此人有个练门,总是肚子痛,一痛就打电话向老师求救,老师为她念《心经》就会转好。

老师就问她:既然一切都是如梦如幻的,你肚子痛时,为毛哎哟哎哟地打电话求救啊?

立刻语塞了。

见解是一回事,修证是另一回事。希阿荣博堪布在《寂静之道》里说

证悟空性与生起大悲心是同时的,生起大悲心与断除恶行是同时的。“一悟便休”,休的是妄想,不是菩萨的六度万行。真正悟道了,处世待人,和光同尘,见地比虚空高,但取舍因果比粉尘细。

程序员入伙书——数组

从前我用过的程序示例里面,使用的数据都是分离的、独立的。就是说,每个常量和变量,各有各的用途,没有“我们是一伙的”这样的共性。而在现实世界里,成群结队地出现的数据是大多数。例如一架飞机上的旅客,一个班级的学生,奥运会的参赛国。

我见过的所有编程语言都有数组(Array,List)的概念,用来存储具有共同属性的批量数据。在Python里,数组用一对中括号包围的一群数据来表示,数据之间用逗号隔开。例如:

>>> countries = ['China', 'USA', 'Germany', 'Canada', 'Japan']
>>> countries[0]
'China'
>>> countries[3]
'Canada'
>>> countries[4]
'Japan'
>>> 
💡 Python语言允许数组的每个元素类型不同,例如字符串和数字可以混装在同一个数组里面,如[3.14, ‘China’]就是一个正常的Python数组。其它的编程语言通常没有这么大度。在实际应用中,即使是Python,也很少遇到各元素类型不同的案例。

在这里,countries就是一个数组,它有五个元素(Element),每个元素都是一个字符串表示的国名。引用这些元素的时候,我们使用一个整数,来指明它在数组里的位置,这个整数叫做下标(Index)。和大家的习惯稍有差异的是,在Python里,当我们说“数组的第一个元素”时,我们用的下标是0,第二个元素的下标是1,第三个元素的下标是2,依此类推。所以上面的程序范例里面,countries[0]打印出来的是第一个国名China,第五个国名使用的下标是4。

如果你觉得这个规则挺怪异的,想一想这个问题:进入一座楼房,爬到一楼需要爬几层楼梯?爬到五楼需要爬几层楼梯?然后你就释然了,因为对于计算机来说,数组就像楼层,一楼就是它的第一个元素,其它的楼层都是相对于一楼的偏移量。英式英语里,一楼叫做Ground Floor,二楼叫做First Floor,三楼叫做Second Floor,这就是计算机式的思维。

C/C++、Python、Perl、Java、PHP等语言里,第一个元素都是用下标0来表示。FORTRAN、BASIC、PASCAL等语言里,第一个元素是用下标1来表示。这两种表示方法都是合理的,照顾不同人群的思维习惯。

在刚才这个数组里,使用countries[5]会看到什么?
猛击阅读全文

对黄灯禁行令的两次释法

1月5日,公安部释法称:即使驾驶员反应不及,只要看到黄灯能停,哪怕是停过线,冲到斑马线上停下来,也是不处罚的。

俺个人认为,这次释法,强调的是停车的诚意。不过像俺这样的渣反应,斑马线不是俺的正常发挥,路口正中间、甚至对面的斑马线才是俺的归宿。

1月6日,公安部又说,闯黄灯以教育为主暂不处罚

拍屁股立法的经典后续,就是扭扭捏捏不肯认错。

禁闯黄灯的随想

red-red-green

友情提示:从小长到大,只看到过“会闪的绿灯”和“会倒计时的绿灯”的童鞋们,不用往下读,北京这土得掉渣的地方,跟您没关系。

从昨天(2013年元旦)零时起,机动车闯黄灯会被扣六分。

规则是:当黄灯亮起时,如果车辆任何部位已经通过停车线,则可以继续通行。尚未越过停车线的,则不得越过停车线。

就此,黄灯和红灯几乎等同。微有差异者:绿灯到黄灯是无缝切换,所以从数学上来说,无论离线有多近,甚至无限接近零,行车有多慢,甚至无限接近静止,驾车者都无法预知,越线的一刹那会不会闯黄灯。排队等红翻绿的前三名自信心强些,依次递减。

如果我是司机,就不知道以后怎么开车了。每看到一个来历不明的绿灯就减速?龟速蹭到停车线前,看看还是绿的,咬牙一闭眼,跺一脚油门冲过去?

好好地开着车,离路口还有五米,忽然绿灯变黄,开过去?六分扣没了。急刹车?牛顿第二定律狞笑了一下:就算你车轮是方的,踩到底也会滑到路口正中间。

哦哦,再补充一点,急刹车前先要看一眼后视镜,如果是日韩系的,还可以对付,如果是欧系、大公共、大货车,一定要果断放弃六分,回家后烧柱高香,庆贺自己捡回一条狗命。

以上讨论的是前头没车的情况,万一是你前头的大货车看到黄灯呢?

保持车距啊……祈祷后车保持车距啊……系好安全带啊……交管部门很快会欣喜地发现,几十年没有解决的“素质问题”,一个禁黄令就搞定了。

再来看看禁黄令的初衷。以前,常见的路口四种状态:红灯停;绿灯行;黄灯减速停;黄灯加速冲。“禁闯黄灯”就是为了解决“黄灯加速冲”而设计的。而这个规则一出,路口的花样会更加繁多:红灯停;绿灯行;黄灯减速停;绿灯加速冲;绿灯急刹停;绿灯急刹追尾;绿灯走走停停,蹭到路口加速冲;冲到一半变黄灯,颤抖一下继续冲;黄灯急刹车熄火,停到路中间;黄灯急刹还是过线,骂一声;黄灯急刹车追尾;黄灯急刹急拐冲上人行道;黄灯急刹急拐翻车……请大家自行补全。

颈托、头盔、大号抱枕、大号毛绒玩具、充气娃娃、晕车药、安全气囊、保险杠、二手车的销量将大增,请关注相应产业的股市板块。日系纸板车业绩将全面跌入低谷,可果断清仓。(此条非投资参考,股市有风险,风险请自担。)

各家车载GPS导航系统看准商机,纷纷推出计算“现在离翻黄还剩几秒”的实时警报,邀请广大车友付费下载扩展包,或者到交管部门指定的供应商处,按成本价获取。(此条纯脑补。)

行人们,请在等绿灯时远离路口,保不齐会有急刹不住,选择往路边撞的。追尾时飞溅的玻璃渣和金属碎片也很危险。

不出半年,北京城的路面可能就没车了。一半儿,是十二分被罚光,没法上路;一半儿,是急刹车惨遭追尾,前赴后继地壮烈了。路面上跑的,只剩下不需要看灯的。交管部门可能会敲锣打鼓地开庆功会吧。

你好,2013!

新年快乐

程序员入伙书——轻松一下

一口气写了十几章,轻松一下。

读者老爷可能有点昏沉了,说,这么多章节了,怎么还没见到一个Windows程序呢?咱们就写一个。

在Python Shell里按Ctrl-N(或者点File菜单,选New Window),在弹出的编辑窗口里输入——或者拷贝-粘贴也行,反正今天是“轻松一下”:

import tkinter
root = tkinter.Tk()
root.geometry('240x180')
root.title('hello, world')
tkinter.Label(root, text = "hello, world").pack(fill="both", expand=1)
root.mainloop()

hello-world-tk

按Ctrl-S(或者点File菜单,选Save),随意起个名字,存好文件之后按F5。

怎么样,看到Windows版的hello, world了吧?虽然看起来十分傻,但既然能写hello, world,就能写别的,就能放按钮,就能画图表,就能放菜单,能写一切能想出来的东西。要紧的不在于界面是什么,而在于理解漂亮的外表背后发生的事情。况且,就连这个漂亮的外表本身,也是由灰头土脸的程序写成的。