Skip to content

Latest commit

 

History

History
1053 lines (786 loc) · 14.5 KB

2019-01-23-go-vs-python.md

File metadata and controls

1053 lines (786 loc) · 14.5 KB

Go vs Python comparison

| python | golang | vs | comparison |

It's not my writings and it's just a copy of Go vs. Python by Peter Bengtsson (see References below)

References


Hello World

Go

package main

import "fmt"

func main() {
	fmt.Println("Hello world")
}

Python

print("Hello world")

Print

Go

package main

import "fmt"

func main() {
	fmt.Println("Some string")
	fmt.Print("Some string")
	fmt.Printf("Name: %s, Age: %d\n", "Peter", 35)
}

Python

print("Some string")
print("Some string", end="")  # no newline character printed
print("Name: {}, Age: {}".format("Peter", 35))

Comments

Go

package main

// This is a general comment

/* This is also a comment
   but on multiple lines.
*/

/* This is the multi-line comment for the function main().
   To get access to this from the command line, run:

     godoc comments.go

*/

func main() {
}

Python

"""This is a doc string for the whole module"""

# This is a inline comment


class Class(object):
    """This is the doc string for the class"""


print(__doc__)
print(Class.__doc__)

Multiline Strings

Go

package main

import "fmt"

func main() {
	fmt.Println(`This is
a multi-line string.
`)
	fmt.Println(
		"O'word " +
			"Another \"word\" " +
			"Last word.")
}

Python

print(
    """This is
a multi-line string.
"""
)
print("O'word " 'Another "word" ' "Last word.")

Lists

Go

package main

import "fmt"

func main() {
	// initialized array
	var numbers [5]int // becomes [0, 0, 0, 0, 0]
	// change one of them
	numbers[2] = 100
	// create a new slice from an array
	some_numbers := numbers[1:3]
	fmt.Println(some_numbers) // [0, 100]
	// length of it
	fmt.Println(len(numbers))

	// initialize a slice
	var scores []float64
	scores = append(scores, 1.1) // recreate to append
	scores[0] = 2.2              // change your mind
	fmt.Println(scores)          // prints [2.2]

	// when you don't know for sure how much you're going
	// to put in it, one way is to
	var things [100]string
	things[0] = "Peter"
	things[1] = "Anders"
	fmt.Println(len(things)) // 100
}

Python

# initialize list
numbers = [0] * 5
# change one of them
numbers[2] = 100
some_numbers = numbers[1:3]
print(some_numbers)  # [0, 100]
# length of it
print(len(numbers))  # 5

# initialize another
scores = []
scores.append(1.1)
scores[0] = 2.2
print(scores)  # [2.2]

Maps

Go

//You can make a map of maps with:
elements : make(map[string]map[string]int)
elements["H"] = map[string]int{
    "protons": 1,
    "neutrons": 0,
}
//But note, this is what you have struct for.

package main

import "fmt"

func main() {
	elements := make(map[string]int)
	elements["H"] = 1
	fmt.Println(elements["H"])

	// remove by key
	elements["O"] = 8
	delete(elements, "O")

	// only do something with a element if it's in the map
	if number, ok := elements["O"]; ok {
		fmt.Println(number) // won't be printed
	}
	if number, ok := elements["H"]; ok {
		fmt.Println(number) // 1
	}

}

Python

elements = {}
elements["H"] = 1
print(elements["H"])  # 1

# remove by key
elements["O"] = 8
elements.pop("O")

# do something depending on the being there
if "O" in elements:
    print(elements["O"])
if "H" in elements:
    print(elements["H"])

Booleans

Go

x := 1
if x != 0 {
    fmt.Println("Yes")
}
var y []string
if len(y) != 0 {
    fmt.Println("this won't be printed")
}

Python

x = 1
if x:
    print "Yes"
y = []
if y:
    print "this won't be printed"

Go

package main

import "fmt"

func main() {
	fmt.Println(true && false) // false
	fmt.Println(true || false) // true
	fmt.Println(!true)         // false

	x := 1
	if x != 0 {
		fmt.Println("Yes")
	}
	var y []string
	if len(y) != 0 {
		fmt.Println("this won't be printed")
	}

}

Python

print(True and False)  # False
print(True or False)  # True
print(not True)  # False

Forloop

package main

import "fmt"

func main() {
	i := 1
	for i <= 10 {
		fmt.Println(i)
		i += 1
	}

	// same thing more but more convenient
	for i := 1; i <= 10; i++ {
		fmt.Println(i)
	}
}

Python

i = 1
while i <= 10:
    print(i)
    i += 1

# ...or...

for i in range(1, 11):
    print(i)

Range

Go

package main

import "fmt"

func main() {
	names := []string{
		"Peter",
		"Anders",
		"Bengt",
	}
	/* This will print

	1. Peter
	2. Anders
	3. Bengt
	*/
	for i, name := range names {
		fmt.Printf("%d. %s\n", i+1, name)
	}
}

Python

