[python] if else one line (3항 연산자)

python에서 if else 문을 한줄에 쓰는 법


흔히 우리가 사용하는 3항 연산자 
a>b ? a:b 
=> condition ? True_Code : False_Code

python에서 3항 연산자, 혹은 one line if-else은 아래와 같다

a if a>b else b
=> True_code if condition else False_code

[date] python 날짜 계산(d-day 계산)

Liberay

from datetime import date

date.days : return day (int)

Code

from datetime import date

end_date = input().split()
start_date = input().split()

end = date(int(end_date[2]), int(end_date[1]), int(end_date[0]))
start = date(int(start_date[2]), int(start_date[1]), int(start_date[0]))
resl = (end - start).days 

Ex)

input : 1 23 2018
              1 20 2018 

output : 3

Golang { Syntax int := 10 }

Golang Syntax _8


31. 셀렉트

package main
import "fmt"

func fibonacci(c, quit chan int) {
    var x, y int = 0, 1 
    for {
        select {
        case c <- x:
            x, y = y, x+y
        case <-quit:
            fmt.Println("quit")
            return
        }
    }
}

func main() {
    c := make(chan int)
    quit := make(chan int)
    go func() {
        for i := 0; i < 10; i++ {
            fmt.Println(<-c)
        }
        quit <- 0
    }()
    fibonacci(c, quit)
}
  • Go의 Select문은 고루틴이 다수의 통신 동작으로부터 수행 준비를 대기하게 해줌.
  • Select는 Case구문으로 받는 통신동작들 중 하나가 수행될 수 있을때 까지 대기함.
  • 다수의 채널이 동시에 준비되면 그 중 하나를 무작위로 선택함.

32. 셀렉트의 디폴트 케이스

package main
import (
    "fmt"
    "time"
)

func main() {
    tick := time.Tick(1e6)
    boom := time.After(5e8)
    for {
        select {
        case <-tick:
            fmt.Println("tick.")
        case <-boom:
            fmt.Println("BOOM!")
            return
        default:
            fmt.Println("    .")
            time.Sleep(5e7)
        }
    }
}
  • select의 default 케이스는 현재 준비가 완료된 케이스가 없을 때 수행된다.
  • 블록킹( 비동기적 ) 송/수신을 하고자 할때 default케이스를 사용할수 있다.

 

33. 연습문제

https://go-tour-kr.appspot.com/#69 참고

package main

import (
    "code.google.com/p/go-tour/tree"
	"fmt"
)

// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
	_walk(t, ch)
	close(ch)
	
}

func _walk(t *tree.Tree, ch chan int) {
	if t != nil {
		_walk(t.Left, ch)
		ch <- t.Value
		_walk(t.Right, ch)
	}
}

// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool {
	ch1 := make(chan int)
	ch2 := make(chan int)
	go Walk(t1, ch1)
	go Walk(t2, ch2)
	for i := range ch1 {
		if i != <- ch2 {
			return false
		}
	}
	return true	
}

func main() {
	//tree.New(2)
	ch := make(chan int)
	go Walk(tree.New(1), ch)
	for v := range ch {
		fmt.Print(v)
	}
	fmt.Println(Same(tree.New(1), tree.New(1)))
	fmt.Println(Same(tree.New(1), tree.New(2)))
}

 

Golang { Syntax int := 8 }

Golang Syntax _8


28. 고루틴

package main
import (
    "fmt"
    "time"
)

func say(s string) {
    for i := 0; i < 5; i++ {
        time.Sleep(1 * time.Millisecond)
        fmt.Println(s)
    }
}

func main() {
    go say("world")
    say("hello")
}
/**** Output ****
hello
world
world
hello
world
hello
hello
world
hello
****************/
  • Goroutines은 런타임중에 관리되는 경략 쓰레드이다.
  • go f(a, b, c)와같이 사용되며, 새로운 고루틴을 실행한다.
  • 고루틴은 동일한 주소공간에서 실행되므로, 공유되는 자원의 접근은 반드시 동기화되야한다.

 

29. 채널

채널은 채널 연산자 <-를 이용해 값을 주고 받을 수 있는, 타입이 존재하는 파이프이다.

package main
import "fmt"

func sum(a []int, c chan int) {
    sum := 0
    for _, v := range a {
        sum += v
    }
    c <- sum // send sum to c
}

