과거의 것들/AI Tech boostcamp

AITech 학습정리-[DAY 3] 파이썬 기초 문법 II

===================================

수업내용

Python Data Structure

  • 스택과 큐 (stack & queue with list)
  • 튜플과 집합(tuple & set)
  • 사전(dictionary)
  • Collection 모듈

 

Stack

Last In First Out (LIFO)

push, pop

a.append(10)

a.pop()

 

Queue

First In First Out (FIFO)

a.append(10)

a.pop()

 

tuple

값의 변경이 불가능한 리스트

[] 대신 () 사용

 

하나일 경우 t = (1,) 로 해야 튜플로 인식

 

집합 (set)

값을 순서업싱 저장, 중복을 불허하는 자료형

s = set([1,2,3,1,2,3])

s # {1,2,3}

s. add(5)

s.remove(2)

s.update([1,4,5,6,7])

s1.union(s2)  또는   s1 | s2  # 합집합

s1.intersection(s2)  또는  s1 & s2  # 교집합

s1.difference(s2)  또는  s1 - s2  #  s1과 s2의 차집합

 

사전 (dictionary)

Key 값을 활용하여 Value를 관리함

 

Collections 모듈

from collections import deque

from collections import Counter

from collections import OrderedDict

from collections import defaultdict

from collections import namedtuple

 

deque

rotate, extend, extendleft(거꾸로 붙음) 함수도 있다

기존 list보다 효율적인 자료구조를 제공

효율적 메모리 구조로 처리속도 향상

 

OrderedDict

근데 python 3.6부터 일단 dict도 입력한 순서를 보장하여 출력함

 

defaultdict

신규값을 안넣어도 알아서.

Dict type의 값에 기본 값(초기 값)을 지정, 신규값 생성시 사용하는 방법

from collections import defaultdict

d = defaultdict(object)  # default dictionary를 생성

d = defaultdict(lambda: 0)  # default 값을 0으로 설정함. 함수 형태로 넣어줘야 함.

print(d["first"])

 

Counter

Sequence type의 data element들의 갯수를 dict 형태로 변환

c = Counter(a=4, b=2, c=0, d=-2)

d = Counter(a=1, b=2, c=3, d=4)

c.subtract(d)  # Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})

Set의 연산들을 지원함. c+d, c&d, c|d

 

namedtuple

Tuple 형태로 Data 구조체를 저장하는 방법

저장되는 data의 variable을 사전에 지정해서 저장함

from collections import namedtuple

Point = namedtuple('Point', ['x', 'y'])

p = Point(11, y=22)

print(p[0] + p[1])

x, y = p

print(x, y)

print(p.x + p.y)

print(Point(x=11, y=22))

 

 

Pythonic code

예)

