Python 开发者在迁移到 Go 时需要知道哪些事
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 开发者在迁移到 Go 时需要知道哪些事相关的知识,希望对你有一定的参考价值。
参考技术A 这是一篇讲述将大块 Python/Cython 代码迁移到 Go 的长文章。如果你想了解整个事情的经过、背景等所有信息,请读下去。如果你只对 Python 开发者需要了解的事感兴趣,请下拉到早该知道的事板块。背景
我们在 Repustate 最大的技术成果就是实现了阿拉伯语情感分析。阿拉伯语是个难啃的硬骨头,因为阿拉伯语词汇的形式非常复杂。阿拉伯语的标记化(把一句话拆分成单个单词)也比英语要难得多,因为阿拉伯单词内部可能会包含空格(例如单词内部“aleph”的位置)。在不泄露机密的情况下,Repustate 利用支持向量机(SVM)来获取一个句子最可能的意思,并且以此来推断句子的情感。我们一共采用了22种模型(22个支持向量机),文档中的每个词都会被分析。也就是说,如果一个文档包含500个词,就会与支持向量机进行10000多次对比。
Python
Repustate 几乎完全是用 Python 搭建的,我们使用 Django 来搭建 API 接口和网站架构。因此,为了保持代码一致性,使用 Python 来实现所有阿拉伯语情感引擎才说得通。就原型设计和实现流程而言,Python 依然是一个很好的选择:表现能力优秀,又有强大的第三方库资源,等等。如果是服务于网页,它就是最佳选择。如果是稍低级别的运算,需要与哈希表(Python 中的字典)进行大量对比时,运行速度就会慢下来。我们一秒钟只能处理2到3个阿拉伯语单词,这种速度太慢了。相比之下,我们的英语情感引擎每秒能处理500个单词。
瓶颈
因此,我们启动了 Python 分析器,开始调查速度慢的原因。还记得上文提到我们有22个支持向量机,每个单词都会通过它们处理吗?原来这个过程是按顺序进行,而不是并行的。好了,第一个想法是换成类似分布式计算系统(map/reduce)的处理器。长话短说:Python 不适合用 map/reduce。当你需要并发性的时候,Python 并不能帮上忙。在 Pycon 2013大会中,Guido 谈到了 Tulip,他希望用来解决这个问题的一个新项目,但是还要过一段时间才能发布。可是,如果已经有了更好的选择,为什么还要苦等下去呢?
选择 Golang 还是回老家(Go Home)
在 Mozilla 的朋友告诉笔者,Mozilla 服务的日志架构大部分代码都已迁移到 Go,部分原因是 goroutines 超级便利。Go 是由谷歌员工开发的,设计之初就将并发需求列为一级理念,而不是像 Python 的众多解决方案一样在做事后补救。因此我们开始着手实现从 Python 到 Go 的迁移。
虽然 Go 代码还没实现大规模产出,得到的结果已经非常振奋人心。我们现在一秒钟能处理1000个文档,使用的内存大大减少,而且也不用再去调试和解决使用 Python 时会遇到的多进程/协程(gevent)/“为什么 Control-C 杀死了我的进程”等问题。
喜欢 Go 的原因
任何略懂编程语言的人(明白解释与编译、动态与静态区别)都会说:“哈,显然 Go 要快多了。”没错,我们是可以用 Java 重写所有内容,并且取得类似的效果,但是这并不是 Go 胜出的原因。你用 Go 写的代码似乎一出来是正确的。笔者也说不清楚,但是不知怎么的,一旦代码被编译(编译过程非常迅速),你就会感觉它能工作了(不只是运行不出错,而且还逻辑正确)。这听起来很含糊,但是它是真的。在冗余或无冗余方面,它跟 Python 相似,它把函数当做一级对象,因此函数编程很方便。而且毋庸置疑,goroutines 和 channels 会让你更加省心省力。静态类型还会带来极大的性能提升,以及更精确的内存分配控制,但是又不会损失太多表达性。
早该知道的事
除去溢美之词,跟 Go 打交道需要与 Python 完全不同的一套思维模式。以下列出的是笔者在迁移时做的一些笔记——都是在从 Python 迁移到 Go 时随机想到的一些东西:
没有内建的集合类型(需要使用 map,然后测试存在性)
由于没有集合类型,需要自己写代码来实现交集、并集等方法
无元组(tuple),必须自己写架构或使用切片(slice)(数组)
没有类似 getattr_() 的方法,因此需要不断检查存在性,而不能像在 Python 中那样设置缺省值:value = dict.get(“a_key”, “default_value”)
必须不断检查错误(至少需要显式忽略它们)
不能包含未使用的变量或包,因此有时候如果要测试一些简单问题,需要给代码添加注释
在 []byte 和 string 之间切换。正则表达 (regexp) 使用 []byte (可变)。这说得通,但是在一些变量之间来回切换还是很烦人
Python 更为宽松。你可以用超出范围的索引来索取字符串片段,也不会有什么问题,还可以提取负值片段,但是 Go 就不行
不能使用混合类型的数据结构。也许不合规定,但是有时候在 Python 可以使用混合字符串和列表的字典。在 Go 就不行,要么清理干净数据结构,要么自定义结构。感谢 Ralph Corderoy 向笔者展示了如何正确操作(用这个界面,卢克)
不能把元组或列表分解成分开的变量(如 x,y,x = [1,2,3])
驼峰字规则(UpperCamelCase)(如果一个包中的函数或结构首字母未大写,就不会暴露给其他包)。笔者更喜欢 Python 的小写加下划线格式(lower_case_with_underscores)
需要显式检查错误是否为 != nil,不像 Python 有很多类型可以用于布尔型检查(0,“”,None 都会被解读为“假”)
某些模块(如 crypto/md5)的文档不足,但是 IRC 上面的 go-nuts 非常棒,拥有特别好的支持
从数字到字符串的类型转换(int64 -> 字符串)跟[]byte -> 字符串(只用字符串([]byte))不同,需要用到 strconv
Go 的代码读起来更像是编程语言,而 Python写出来更像伪代码。Go 包含更多非数字字母字符,用 || 和 && 来表示“或”与“和”
写文件会有 File.Write([]byte) 和File.WriteString(string),这会让习惯了 Python
只有一种做事方法的开发者们有些不适应
字符串插入很麻烦,不得不经常使用 fmt.Sprintf
没有构造函数,常见的做法是创建 NewType() 函数,来返回你需要的结构
Else 或 else if 必须格式正确,else 得跟 if 从句的大括号在一行。这很奇怪。
根据函数内外位置,使用不同的赋值操作符,例如 = 和 :=
如果只想要类似dict.keys() 或dict.values()得到的键值或取值列表,或者通过
dict.items()得到的元祖列表,在 Go 里面是无法实现的,只能自行迭代 map,然后创建自己的列表
笔者习惯建立一个取值为函数的字典,并通过键值调用函数。你可以在 Go
里面这么做,但是所有的函数都得接受和返回同样的东西,也就是说,必须具备同样的方法签名
如果你是用 JSON, 而且是混合类型的 JSON,那么你还是自求多福吧。你得创建一个能够匹配你的 JSON 二进制大对象(blob)格式的个性化结构,然后解组(Unmarshall)原始 JSON 成为你的个性化架构的一个用例。比起在 Python 中的一句“obj = json.loads(json_blob)”要费更多功夫
这么折腾值得吗?
值,一百万个值,超值。速度的提升不容忽视。而且笔者认为这也是促使 Go 成为流行语言的重要原因。因此在招聘时,笔者认为把 Go 当成 Python 开发者的必备技能也很重要。
有经验的 Java SWT 程序员在迁移到 Swing 时应该注意哪些主要事项?
【中文标题】有经验的 Java SWT 程序员在迁移到 Swing 时应该注意哪些主要事项?【英文标题】:What are the main things that an experienced Java SWT programmer should be aware of when moving to Swing? 【发布时间】:2011-10-03 07:36:54 【问题描述】:可能遇到的主要差异是什么?应用程序设计有什么重大差异吗?线程模型?您构建 GUI 的方式是什么? Swing 中没有 SWT 的哪些功能?
【问题讨论】:
ibm.com/developerworks/grid/library/os-swingswt 和其他谷歌返回的网站 我的主要建议:不要尖叫太多。 SWT 在过去 10 年中有所改进,而 Swing 则没有。 【参考方案1】:从我在 Swing 和 SWT 之间的经验中得到的一些发现
Swing 的渲染速度有点慢(我的经验)并且使用更多的内存 原生外观可能只是部分(取决于选择的外观'n'feel) 大部分 Swing 组件都以某种方式实现了 MVC 模式(因此您不必自己进行数据绑定) 可以对组件进行子类化,当您必须更改某些组件的行为时使用它(因此经常使用) Swing 发送程序生成的事件(我讨厌这种行为;]) 在 Swing 中,您不必调用 (a)syncExec() 方法(您不必像在 SWT 中那样关心从哪个线程更新 GUI,但请务必阅读Swing threading policy (end of page) 和 Concurrency in Swing) Swing 真的很啰嗦(与 SWT 相比) 不再有 dispose() 方法;] Swing 在容器中具有标准布局管理器(请参阅 BorderLayout)并在基础上有 different layout managers(使用 MigLayout,它也适用于 Swing 和 SWT,没有竞争对手) 在创建组件实例时您不必知道您的父级,但您必须知道父级(容器)上的 .add(Component c) 方法 Swing 不依赖于平台(不再针对每个平台和 x32/x64 进行多重构建) Swing 有自己的错误(与其他技术一样,这是不可避免的)【讨论】:
Swing 组件不是线程安全的。所有的 GUI 更新都应该从 Event Dispatch Thread 完成。 只是补充一点,Swing 有更多的组件,并且比 SWT 更可定制(你可以制作更漂亮的 GUI)。 @Zemzela 这取决于意见,我相信(作为 SWT 和 Swing 程序员的经验)这两个 GUI 框架具有相同的表达可能性。但是在 SWT 中制作自己的组件有点困难是正确的(更多工作,更多代码),但在 SWT 中你不会经常这样做.. 这不是真的 1) Swing 的渲染有点慢(我的经验)并且使用更多的内存 == 错误的建议 2) Swing 不是单线程 UI,因为 SWT == 错误的建议, Swing 是唯一且唯一的单线程输出到 GUI 3) Swing 真的很啰嗦 == ???? 4) 不再有 dispose() == 错误建议,dispose finalize @mKordel 1) 内存蓝图比 SWT 高得多,可以证明,无论如何,渲染速度是我的看法(正如我所写的所有这些发现)2) 再次,我不知道如何正确地编写这个想法,但在 Swing 中,您不必调用display.syncExec(Runnable thread)
(或者我并不真正了解任何必要的用法)。我愿意接受任何更正确的描述 3) 意味着您必须编写比在 SWT 中更多的代码,因为 Swing 不使用位设置作为 SWT(SWT.CLOSE | SWT.OK | SWT.CANCEL 等)。 以上是关于Python 开发者在迁移到 Go 时需要知道哪些事的主要内容,如果未能解决你的问题,请参考以下文章
如何系统地学习 C++ 语言关于C++,有哪些你需要提前知道的知识?