func main() {
    a := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int)
    go sum(a[:len(a)/2], c)
    go sum(a[len(a)/2:], c)
    x, y := <-c, <-c // receive from c

    fmt.Println(x, y, x+y) // -5 17 12
}
  • ch <- v : v를 ch로 보낸다.
    v := <-ch : ch로부터 값을 받아서 v로 넘긴다.
  • 맵이나 슬라이스처럼, 채널은 사용되기 전에 생성 되어야한다.
    ch := make(chan int)
  • 송/수신은 상대편이 준비될때까지 대기한다.
  • 채널은 버퍼링될 수 있다. make에서 두번째 인자로 버퍼의 용량을 지정해 줌으로써 해당 버퍼만큼 버퍼링되는 채널을 생성할 수 있다.
    ch := make(chan int, 100)

    package main
    
    import "fmt"
    
    func main() {
        c := make(chan int, 2)
        c <- 1
        c <- 2
        fmt.Println(<-c)
        fmt.Println(<-c)
    }

    만약 버퍼를 1을 잡게 된다면 에러가 발생하게 된다.

 

30. Range와 Close

데이터 송신측은 더 이상 보낼 값이 없음을 알리기 위해 채널을 close할 수 있다.
수신자는 아래와 같은 수신 코드의 두번째 인자를 줌으로써 채널이 닫혓는지 테스트 할 수 있다.
v, ok := <- ch와 같이 사용하며, 만약 채널이 닫겨있다면 okfalse가 들어가게 된다.
또한 for i := range ch와 같은 반복문은 채널이 닫힐 때 까지 계속해서 값을 받는다.

package main
import (
    "fmt"
)

func fibonacci(n int, c chan int) {
    x, y := 0, 1
    for i := 0; i < n; i++ {
        c <- x
        x, y = y, x+y
    }
    close(c)
}

func main() {
    c := make(chan int, 10)
    go fibonacci(cap(c), c)
    for i := range c {
        fmt.Println(i)
    }
}
  • 주의할 점은 채널은 송신측만 닫을수 있으며, 수신측에선 닫을 수 없다.
  • 채널은 파일과 다르기에 항상 닫을 필요가 없으며,
    채널을 닫는 동작은 오로지 수신측에게 더이상 보낼값이 없다고 말해야 할 때만 행해지면 된다.

 

 

Golang { Syntax int := 7 }

Golang Syntax _7


24. 웹서버

package main
import (
    "fmt"
    "net/http"
)

type Hello struct{}

func (h Hello) ServeHTTP(
    w http.ResponseWriter,
    r *http.Request) {
    fmt.Fprint(w, "Hello!")
}

func main() {
    var h Hello
    http.ListenAndServe("localhost:4000", h)
}
  • Package http는 http.handler를 구현한 어떠한 값을 사용해 HTTP 요청을 제공한다.
  • Handler는 다음과 같은 인터페이스를 가진다.
    package http
    type Handler interface {
    	ServeHTTP(w ResponseWriter, r *Request)
    }

 

25. 연습문제

아래 나오는 타입을 구현하고 그 타입의 ServeHTTP 메소드를 정의하십시오. 그 메소드를 당신의 웹 서버에서 특정 경로를 처리할 수 있도록 등록하십시오.

type String string

type Struct struct {
    Greeting string
    Punct string
    Who string
}

예컨대, 당신은 아래와 같이 핸들러를 등록할 수 있어야 합니다.
http.Handle("/string", String("I'm a frayed knot."))
http.Handle("/struct", &Struct{"Hello", ":", "Gophers!"})

package main
import (
    "fmt"
    "net/http"
)

type String string

func (s String) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, s)
}

type Struct struct {
    Greeting string
    Punct string
    Who string
}

func (s *Struct) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, s.Greeting, s.Punct, s.Who)
}

func main(){
    http.Handle("/string", String("I'm silnex"))
    http.Handle("/struct", &Struct{"Hello",":","Gopher!"})
    http.ListenAndServe("localhost:4000", nil)
}

 

26. 이미지

package main
import (
    "fmt"
    "image"
)

