제너레이터는 지연 평가(lazy evaluation) 구현체이다.

파이썬에서 모든 lazy evalution은 이터레이터(iterator)라고 불린다.
이러한 이터레이터 중에서 특정 방식을 통해서 생성한 이터레이터를 제너레이터라고 부른다.

즉, 객체의 값을 미리 생성해서 저장해 두지 않고 해당 객체를 사용할 때 값을 계산해서 반환해준다.

 

제너레이터는 소괄호()를 이용한 컴프리헨션으로 생성할 수 있다.

num = (x for x in range(10))
print(num)

>><generator object <genexpr> at 0x00000214166F4AC8>

 

위의 설명처럼 객체를 사용할 때 값을 계산해주므로 for문으로 제너레이터를 사용해보면

num = (x for x in range(10))
for x in num:
    print(x, end=' ')
    
>>0 1 2 3 4 5 6 7 8 9 

next함수로도 제너레이터의 사용이 가능하다. next함수는 제너레이터의 다음 값을 반환해준다.

num = (x for x in range(3))
print(next(num))
print(next(num))
print(next(num))

>>0
>>1
>>2

정해진 범위를 벗어나면 StopIteration 에러가 발생한다.

num = (x for x in range(3))
print(next(num))
print(next(num))
print(next(num))
print(next(num))

>>0
1
2
Traceback (most recent call last):
  File "..............................", line 5, in <module>
    print(next(num))
StopIteration

 

제너레이터는 다른 이터레이터(iterator)와 달리 값을 계산해서 반환해주고 나면 값을 소비하고 더 이상 기억하지 않는다.

(재사용이 불가능하다.)

num = (x for x in range(10))
for x in num:
    print(x, end=' ')

for x in num:			#두 번째 for문에서는 아무것도 출력이 되지않는다.
    print(x, end=' ')
    
>>0 1 2 3 4 5 6 7 8 9 

 

 

yield를 이용한 제너레이터 생성


def문을 이용한 함수 내부에 yield 키워드를 사용하여 제너레이터의 생성이 가능하다.

아래와 같이 값을 단순 지정해줄 수도 있고

def gen():
    yield 0
    yield 1
    yield 2

x=gen()		#제너레이터 x 생성
for i in x:
    print(i)
    
>>0
1
2

보통 함수와 같이 내부에 for문과 if문을 사용할 수도 있다.

def gen():
    for i in range(3):
        yield i

x=gen()
for i in x:
    print(i)
    
    
>>0
1
2
파이썬은 함수 내부에 yield 키워드가 하나라도 존재하면 해당 함수를 generator로 인식한다.

아래와 같이 함수에 인자를 받으면 더 다양한 제너레이터를 생성할 수 있다.

또한 반복문을 이용하여 매번 다른 값을 생성하여 반환해준다면 재사용도 가능할 것이다.

import random

def broken_dice(n):     #1~6까지의 주사위 값중 n을 제외하고 리턴
    while True:
        number = random.randint(1, 6) # 1~6까지 정수 중 랜덤하게 숫자를 뽑는다.
        if number != n: #  랜덤하게 뽑은 숫자, n이 아니라면 리턴
            yield number

dice=broken_dice(5)
for i in range(6):
    print(next(dice))
    
>>2
2
2
1
1
4

 

 

출처:https://wikidocs.net/22802

'Python' 카테고리의 다른 글

Python - 컴프리헨션(Comprehension)  (0) 2020.08.25
Python - 람다함수(익명함수)  (0) 2020.08.24
Python - 전역 변수, 지역 변수  (0) 2020.08.23
Python - mutable객체, immutable객체  (0) 2020.08.22
Python - 빠른 입력  (0) 2020.08.17

파이썬은 컴프리헨션이라는 문법을 지원한다.

컴프리헨션을 이용하면 list, dict, set을 좀 더 간단한 방법으로 작성할 수 있다.

 

 

리스트 컴프리헨션


리스트 컴프리헨션의 작성법은 아래와 같다.

num = [x for x in range(10)]

위의 컴프리헨션문을 for문으로 표기하면 아래와 같다.

num = []
for x in range(10):
	num.append(x)
 

 

append(x)를 대신하여 컴프리헨션문에서는 for문 앞에 변수명만 적어주면 된다.

 

 

컴프리헨션문 내에서 if문과 다중 for문도 사용이 가능하다.(if문도 여러개 사용 가능)