names = ["Peter", "Anders", "Bengt"]
for i, name in enumerate(names):
    print("{}. {}".format(i + 1, name))

Switch

Go

package main

import (
	"fmt"
	"strconv"
)

func str2int(s string) int {
	i, err := strconv.Atoi(s)
	if err != nil {
		panic("Not a number")
	}
	return i
}

func main() {
	var number_string string
	fmt.Scanln(&number_string)
	number := str2int(number_string)

	switch number {
	case 8:
		fmt.Println("Oxygen")
	case 1:
		fmt.Println("Hydrogen")
	case 2:
		fmt.Println("Helium")
	case 11:
		fmt.Println("Sodium")
	default:
		fmt.Printf("I have no idea what %d is\n", number)
	}

	// Alternative solution

	fmt.Scanln(&number_string)
	db := map[int]string{
		1:  "Hydrogen",
		2:  "Helium",
		8:  "Oxygen",
		11: "Sodium",
	}
	number = str2int(number_string)
	if name, exists := db[number]; exists {
		fmt.Println(name)
	} else {
		fmt.Printf("I have no idea what %d is\n", number)
	}

}

Python

def input_():
    return int(input())


number = input_()
if number == 8:
    print("Oxygen")
elif number == 1:
    print("Hydrogen")
elif number == 2:
    print("Helium")
elif number == 11:
    print("Sodium")
else:
    print("I have no idea what %d is" % number)


# Alternative solution
number = input_()
db = {1: "Hydrogen", 2: "Helium", 8: "Oxygen", 11: "Sodium"}
print(db.get(number, "I have no idea what %d is" % number))

Variadic Functions

package main

import "fmt"

func average(numbers ...float64) float64 {
	total := 0.0
	for _, number := range numbers {
		total += number
	}
	return total / float64(len(numbers))
}

func main() {
	fmt.Println(average(1, 2, 3, 4)) // 2.5
}

Python

def average(*numbers):
    return sum(numbers) / len(numbers)

print(average(1, 2, 3, 4))  # 10/4 = 2.5

Time Elapsed

Go

package main

import "fmt"
import "time"

func main() {
	t0 := time.Now()
	elapsed := time.Since(t0)
	fmt.Printf("Took %s", elapsed)
}

Python

import time

t0 = time.time()
time.sleep(3.5)  # for example
t1 = time.time()
print("Took {:.2f} seconds".format(t1 - t0))

Closure Functions

Go

package main

import "fmt"

func main() {

	number := 0

	/* It has to be a local variable like this.
	   You can't do `func increment(amount int) {` */
	increment := func(amount int) {
		number += amount
	}
	increment(1)
	increment(2)

	fmt.Println(number) // 3

}

Python

def run():
    def increment(amount):
        return number + amount

    number = 0
    number = increment(1)
    number = increment(2)
    print(number)  # 3


run()

Defer

Go

package main

import (
	"os"
)

func main() {
	f, _ := os.Open("defer.py")
	defer f.Close()
	// you can now read from this
	// `f` thing and it'll be closed later

}

Python

f = open("defer.py")
try:
    f.read()
finally:
    f.close()

Panic Recover

Go

package main

import "fmt"

func main() {

	// Running this will print out:
	//    error was: Shit!
	defer func() {
		fmt.Println("error was:", recover())
	}()
	panic("Shit!")
}

Python

try:
    raise Exception("Shit")
except Exception as e:
    print("error was:", e)

Mutables

Go

package main

import (
	"fmt"
	"strings"
)

func upone_list(thing []string, index int) {
	thing[index] = strings.ToUpper(thing[index])
}

func upone_map(thing map[string]string, index string) {
	thing[index] = strings.ToUpper(thing[index])
}

func main() {
	// mutable
	list := []string{"a", "b", "c"}
	upone_list(list, 1)
	fmt.Println(list) // [a B c]

	// mutable
	dict := map[string]string{
		"a": "anders",
		"b": "bengt",
	}
	upone_map(dict, "b")
	fmt.Println(dict) // map[a:anders b:BENGT]
}

Python

def upone(mutable, index):
    mutable[index] = mutable[index].upper()


list_ = ["a", "b", "c"]
upone(list_, 1)
print(list_)  # ['a', 'B', 'c']

dict_ = {"a": "anders", "b": "bengt"}
upone(dict_, "b")
print(dict_)  # {'a': 'anders', 'b': 'BENGT'}

Structs

Go

package main

import (
	"fmt"
	"math"
)

type Point struct {
	x float64
	y float64
}

func distance(point1 Point, point2 Point) float64 {
	return math.Sqrt(point1.x*point2.x + point1.y*point2.y)
}

// Since structs get automatically copied,
// it's better to pass it as pointer.
func distance_better(point1 *Point, point2 *Point) float64 {
	return math.Sqrt(point1.x*point2.x + point1.y*point2.y)
}