func main() {
    m := image.NewRGBA(image.Rect(0, 0, 100, 100))
    fmt.Println(m.Bounds())
    fmt.Println(m.At(0, 0).RGBA())
}
  • Package Image는 아래와 같은 image인터페이스를 정의한다.
    package image
    
    type Image interface {
    	ColorModel() color.Model
    	Bounds() Rectangle
    	At(x, y int) color.Color
    }

 

27. 연습문제

이전의 연습에서 당신이 작성한 그림 생성기를 기억하십니까? 다른 생성기를 만들어봅시다.
하지만 이번에는 데이터의 슬라이스 대신에 image.Image 의 구현체를 반환할 것입니다.
당신 자신의 Image 타입을 정의하시고, 필수 함수들 을 구현하신 다음, pic.ShowImage 를 호출하십시오.
Bounds 는 image.Rect(0, 0, w, h) 와 같은 image.Rectangle 을 반환해야 합니다.
ColorModel 은 color.RGBAModel 을 반환해야 합니다.
At 은 하나의 컬러를 반환해야 합니다; 지난 그림 생성기에서 값 v 는 color.RGBA{v, v, 255, 255} 와 같습니다.

package main
import (
    "code.google.com/p/go-tour/pic"
    "image"
	"image/color"
)

type Image struct{
	w, h int
    colorA, colorB uint8
}


func (i *Image) ColorModel() color.Model{
    return color.RGBAModel
}

func (i *Image) Bounds() image.Rectangle {
    return image.Rect(0,0,i.w,i.h)
}

func (i *Image) At(x, y int) color.Color{
    return color.RGBA{uint8(x), uint8(y), i.colorB, i.colorA}
}

func main() {
    m := &Image{123,123,131,141}
    pic.ShowImage(m)
}

==== Output ====

Golang { Syntax int := 6 }

Golang Syntax _6


21. 메소드

package main
import (
    "fmt"
    "math"
)

type Vertex struct {
    X, Y float64
}

func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
    v := &Vertex{3, 4}
    fmt.Println(v.Abs())
}
  • Go에는 클래스가 없지만 메소드를 구조체(struct)에 붙일 수 있다.
  • 메소드 리시버(method receiver) func 키워드와 메소드 이름 사이에 인자로 들어간다.
    func 구조체이름(혹은포인터) 메소드_리시버_이름 반환타입이고 위 코드를 통해 예시를 들면,
    func (v *Vertex) Abs() float64: 구조체 VertexAbs()란 이름으로 호출 할 수 있다.
  • Go의 메소드는 구조체 뿐만아니라 모든 타입(type)에 붙일 수 있다.
    하지만, 다른 패키지에 있는 타입이나 기본 타입들에 메소드를 붙이는 것은 불가능하다.

    package main
    import (
        "fmt"
        "math"
    )
    
    type MyFloat float64
    
    func (f MyFloat) Abs() float64 {
        if f < 0 {
            return float64(-f)
        }
        return float64(f)
    }
    
    func main() {
        f := MyFloat(-math.Sqrt2)
        fmt.Println(f.Abs())
    }
    
  • 포인터 리시버는 메소드가 호출될때마다 값이 복사되는 것을막고, 메소드에서 리시버 포인터가 가르키는 값을 수정하기 위함이다.
    (함수에서 포인터를 전달하는것과 값을 전달하는 것에 차이를 생각하면 이해가 쉽다..)

    package main
    import (
        "fmt"
        "math"
    )
    
    type Vertex struct {
        X, Y float64
    }
    
    func (v *Vertex) Scale(f float64) {
        v.X = v.X * f
        v.Y = v.Y * f
    }
    
    func (v *Vertex) Abs() float64 {
        return math.Sqrt(v.X*v.X + v.Y*v.Y)
    }
    
    func main() {
        v := &Vertex{3, 4}
        v.Scale(5)
        fmt.Println(v, v.Abs()) // &{15 20} 25
    }
    

 

22. 인터페이스

package main
import (
    "fmt"
    "math"
)

type Abser interface {
    Abs() float64
}

func main() {
    var a Abser

    f := MyFloat(-math.Sqrt2)
    v := Vertex{3, 4}
    a = f  // a MyFloat implements Abser
    a = &v // a *Vertex implements Abser
    //a = v  // a Vertex, does NOT
    // implement Abser

    fmt.Println(a.Abs()) // 5
}

/****** MyFloat ******/
type MyFloat float64