colors = ['red', blue', 'yellow'] 

''.join(colors)

  • split & join
  • list comprehension
  • enumerate & zip
  • lambda & map & reduce
  • generator
  • asterisk
 

split & join

a.split(),  a.split(',')

''.join(a),  '-'.join(a)

 

list comprehension

result = [i for i in range(10) if i % 2 == 0]

 

word_1 = "Hello"

word_2 = "World"

result = [i+j for i in word_1 for jj in word_2] #Nested For loop

result  # ['HW', 'Ho', 'Hr', 'Hl', 'Hd', 'eW', 'eo', ... ,'od']

for i in word_1:

    for j in world_2:

        result.append(i+j)

 

result = [i+j for i in case_1 for j in case_2 if not(i==j)]  # filter

result = [i+j if not(i==j) else i for i in case_1 for j in case_2]  # 도 가능

 

stuff = [[w.upper(), w.lower(), len(w)] for w in words]

하면 2차원으로 나옴

 

Two dimensional vs One dimensional

case_1 = ["A", "B", "C"]

case_2 = ["D", "E", "A"]

 

result = [i+j for i in case_1 for j in case_2]

['AD', 'AE', 'AA', 'BD', 'BE', 'BA', 'CD', 'CE', 'CA']

for i in case_1:

    for j in case_2:

        result.append(i+j)

 

result = [ [ i+j for i in case_1 ] for j in case_2 ]

[ [ 'AD', 'BD' 'CD' ], [ 'AE', 'BE', 'CE' ], [ 'AA', 'BA', 'CA' ] ]

for j in case_2:

    line = [ ]

    for i in case_1:

        line.append(i+j)

    result.append(line)

result = [ [ i+j for i in case_1 if i != 'C' ] for j in case_2 ]

 

enumerate & zip

for i, v in enumerate(['tic', 'tac', 'toe']):

    print(i, v)

 

my_str = 'ABCD'

{v : i for i, v in enumerate(my_str)}

{ 'A': 0, 'B': 1, 'C': 2, 'D': 3 }

 

alist = ['a1', 'a2', 'a3']

blist = ['b1', 'b2', 'b3']

for a, b in zip(alist, blist):

    print(a, b)

 

math = (100, 90, 80)

kor = (90, 90, 70)

eng = (90, 80, 70)

[ sum(value) / 3 for value in zip(math, kor, eng) ]

 

lambda & map & reduce

f = (lambda x, y : x + y)

f(10, 50)

(lambda x, y : x + y)(10, 50)

python 3 부터는 권장하지 않으나 많이 쓰임

 

def f(x): return 2*x  # YES

f = lambda x: 2*x  # NO

 

 

ex = [ 1, 2, 3, 4, 5]

f = lambda x: x ** 2

list(map(f, ex))  #  [1,4,9,16,25]

 

f = lambda x, y : x + y

list(map(f, ex, ex))  # [2, 4, 6, 8, 10]

근데 복잡하니까 차라리

[ f(value) for value in ex ] 로 써라

list(map(lambda x : x ** 2 if x % 2 == 0 else x, ex))  대신

[ value**2 if value % 2 == 0 else value for value in ex ]

 

 

from functools import reduce

map function과 달리 list에 똑같은 함수를 적용해서 통합

print( reduct( lambda x, y : x+y, [ 1, 2, 3, 4, 5 ]))  # 15

 

iterable object (for learn Generator)

차례대로 출력하는 모든 object가 iterable object

내부적 구현으로 __iter__와 __next__ 가 사용됨

iter() 와 next() 함수로 iterable 객체를 iterator object로 사용

cities = [ "Seoul", "Busan", "Jeju" ]

memory_address_cities = iter(cities)

print(next(memory_address_cities ))

print(next(memory_address_cities ))

print(next(memory_address_cities ))

next(memory_address_cities )

시작 메모리 값을 저장

 

for city in cities:

    print(city)

할 때 사실 내부적으로 사용되고 있었다.

 

Generator

iterable object를 특수한 형태로 사용해주는 함수

element가 사용되는 시점에 값을 메모리에 반환

: yield를 사용해 한번에 하나의 element만 반환함

메모리 주소만 가지고 있다

 

for e in list(range(50)):

    print(e)

sys.getsizeof(list(range(50))  #  520

def generator_list(num):

    for i in range(num):

        yield i

for e in generator_list(50):

    print(e)

sys.getsizeof(generator_list(50)) # 120

 

generator comprehension

list comprehension과 유사한 형태로 generator형태의 list 생성

generator experssion 이라는 이름으로도 부름

[ ] 대신 ( ) 를 사용하여 표현

gen_ex = ( n*n for n in range(500) )

print(type(g))

for 나 list를 써주면 메모리에 올라감

 

일반적인 iterator는 generator에 반해 훨씬 큰 메모리 용량 사용

gen_ex = ( n*n for n in range(50000) )

getsizeof(gen_ex))  #  112

getsizeof(list(gen)ex))  # 40808

list_ex = [ n*n for n in range(50000) ]

getsizeof(list_ex)   #  43032

 

- list 타입의 데이터를 반환해주는 함수는 generator로 만들어라!

: 읽기 쉬운 장점, 중간 과정에서 loop이 중단될 수 있을 때

- 큰 데이터를 처리할 때는 generator expression을 고려하라!

: 데이터가 커도 처리의 어려움이 없음

- 파일 데이터를 처리할 때도 generator를 쓰자

 

function passing arguments

- 함수에 입력되는 arguments의 다양한 형태

1) Keyword argument

2) Default argument

3) Variable-length arguments

 

Keyword argument

def print_something(my_name, your_name):

    print("Hello {0}, My name is {1}".format(yourname, my_name))

 

print_something("gun", "teamlab")

print_something(your_name = "teamlab", "gun")

 

Default argument

def print_something(my_name, your_name="teamlab"):

    print("Hello {0}, My name is {1}".format(yourname, my_name))

 

print_something("gun", "teamlab")

print_something("gun")

Variable-length argument

가변인자 (variable-length)

- 개수가 정해지지 않은 변수를 함수의 parameter로 사용하는 법

- Keyword arguments와 함께, argument 추가가 가능