num = [x for x in range(10) if x%2==0]  #if문을 이용하여 짝수만 저장
print(num)

>>[0, 2, 4, 6, 8]

 

 

다중 for문 작성법(왼쪽 for문이 먼저 작동한다.)

num=[[x,y] for x in [1,2,3] for y in [4,5,6]]
print(num)

>>[[1, 4], [1, 5], [1, 6], [2, 4], [2, 5], [2, 6], [3, 4], [3, 5], [3, 6]]

 

 

셋 컴프리헨션


위 리스트 컴프리헨션의 대괄호[]만 중괄호{}로 바꿔주면된다. 내부 코드 작성법은 동일.

 

 

 

딕셔너리 컴프리헨션


컴프리헨션문을 중괄호{}로 감싸고 key:value의 형태로 내용을 채우면 딕셔너리의 생성이 가능하다.

li = ['A','B','C']
di = {x:0 for x in li}	#value는 0
print(di)

>>{'A': 0, 'B': 0, 'C': 0}

 

컴프리헨션을 이용하여 기존 딕셔너리를 새롭게 변경할 수도 있다.

old={'A':10,'B':10,'C':20,'D':10}
new={k:v for k,v in old.items() if v!=20}	#items메소드를 이용해 old에서 key와 value를 가져옴
print(new)

>>{'A': 10, 'B': 10, 'D': 10}	#if문을 이용해 20이라는 value를 가진 key 제거

 

 

 

튜플 컴프리헨션


위의 방법대로라면 소괄호()를 사용하여 튜플 컴프리헨션을 작성할 수 있을 것 같다.

num = (x for x in range(10))
print(num)

>><generator object <genexpr> at 0x00000220CCDD4AC8>

하지만 생각과 달리 generator(제너레이터)가 생성된다.

제너레이터에 대해서는 다음 글에서 설명하겠다.

 

'Python' 카테고리의 다른 글

Python - 제너레이터(Generator)  (0) 2020.08.25
Python - 람다함수(익명함수)  (0) 2020.08.24
Python - 전역 변수, 지역 변수  (0) 2020.08.23
Python - mutable객체, immutable객체  (0) 2020.08.22
Python - 빠른 입력  (0) 2020.08.17

파이썬에서 함수는 기본적으로 def를 이용하여 작성하지만, 람다를 사용하면 좀 더 간결한 코드로 작성이 가능하고 메모리 절약도 가능하다.

lambda <<매개변수>>: <<리턴값>>

람다함수는 위와 같은 형태로 작성한다.

 

 

람다함수의 또 다른 이름이 익명함수인 만큼 "이름 없는 함수"로 작성이 가능하다.

함수의 이름이 정해지지 않았으니 재사용은 불가능하다.

print((lambda x:x**2)(3))	#람다함수는 정의와 동시에 사용할 수 있다.

>>9

 

 

하지만 람다함수를 변수에 저장하게 되면 def문을 이용해서 작성한 함수와 똑같이 재사용이 가능하다.

f=lambda x:x**2		#f에 람다함수 저장
print(f(3))

>>9

 

 

 

람다함수는 보통 아래와 같이 딱 한번 필요한 함수를 정의하는데 자주 사용된다.

li=[1,2,3,4,5]
li=list(map(lambda x:x**2,li))
print(li)

>>[1, 4, 9, 16, 25]

 

'Python' 카테고리의 다른 글

Python - 제너레이터(Generator)  (0) 2020.08.25
Python - 컴프리헨션(Comprehension)  (0) 2020.08.25
Python - 전역 변수, 지역 변수  (0) 2020.08.23
Python - mutable객체, immutable객체  (0) 2020.08.22
Python - 빠른 입력  (0) 2020.08.17

파이썬에서 객체는 변경가능한(mutable) 객체와 변경불가능(immutable) 객체로 나뉜다.

 

mutable객체로는 list, set, dictionary 가 있고

위의 셋을 제외한 bool, int, float등이 immutable객체이다.

list mutable
set mutable
dict mutable
bool immutable
int immutable
float immutable
tuple immutable
str immutable
frozenset immutable

 

mutable


List

x=[1,2,3]
print(id(x))
x[2]=5		
print(id(x))	#값을 바꿔도 주소는 그대로


>>2066410918472
>>2066410918472

 

 

Set