func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}

/****** Vertex ******/
type Vertex struct {
    X, Y float64
}

func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
  • 인터페이스는 메소드의 집합으로 정의된다.
    인터페이스 안에 정의되어있는 모든 메소드가 구현되어있는 타입의 값은 모두 인터페이스 타입의 값이 될수 있다.
  • 인터페이스의 메소드가 이미 정의 되어있는 패키지 혹은 타입에 대해서 따로 명시적으로 표현할 필요가 없다.
    패키지 io에 Reader와 Writer가 정의되어 있기 때문에 따로 정의할 필요가없다.

    package main
    import (
        "fmt"
        "os"
    )
    
    type Reader interface {
        Read(b []byte) (n int, err error)
    }
    
    type Writer interface {
        Write(b []byte) (n int, err error)
    }
    
    type ReadWriter interface {
        Reader
        Writer
    }
    
    func main() {
        var w ReadWriter
        //var w Writer
    
        // os.Stdout implements Writer
        w = os.Stdout
    
        fmt.Fprintf(w, "hello, writer\n")
    }
    

 

22. 에러

package main
import (
    "fmt"
    "time"
)

type MyError struct {
    When time.Time
    What string
}

func (e *MyError) Error() string {
    return fmt.Sprintf("at %v, %s",
        e.When, e.What)
}

func run() error {
    return &MyError{
        time.Now(),
        "it didn't work",
    }
}

func main() {
    if err := run(); err != nil {
        fmt.Println(err) // at 2009-11-10 23:00:00 +0000 UTC m=+0.000000001, it didn't work
    }
}
  • Go에선 문자열을 반환하는 하나의 메소드 Error()로 구성된 내장 인터페이스 타입 error를 사용한다.
    type error interface {
         Error() string
    }
  • 기본적으로 모든 에러는 error interface를 호출하지만, 위 코드 처럼 직접 에러를 정의할 수 있다.
  • + 이해가 힘들어 추가적인 내용 첨부 [예제로 배우는 Go 프로그래밍]

 

23. 연습문제

Sqrt 함수는 복소수를 지원하지 않기 때문에, 음수가 주어지면 nil 이 아닌 에러 값을 반환해야 합니다.


새로운 타입을 만드십시오.

type ErrNegativeSqrt float64

and make it an error by giving it a 그리고 아래 메소드를 구현함으로써 그 타입이 error 가 되게 하십시오.

func (e ErrNegativeSqrt) Error() string

이는 ErrNegativeSqrt(-2).Error() 가 "cannot Sqrt negative number: -2" 를 반환하는 그러한 메소드입니다.


package main
import (
    "fmt"
    "math"
)

type ErrNegativeSqrt float64

func (e ErrNegativeSqrt) Error() string {
    if e < 0 {
    	return fmt.Sprintf("cannot Sqrt negative number: %0.1f", e)
    }
    return fmt.Sprintf("OK")
}


func Sqrt(f float64) (float64, error) {
    if f > 0 {
	    var a, z, c float64 = 0, 1, 0
	    for a = 1; a < 10; a++ {
	        if math.Abs(z - c) > 1e-10 {
    	        c = z
        	    z = z - (z * z - f)/(2*z)
	        } else {
    	        break
        	}
    	}
    	return z, ErrNegativeSqrt(f)
    } else {
        return f, ErrNegativeSqrt(f)
    }
    
}

func main() {
    fmt.Println(Sqrt(2))
    fmt.Println(Sqrt(-2))
}

 

Golang { Syntax int := 5 }

Golang Syntax _5


19. 스위치

package main

import (
    "fmt"
    "time"
)

func main() {
    fmt.Println("When's Saturday?")
    today := time.Now().Weekday()
    switch time.Saturday {
    case today + 0:
        fmt.Println("Today.")
    case today + 1:
        fmt.Println("Tomorrow.")
    case today + 2:
        fmt.Println("In two days.")
    default:
        fmt.Println("Too far away.")
    }
}
  • Go의 Switch는 break문을 통해 빠져나오지 않고 조건이 일치하는 case문을 마치면 switch문을 종료하게된다.
  • 위의 코드를 보면 만약 time.Saturdaytoday + 0와 일치하면 today + 1today + 2, default문은 실행하지 않는다.
  • Go의 switch에선 조건을 생략할 수 있는데 이를 이용해 if-then-else문을 깔끔하게 작성할 수 있다.
    switch옆에 조건이 없는 대신 case문에 조건문이 들어가게되며, 제일 위쪽부터 true인 조건의 case문을 실행한다.

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func main() {
        t := time.Now()
        switch {
        case t.Hour() < 12:
            fmt.Println("Good morning!")
        case t.Hour() < 17:
            fmt.Println("Good afternoon.")
        default:
            fmt.Println("Good evening.")
        }
    }
    

 