func main() {
	p1 := Point{1, 3}
	p2 := Point{2, 4}
	fmt.Println(distance(p1, p2))          // 3.7416573867739413
	fmt.Println(distance_better(&p1, &p2)) // 3.7416573867739413
}

Python

from math import sqrt


class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y


def distance(point1, point2):
    return sqrt(point1.x * point2.x + point1.y * point2.y)


p1 = Point(1, 3)
p2 = Point(2, 4)
print(distance(p1, p2))  # 3.74165738677

Methods

Go

package main

import (
	"fmt"
	"math"
)

type Point struct {
	x float64
	y float64
}

func (this Point) distance(other Point) float64 {
	return math.Sqrt(this.x*other.x + this.y*other.y)
}

// Dince structs get automatically copied,
// it's better to pass it as pointer.
func (this *Point) distance_better(other *Point) float64 {
	return math.Sqrt(this.x*other.x + this.y*other.y)
}

func main() {
	p1 := Point{1, 3}
	p2 := Point{2, 4}
	fmt.Println(p1.distance(p2))         // 3.7416573867739413
	fmt.Println(p1.distance_better(&p2)) // 3.7416573867739413
}

Python

from math import sqrt


class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def distance(self, other):
        return sqrt(self.x * other.x + self.y * other.y)


p1 = Point(1, 3)
p2 = Point(2, 4)
print(p1.distance(p2))  # 3.74165738677
print(p2.distance(p1))  # 3.74165738677

Goroutines

Go

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"sync"
)

func f(url string) {
	response, err := http.Get(url)
	if err != nil {
		panic(err)
	}
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		panic(err)
	}

	fmt.Println(len(body))
}

// See the example in https://golang.org/pkg/sync/#WaitGroup
func main() {
	var wg sync.WaitGroup
	urls := []string{
		"https://www.peterbe.com",
		"https://python.org",
		"https://golang.org",
	}
	for _, url := range urls {
		wg.Add(1)
		go func(url string) {
			defer wg.Done()
			f(url)
		}(url)
	}
	// Wait for the goroutines to finish
	wg.Wait()
}

Python

import urllib2
import multiprocessing


def f(url):
    req = urllib2.urlopen(url)
    try:
        print(len(req.read()))
    finally:
        req.close()


urls = ("https://www.peterbe.com", "https://python.org", "https://golang.org")


if __name__ == "__main__":
    p = multiprocessing.Pool(3)
    p.map(f, urls)

Args

Go

package main

import (
	"fmt"
	"os"
	"strings"
)

func transform(args []string) {
	for _, arg := range args {
		fmt.Println(strings.ToUpper(arg))
	}

}
func main() {
	args := os.Args[1:]
	transform(args)
}

Python

import sys


def transform(*args):
    for arg in args:
        print(arg.upper())


if __name__ == "__main__":
    transform(*sys.argv[1:])

Import Alias

Go

import (
    pb "github.com/golang/groupcache/groupcachepb"
)
// or
import (
    _ "image/png"  // You can also import packages that you won't actually use
)

// or 
package main

import (
	"fmt"
	s "strings"
)

func main() {
	fmt.Println(s.ToUpper("world"))
}

Python

import string as s

print(s.upper("world"))

Sprintf

Go

package main

import "fmt"

func main() {
	max := 10
	panic(fmt.Sprintf("The max. number is %d", max))
}

Python

max = 10
raise Exception(f"The max. number is {max}")

Uniqify

Go

package main

import "fmt"

func uniqify(items []string) []string {
	uniq := make([]string, 0)
	seen := make(map[string]bool)

	// For the highest memory efficiency, do:
	// seen := make(map[string]struct{})
	// see: https://stackoverflow.com/questions/37320287/maptstruct-and-maptbool-in-golang

	for _, i := range items {
		if _, exists := seen[i]; !exists {
			uniq = append(uniq, i)
			seen[i] = true
		}
	}

	return uniq
}

func main() {
	items := []string{"B", "B", "E", "Q", "Q", "Q"}
	items = uniqify(items)
	fmt.Println(items) // prints [B E Q]
}

Python

def uniqify(seq):
    seen = {}
    unique = []
    for item in seq:
        if item not in seen:
            seen[item] = 1
            unique.append(item)
    return unique


items = ["B", "B", "E", "Q", "Q", "Q"]
print(uniqify(items))  # prints ['B', 'E', 'Q']

Dotdict

Go

package main

import "fmt"

func main() {
	names := []string{"peter", "anders", "bengt", "bengtsson"}
	initials := make(map[string]int)
	for _, name := range names {
		initial := string(name[0])
		initials[initial]++
	}
	fmt.Println(initials)
	// outputs
	// map[p:1 a:1 b:2]
}

Python

initials = {}
for name in ("peter", "anders", "bengt", "bengtsson"):
    initial = name[0]
    # if initial not in initials:
    #     initials[initial] = 0
    initials.setdefault(initial, 0)
    initials[initial] += 1

print(initials)
# outputs
# {'a': 1, 'p': 1, 'b': 2}