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

  • 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:

golang.org/s/go4py-ex1

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:

golang.org/s/go4py-ex2

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:

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:

localhost:8080/hi

This is authorized:

localhost:8080/hi?user=john

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:

localhost:8080/hi

This is authorized:

localhost:8080/hi?user=john

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.

golang.org/s/go4py-ex3

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

golang.org

Learn Go from your browser

tour.golang.org

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 禅的更多相关文章

  1. 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 ...

  2. funny_python 00 The Zen of Python

    # 打算每天多动的时候尽量搜索一些和coding相关的funny stuff Day 00 - PEP 20 The Zen of Python 在shell里面输入python -m this 回车 ...

  3. python之禅 the zen of python

    >>> import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is ...

  4. Python import this : The Zen of Python

    >>> import thisThe Zen of Python, by Tim Peters Beautiful is better than ugly.Explicit is b ...

  5. Python彩蛋--zen of python

    今天早上在公交上浏览博客的时候,发现了python里面的一个小彩蛋--zen of python 一首python之歌 我们来看一看... ​ 是不是很简单,在python shell 里 输入 im ...

  6. Zen of Python(Python的19条哲学)

    The Zen of Python Beautiful is better than ugly. Explicit is better than implicit. Simple is better ...

  7. 趣闻|Python之禅(The Zen of Python)

    在Python解释器中输入“import this”会发生什么?如果你不知道这个彩蛋,推荐继续阅读这篇文章. 2001年秋,Foretec(一家会议组织公司)正在准备召开第十届Internationa ...

  8. Python的设计哲学--zen of Python

               Python的设计哲学--zen of Python Beautiful is better than ugly. 优美胜于丑陋 Explicit is better than ...

  9. Import This - The Zen of Python

    The Zen of Python -- by Tim Peters Beautiful is better than ugly.Explicit is better than implicit.Si ...

随机推荐

  1. 将notepad++关联到右键菜单

    Step1: 新建txt文本, 将以下内容复制到文本中: Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT*\Shell\NotePad+ ...

  2. [译] ConstraintLayout 可视化[Design]编辑器(这到底是什么)[第四部分]

    原文地址:Testing Views in Isolation with Espresso 原文作者:Ataul Munim 译文出自:掘金翻译计划 译者:yazhi1992 校对者:lovexiao ...

  3. C# 9 新特性——init only setter

    C# 9 新特性--init only setter Intro C# 9 中新支持了 init 关键字,这是一个特殊的 setter,用来指定只能在对象初始化的时候进行赋值,另外支持构造器简化的写法 ...

  4. css 自定义悬浮窗写法

    HTML: css(sass): 复制代码 .info { } &:hover::after { content: attr(data-title); display: inline-bloc ...

  5. Java学习日报8.6

    <构建之法:现代软件工程>读后感 比起一般的教学类书籍,这本书更像是一本传记小说,作者邹欣以自己或者说一些典型的软件工程师为例子,详细介绍了一个软件工程师的工作内容,全书给我的感觉就是以一 ...

  6. netty服务端客户端启动流程分析

    服务端启动流程 我们回顾前面讲解的netty启动流程,服务端这边有两个EventLoopGroup,一个专门用来处理连接,一个用来处理后续的io事件 服务端启动还是跟nio一样,绑定端口进行监听,我们 ...

  7. Solon rpc 之 SocketD 协议 - 消息加密模式

    Solon rpc 之 SocketD 协议系列 Solon rpc 之 SocketD 协议 - 概述 Solon rpc 之 SocketD 协议 - 消息上报模式 Solon rpc 之 Soc ...

  8. 【C++】《C++ Primer 》第十三章

    第十三章 拷贝控制 定义一个类时,需要显式或隐式地指定在此类型地对象拷贝.移动.赋值和销毁时做什么. 一个类通过定义五种特殊的成员函数来控制这些操作.即拷贝构造函数(copy constructor) ...

  9. 【Web】CSS实现鼠标悬停实现显示与隐藏 特效

    鼠标悬停实现显示与隐藏特效 简单记录 - 慕课网 Web前端 步骤四:鼠标悬停实现显示与隐藏特效 初步掌握定位的基本使用,以及CSS选择器更高级的运用,完成一个网页中必会的鼠标经过隐藏显示特效. 实现 ...

  10. 【Java】计算机软件、博客的重要性、编程语言介绍和发展史

    之前学得不踏实,重新复习一遍,打扎实基础中. 记录 Java核心技术-宋红康_2019版 & Java零基础学习-秦疆 文章目录 软件开发介绍 软件开发 什么是计算机? 硬件及冯诺依曼结构 计 ...