20. 연습문제

complex64 타입과 complex128 타입을 통해서 Go 언어의 복소수 지원 기능을 알아봅니다.
세제곱근을 얻기 위해서는, 뉴턴의 방법 (Newton’s method)을 적용하여 다음을 반복 수행합니다:

z = z - (z * z * z - x) / (3 * z * z)

package main
import "fmt"

func Cbrt(x complex128) complex128 {
    var z complex128 = 1
    for a := 1; a < 10; a++ {
        z =  z - (z * z * z - x) / (3 * z * z)
    }
    return z
}

func main() {
    fmt.Println(Cbrt(3)) // (1.4422495703074083+0i)
}

Golang { Syntax int := 4 }

Golang Syntax _4


15. 맵 (Maps)

package main
import "fmt"

type Vertex struct {
    Lat, Long float64
}

var m = map[string]Vertex{
    "Bell Labs": Vertex{
        40.68433, -74.39967,
    },
    "Google": {
        37.42202, -122.08408,
    },
}

func main() {
    fmt.Println(t, m) // map[Bell Labs:{40.68433 -74.39967} Google:{37.42202 -122.08408}]
}
  •  Go에서 맵은 값에 key를 지정한다.
  • 맵은  반드시 사용하기 전에  make를 명시해아한다.
  • make를 수행하지 않은 nil 에는 값을 할당할 수 없다.
  • 만약 상위의 타입이 타입명이라면 리터럴에서 타입명을 생략해도 된다.
    즉 "Bell Labs": {40.68433, -74.39967} 와 "Bell Labs": Vertex{40.68433, -74.39967}는 같은 뜻이다.
  • 맵 다루기 >
        맵의 요소를 생성/ 수정 :  m[key] = data
        요소값 가져오기 : val = m[key]
        키 존재 여부 확인 : val, has_key = m[key] >>  만약 m[key]가 존재하지 않는다면 has_keyfalse가, valzero value이 할당된다.

16. 연습문제

WordCount 함수를 구현합니다. 이 함수는 s라는 문자열 내에서 각각의 “단어”의 등장 횟수를 나타내는 맵을 반환해야 합니다. wc.Test 함수는 주어진 함수를 이용하여 테스트를 실행한 뒤에 그 성공 여부를 출력해 줍니다.

package main
import (
    "code.google.com/p/go-tour/wc"
    "strings"
)

func WordCount(s string) map[string]int {
    m := make(map[string]int)
    for _, key := range strings.Fields(s) {
        _, ok := m[key]
        if ok {
            m[key]++
        } else {
            m[key] = 1
        }
    }
    return m
}

func main() {
    wc.Test(WordCount)
}

 

17. 함수 값과 클로저

package main
import "fmt"

func adder() func(int) int {
    sum := 0
    return func(x int) int {
        sum += x
        return sum
    }
}

func main() {
    pos, neg := adder(), adder()
    for i := 0; i < 10; i++ {
        fmt.Println(
            pos(i),
            neg(-2*i),
        )
    }
}
  • Go에서  함수를 value(값)이다. 값이기 때문에 변수에 저장해 사용할 수 있다.
  • 함수는 클로저(full closures)이다. 위 예제에서 보면 각각의 pos와  neg의  sum 변수가 존재하는 걸 볼 수있다.

18. 연습문제

fibonacci 함수를 구현합니다. 이 함수는 이어지는 피보나치 수를 반환하는 함수 (클로져)를 반환해야 합니다.

package main
import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
    x1 := 1
    x2 := 2
    return func() int {
        x3 := x1+x2
        x1, x2 = x2, x3
        return x3
    }
}

func main() {
    f := fibonacci()
    for i := 0; i < 10; i++ {
        fmt.Println(f())
    }
}