x={0:True,1:True,2:True}
print(id(x))
x[0]=False		#{0:False,1:True,2:True}
print(id(x))	#값을 바꿔도 주소는 그대로

>>3146876058024
>>3146876058024

 

immutable


Int

x=1
print(id(x))
x+=1
print(id(x))

>>140712646963456
>>140712646963488

 

String

x='Python'
x[0]='A'	#에러 발생


>>Traceback (most recent call last):
  File ".....................................", line 2, in <module>
    x[0]='A'
TypeError: 'str' object does not support item assignment
x='Python'
print(id(x))
x+='3'
print(id(x))

>>1813087795312
>>1813087831536

 

 

 

 

 

'Python' 카테고리의 다른 글

Python - 람다함수(익명함수)  (0) 2020.08.24
Python - 전역 변수, 지역 변수  (0) 2020.08.23
Python - 빠른 입력  (0) 2020.08.17
Python - 함수 인자의 개수를 알 수 없을 때  (0) 2020.08.11
Python - 예외처리  (0) 2020.08.10

지금까지 파이썬에서 입력을 받기 위해서 input()을 사용했다.

하지만 파이썬으로 알고리즘 문제를 풀 때 input()을 이용해 많은 입력을 받다 보면 시간 초과가 발생한다.

시간 초과를 방지하기 위해 input()보다 더 빠른 sys모듈의 sys.stdin.readline()을 사용해보자.

import sys
x=sys.stdin.readline()
print(x)

>>Python	#입력
Python		#출력

sys.stdin.readline()은 문자열 마지막의 줄 바꿈 문자까지 읽기 때문에 strip()을 이용해 줄 바꿈 문자를 제거해주는 것이 좋다.

import sys
x=sys.stdin.readline().strip()
print(x)
print('Java')

>>Python	#입력
Python		#출력
Java

함수, 메서드를 작성할 때 대부분의 경우 매개변수의 개수를 명확히 지정해준다.

하지만 때로는 내가 작성한 함수의 인자로 몇 개가 입력될지 모를 때가 있다.

그럴 때는 매개변수에 *를 붙이면 여러 개의 입력값(인자)을 하나의 튜플로 받을 수 있다.

이러한 함수를 가변인자함수라고한다.

def print_animal(*args):	
    for name in args:				#for문을 이용해 튜플의 모든 내용 출력
        print(name,end=' ');

    print();

print_animal('dog','cat','lion');	#튜플('dog','cat','lion')를 인자로 전달
print_animal('tiger','cat');		#튜플('tiger','cat')를 인자로 전달

>>dog cat lion 
>>tiger cat 

(*매개변수)를 마지막에만 작성해주면 그 앞에 다른 매개변수를 포함해도 함수는 정상적으로 작동된다.

def print_animal(num,*args):
    print(num,end=' ');
    for name in args:
        print(name,end=' ');

    print();

print_animal(3,'dog','cat','lion');
print_animal(2,'tiger','cat');

>>3 dog cat lion 
>>2 tiger cat 

위의 예제에서는 함수의 인자를 위치 인자(Positional arguments)로 전달했지만 아래와 같이 키워드 인자(keyword arguments)를 전달받는 가변인자함수도 생성이 가능하다.

def print_animal(**kwargs):		# 매개변수의 이름앞에(**)를 붙여준다.
   print(kwargs)			#딕셔너리 형태로 전달받는다.
   for x in kwargs:
       print(kwargs[x])

print_animal(a='cat',b='dog',c='lion')

>>{'a': 'cat', 'b': 'dog', 'c': 'lion'}	#딕셔너리 형태로 전달받는다.
>>cat
>>dog
>>lion

위의 두 예시를 함께 사용할 수도 있다.

단, 위치 인자가 키워드 인자보다 항상 앞에 위치해야 된다.

def print_animal(*args,**kwargs):
    print(args)
    print(kwargs)
  

print_animal('tiger','rabbit',a='cat',b='dog',c='lion')

>>('tiger', 'rabbit')
>>{'a': 'cat', 'b': 'dog', 'c': 'lion'}

'Python' 카테고리의 다른 글

Python - mutable객체, immutable객체  (0) 2020.08.22
Python - 빠른 입력  (0) 2020.08.17
Python - 예외처리  (0) 2020.08.10
Python - 클래스(Class)와 객체(Object)  (0) 2020.08.09
Python - 컬렉션 정리  (0) 2020.08.04

+ Recent posts