Go for Pythonistas Go and the Zen of Python 禅
Go for Pythonistas
https://talks.golang.org/2013/go4python.slide#1
Things I don't like about Python (it'll be short)
Beautiful and simple
Dynamic typing - nice because it's concise, like Python.
- a = "hello"
- b = 1
- # but also
- a = 2
Static typing - can be verbose, like Java or C++.
- Foo foo = new Foo();
Static typing with inferred types, like Go.
- a := "hello"
- b := 1
- // but no
- a = 2
Statically-typed Python? Check mypy and Cython.
Run time pyrotechnics
- name = 'pythonista'
- # This code only works half of the time.
- if random.random() > 0.5:
- print 'hey '+name+', you win!'
- else:
- print 'sorry '+nane+', you lose'
I don't want start a flame war here but ...
100% code coverage is a symptom
- Code coverage should point you to untested cases.
- Not a way to find typos!
- 100% code coverage doesn't mean bug free.
Other things I don't like
- Deploying - managing dependencies.
- Performance - "not too slow" is often not fast enough.
- Magic! (e.g.:
__magic__
:**kargs
,__getattr__
)
A list of magic methods in Python:
www.rafekettler.com/magicmethods.html
And I *do* like concurrency!
A lot has been said about Python's infamous Global Interpreter Lock.
You should watch Mindblowing Python GIL, by David Beazley.
Things I like about Python
Things I like about Python
- The Zen of Python. (Go and the Zen of Python)
- Hashes and arrays are part of the language.
- The standard library.
- Magic! A bit of code can do a lot.
A bit of code
fib.py
Have you ever heard of Fibonacci?
- def fib(n):
- a, b = 0, 1
- for i in range(n):
- a, b = b, a + b
- return b
- def fib_rec(n):
- if n <= 1:
- return 1
- else:
- return fib_rec(n-1) + fib_rec(n-2)
- for x in range(10):
- print fib(x), fib_rec(x)
fib.go
Something familiar?
- func fib(n int) int {
- a, b := 0, 1
- for i := 0; i < n; i++ {
- a, b = b, a+b
- }
- return b
- }
- func fibRec(n int) int {
- if n <= 1 {
- return 1
- }
- return fibRec(n-1) + fibRec(n-2)
- }
- func main() {
- for i := 0; i < 10; i++ {
- fmt.Println(fib(i), fibRec(i))
- }
- }
Fibonacci without generators? What?
Python generators are awesome.
- def fib(n):
- a, b = 0, 1
- for i in range(n):
- a, b = b, a + b
- yield a
Mechanically complex.
- f = fib(10)
- try:
- while True:
- print f.next()
- except StopIteration:
- print 'done'
But very easy to use.
- for x in fib(10):
- print x
- print 'done'
Python generators
Note the generator executes concurrently. Hmm... I like concurrency.
Go concurrency
Based on goroutines and channels.
- Goroutines: very light processing actors (the gophers).
- Channels: typed, synchronized, thread-safe pipes (the arrows).
"Generator" goroutines
"Generator" goroutines
Uses a channel send instead of yield
.
- func fib(c chan int, n int) {
- a, b := 0, 1
- for i := 0; i < n; i++ {
- a, b = b, a+b
- c <- a
- }
- close(c)
- }
- func main() {
- c := make(chan int)
- go fib(c, 10)
- for x := range c {
- fmt.Println(x)
- }
- }
"Generator" goroutines
A more generator-like style:
- func fib(n int) chan int {
- c := make(chan int)
- go func() {
- a, b := 0, 1
- for i := 0; i < n; i++ {
- a, b = b, a+b
- c <- a
- }
- close(c)
- }()
- return c
- }
- func main() {
- for x := range fib(10) {
- fmt.Println(x)
- }
- }
Exercise: generating prime numbers
Write a function that returns a channel and sends the first n prime numbers on
it.
Given the function prime
:
- // prime returns true if n is a prime number.
- func prime(n int) bool {
- for i := 2; i < n; i++ {
- if n%i == 0 {
- return false
- }
- }
- return true
- }
Use the Go playground:
Solution: generating prime numbers
- func primes(n int) chan int {
- c := make(chan int)
- go func() {
- for i := 1; n > 0; i++ {
- if prime(i) {
- c <- i
- n--
- }
- }
- close(c)
- }()
- return c
- }
- func main() {
- for p := range primes(10) {
- fmt.Println(p)
- }
- }
Exercise: Fibonacci primes
Write a filterPrimes
function that takes a channel of ints as a
parameter and returns another channel of ints.
All the prime numbers that filterPrimes
receives from the input channel are
sent into the output channel.
Complete this code snippet:
Solution: Fibonacci primes
- func filterPrimes(cin chan int) chan int {
- cout := make(chan int)
- go func() {
- for v := range cin {
- if prime(v) {
- cout <- v
- }
- }
- close(cout)
- }()
- return cout
- }
- func main() {
- for p := range filterPrimes(fib(20)) {
- fmt.Println(p)
- }
- }
But there's much more
Goroutines and channels aren't just for generators. They can be used to model
all kinds of concurrent systems.
To learn more:
- Concurrency patterns, by Rob Pike
- Advanced Concurrency Patterns, by Sameer Ajmani
Object-oriented Go
Object-oriented Go
A type declaration.
- type Name struct {
- First string
- Middle string
- Last string
- }
A method declaration.
- func (n Name) String() string {
- return fmt.Sprintf("%s %c. %s", n.First, n.Middle[0], strings.ToUpper(n.Last))
- }
Constructing a Name
and using it.
- n := Name{"William", "Mike", "Smith"}
- fmt.Printf("%s", n.String())
Methods on anything
There's more to types than structs.
- type SimpleName string
You can define methods on any type.
- func (s SimpleName) String() string { return string(s) }
Or almost any type.
- func (s string) NoWay()
You can only define methods on types within the same package.
Duck typing
Duck typing
If it walks like a duck ...
What defines a duck?
- Is there an explicit list of "duck" features?
- What if the duck is not exactly a duck?
s/duck/file-like object/g
Go interfaces
Simply a set of methods.
From the fmt
package:
- type Stringer interface {
- String() string
- }
fmt.Println
calls the String method if the parameter is a Stringer
.
- n = Name{"William", "Mike", "Smith"}
- fmt.Println(n)
A type with all the methods of the interface implements the interface.
Implicit satisfaction == No "implements"
Structural typing: it doesn't just sound like a duck, it is a duck.
And that's checked at compile time.
Decorators
Decorators
A convenient way to wrap a function.
- def auth_required(myfunc):
- def checkuser(self):
- user = parse_qs(urlparse(self.path).query).get('user')
- if user:
- self.user = user[0]
- myfunc(self)
- else:
- self.wfile.write('unknown user')
- return checkuser
A function can be decorated using @
.
- class myHandler(BaseHTTPRequestHandler):
- @auth_required
- def do_GET(self):
- self.wfile.write('Hello, %s!' % self.user)
Decorators
If we run it.
- try:
- server = HTTPServer(('', PORT_NUMBER), myHandler)
- server.serve_forever()
- except KeyboardInterrupt:
- server.socket.close()
This is unauthorized:
This is authorized:
Decorators in Go?
Not exactly, but close enough.
Go doesn't provide decorators in the language, but its function literal syntax and simple scoping rules make it easy to do something similar.
- var hiHandler = authRequired(
- func(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintf(w, "Hi, %v", r.FormValue("user"))
- },
- )
A wrapper function.
- func authRequired(f http.HandlerFunc) http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) {
- if r.FormValue("user") == "" {
- http.Error(w, "unknown user", http.StatusForbidden)
- return
- }
- f(w, r)
- }
- }
Decorators in Go?
- func main() {
- http.HandleFunc("/hi", hiHandler)
- http.ListenAndServe(":8080", nil)
- }
This is unauthorized:
This is authorized:
Exercise: errors in HTTP handlers
In Go, functions can return errors to indicate that something bad happened.
The net/http
package from the standard library defines the type HandlerFunc
.
- type HandlerFunc func(ResponseWriter, *Request)
But it's often useful to unify the error handling into a single function to avoid
repetition.
- type errorHandler func(http.ResponseWriter, *http.Request) error
Write a decorator that given a errorHandler
returns a http.HandlerFunc
.
If an error occurs it logs it and returns an http error page.
Exercise: errors in HTTP handlers (continuation)
Given the function handler
.
- func handler(w http.ResponseWriter, r *http.Request) error {
- name := r.FormValue("name")
- if name == "" {
- return fmt.Errorf("empty name")
- }
- fmt.Fprintln(w, "Hi,", name)
- return nil
- }
We want to use it as follows.
- http.HandleFunc("/hi", handleError(handler))
Implement handleError
using the playground.
Solution: errors in HTTP handlers
- func handleError(f errorHandler) http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) {
- err := f(w, r)
- if err != nil {
- log.Printf("%v", err)
- http.Error(w, "Oops!", http.StatusInternalServerError)
- }
- }
- }
- // Fake request without 'name' parameter.
- r := &http.Request{}
- w := newDummyResp()
- handleError(handler)(w, r)
- fmt.Println("resp a:", w)
- // Fake request with 'name' parameter 'john'.
- r.Form["name"] = []string{"john"}
- w = newDummyResp()
- handleError(handler)(w, r)
- fmt.Println("resp b:", w)
Monkey patching
Monkey patching
"A monkey patch is a way to extend or modify the run-time code of dynamic languages without altering the original source code." - Wikipedia
Monkey patching
Also known as "duck punching" ... poor duck.
Often used for testing purposes.
For example, say we want to test this function:
- def say_hi(usr):
- if auth(usr):
- print 'Hi, %s' % usr
- else:
- print 'unknown user %s' % usr
Which depends on a function that makes an HTTP request:
- def auth(usr):
- try:
- r = urllib.urlopen(auth_url + '/' + usr)
- return r.getcode() == 200
- except:
- return False
Monkey patching
We can test say_hi
without making HTTP requests by stubbing out auth
:
- def sayhitest():
- # Test authenticated user
- globals()['auth'] = lambda x: True
- say_hi('John')
- # Test unauthenticated user
- globals()['auth'] = lambda x: False
- say_hi('John')
Gopher punching!
The same effect can be achieved in Go.
- func sayHi(user string) {
- if !auth(user) {
- fmt.Printf("unknown user %v\n", user)
- return
- }
- fmt.Printf("Hi, %v\n", user)
- }
Which depends on
- var auth = func(user string) bool {
- res, err := http.Get(authURL + "/" + user)
- return err == nil && res.StatusCode == http.StatusOK
- }
Gopher punching!
Our test code can change the value of auth easily.
- func TestSayHi() {
- auth = func(string) bool { return true }
- sayHi("John")
- auth = func(string) bool { return false }
- sayHi("John")
- }
Conclusion
Go is a bit like Python
- simple
- flexible
- fun
but a bit different too
- fast
- concurrent
- statically typed
Disclaimer :
- "No pythons, ducks, monkeys or gophers were harmed while writing this talk"
Try it
Next steps
Learn Go from your browser
The community: golang-nuts
groups.google.com/d/forum/golang-nuts
Go and the Zen of Python
https://talks.golang.org/2012/zen.slide#1
Go for Pythonistas Go and the Zen of Python 禅的更多相关文章
- Zen of Python
Zen of Python $ python Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:01:18) [MSC v.1900 32 bit ...
- funny_python 00 The Zen of Python
# 打算每天多动的时候尽量搜索一些和coding相关的funny stuff Day 00 - PEP 20 The Zen of Python 在shell里面输入python -m this 回车 ...
- python之禅 the zen of python
>>> import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is ...
- Python import this : The Zen of Python
>>> import thisThe Zen of Python, by Tim Peters Beautiful is better than ugly.Explicit is b ...
- Python彩蛋--zen of python
今天早上在公交上浏览博客的时候,发现了python里面的一个小彩蛋--zen of python 一首python之歌 我们来看一看... 是不是很简单,在python shell 里 输入 im ...
- Zen of Python(Python的19条哲学)
The Zen of Python Beautiful is better than ugly. Explicit is better than implicit. Simple is better ...
- 趣闻|Python之禅(The Zen of Python)
在Python解释器中输入“import this”会发生什么?如果你不知道这个彩蛋,推荐继续阅读这篇文章. 2001年秋,Foretec(一家会议组织公司)正在准备召开第十届Internationa ...
- Python的设计哲学--zen of Python
Python的设计哲学--zen of Python Beautiful is better than ugly. 优美胜于丑陋 Explicit is better than ...
- Import This - The Zen of Python
The Zen of Python -- by Tim Peters Beautiful is better than ugly.Explicit is better than implicit.Si ...
随机推荐
- 推荐使用并手写实现redux-actions原理
@ 目录 一.前言 二.介绍 2.1 创建action 2.2 reducer 2.3 触发action 三. 认识与手写createAction() 3.1 用法 3.2 原理实现 四.认识hand ...
- device_create为何可以在/sys/class/具体类/属性文件?怎么实现的
答案: 版本3.6.9: device_create -> device_register -> device_add -> device_add_attrs -> devic ...
- Java学习日报7.22
//3.2 逆向输出三位整数! 7.22 package 三个和尚比身高1; import java.util.Scanner; public class Demo1{ @SuppressW ...
- 编写高质量JAVA代码之让接口的职责保持单一
上述标题读者朋友应该也注意到了是让接口的职责保持单一,而不是实现者单一. 设计模式六大原则之单一原则: 定义 不要存在多于一个导致类变更的原因.**通俗的说,即一个类只负责一项职责. 下面以一个电话模 ...
- python实例:解决经典扑克牌游戏 -- 四张牌凑24点 (二)
Hey! 如果你还没有看这篇的上文的话,可以去稍稍瞅一眼,会帮助加速理解这一篇里面涉及到的递归结构哦!(上一篇点这里:<python实例:解决经典扑克牌游戏 -- 四张牌凑24点 (一)> ...
- Linux下nginx反向代理负载均衡几种方式以及配置
下面以ip地址192.168.1.1 和192.168.1.2举例 1.轮询 (1).轮询:每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除. upstream ...
- 七、Elasticsearch+elasticsearch-head的安装+Kibana环境搭建+ik分词器安装
一.安装JDK1.8 二.安装ES 三个节点:master.slave01.slave02 1.这里下载的是elasticsearch-6.3.1.rpm版本包 https://www.elastic ...
- SparkSql自定义数据源之读取的实现
一.sparksql读取数据源的过程 1.spark目前支持读取jdbc,hive,text,orc等类型的数据,如果要想支持hbase或者其他数据源,就必须自定义 2.读取过程 (1)sparksq ...
- [ABP教程]第一章 创建服务端
Web应用程序开发教程 - 第一章: 创建服务端 关于本教程 在本系列教程中, 你将构建一个名为 Acme.BookStore 的用于管理书籍及其作者列表的基于ABP的应用程序. 它是使用以下技术开发 ...
- Spark推荐系统实践
推荐系统是根据用户的行为.兴趣等特征,将用户感兴趣的信息.产品等推荐给用户的系统,它的出现主要是为了解决信息过载和用户无明确需求的问题,根据划分标准的不同,又分很多种类别: 根据目标用户的不同,可划分 ...