- Asterisk(*) 기호를 사용하여 함수의 parameter를 푝시함

- 입력된 값은 tuple type으로 사용할 수 있음

- 가변인자는 오직 한 개만 맨 마지막 parameter 위치에 사용가능

- 가변인자는 일반적으로 *args를 변수명으로 사용

- 기존 parameter 이후에 나오는 값을 tuple로 저장함

 

키워드 가변인자 (Keyword variable-length)

- Parameter 이름을 따로 지정하지 않고 입력하는 방법

- asterisk(*) 두개를 사용하여 함수의 parameter를 표시함

- 입력된 값은 dict type으로 사용할 수 있음

- 가변인자는 오직 한 개만 기존 가변인자 다음에 사용

 

def asterisk_test(a, *args):

    print(a, args)

    print(type(args))

asterisk_test(1,2,3,4,5,6)

# 1 (2, 3, 4, 5, 6)

# <class 'tuple'>

 

def asterisk_test(a, **kwargs):

    print(a, kwargs)

    print(type(kwargs))

asterisk_test(1,b=2,c=3,d=4,e=5,f=6)

# 1 {'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}

# <class 'dict'>

 

def kwargs_test_3(one, two=3, *args, **kwargs):

    print(one)

    print(two)

    print(args)

    print(kwargs)

kwargs_test_3( 10, 30, 3, 5, 6, 7, 8, first=3, second=4, third=5 ) 

# 변수 넣는 순서 지켜야 한다. 키워드는 뒤에 넣어야 함.

10

30

(3, 5, 6, 7, 8)

{'first': 3, 'second': 4, 'third': 5}

 

asterisk

- 흔히 알고 있는 *를 의미함

- 단순 곱셈, 제곱연산, 가변 인자 활용 등 다양하게 사용됨

- tuple, dict 등 자료형에 들어가 있는 값을 unpacking

- 함수의 입력값, zip 등에 유용하게 사용가능

 

함수에 넣는 *args나 **kwargs 와는 다른 *다. 헷갈리지 말기.

def asterisk_test_1(a, *args):

    print(a, *args)

    print(a, args)  # 변수를 딱 하나로만 해서 tuple 값으로 들어감

    print(type(args))

test = ( 2 ,3 ,4 ,5 ,6 )

asterisk_test_1(1, *test)  은  asterisk_test_1(1, 2, 3, 4, 5, 6) 과 같음

# 1 2 3 4 5 6

# 1 (2, 3, 4, 5, 6)

# <class 'tuple'>

 

def asterisk_test_2(a, *args):

    print(a, *args)

    print(a, args)

    print(type(args))

test = ( 2, 3, 4, 5, 6 )

asterisk_test_2(1, test)

# 1 (2 3 4 5 6)

# 1 ((2, 3, 4, 5, 6),)

# <class 'tuple'>

 

 

def asterisk_test_3(a,b,c,d):

    print(a,b,c,d)

data = {"b":1, "c":2, "d":3}

asterisk_test(10,**data)  #  **data하면 dict 풀어서 b=1, c=2, d=3이 그대로 들어감  

# 10 1 2 3

print(*data)

# b c d

# print(**data)  # 에러뜸

 

 

ex = ([1,2],[3,4],[5,6])

print(ex) # ([1,2],[3,4],[5,6])

print(*ex) # [1,2] [3,4] [5,6]

for i in zip(*ex):  

    print(i)

(1,3,5)

(2,4,6)

은 

for i in zip([1,2],[3,4],[5,6]):

    print(i)

 과 같음.

 

===================================

피어세션

이번에 파이썬에서만 있는 문법들이 많았기 때문에 다른언어와의 차이점 및 리트코드에서 풀었던 각자의 방식을 공유하는 시간을 가졌다.

또 취업에 대한 궁금증, 다른 기업들은 어떤 인재를 선호하는지, 어떤식으로 취업시장이 돌아가는지에 대한 얘기를 나눴다. 눈이 넓어진 느낌이다.

 

===================================

오늘 공부 후기

진짜 comprehension 이나 asterisk는 검색해도 찔끔찔끔 나오거나 찾기 힘든 내용인데 이런걸 한번에 알려줘서 정말 유익하고 감사했다. 또 피어세션에서 다른 피어분들의 말을 듣고 작기만 했던 견문을 넓힌 느낌이라 정말 좋았다.

특히 Generator, 가변인자, asterisk는 꼭 기억하자