일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- ECS
- instance
- algorithm
- TypeScript
- Project
- data
- Scrum
- 자바스크립트
- data analyze
- python
- 크롤링
- tensorflow
- keras
- 다나와
- analyzing
- adaptive life cycle
- angular
- webcrawling
- DANAWA
- AWS
- matplotlib
- 애자일
- visualizing
- pandas
- opencv
- 프로젝트
- Method
- Agile
- Crawling
- javascript
Archives
- Today
- Total
LiJell's 성장기
Python Extras 본문
반응형
1. Iterator
- Iterable(반복 가능) 객체
- 반복자로 요소를 순서대로 읽을 수 있음
- for 문과 함께 자주 사용됨
- 요소를 순회할 반복자 제공
nums = [11,22,33]
it = iter(nums)
while True:
try:
num = next(it)
except StopIteration:
break
print(num)
'''
11
22
33
'''
1.1. Iterator Generator
- 매번 iterator 관련 메서드를 작성하는 수고를 덜 수 있음
- 시간과 메모리를 적게 차지해서 많이 사용
- yield
- 값을 반환
- return과 유사하나 변수의 마지막 값과 상태를 저장
def seq_gen(data):
for idx in range(0, len(data), 2):
yield data[idx:idx+2]
solar_time = seq_gen("입춘우수경칩춘분청명곡우힙하소만망종하지소서대서")
for k in solar_time:
print(k, end=', ')
'''
입춘, 우수, 경칩, 춘분, 청명, 곡우, 힙하, 소만, 망종, 하지, 소서, 대서,
'''
- seq_gen generator
- iter, next 메서드를 내부에 자동 생성
- 인수로 전달받은 문자열 데이터를 분리하여 yield로 리턴
# Generator를 사용한 경우
def seq_gen(data):
for idx in range(0, len(data), 2):
yield data[idx:idx+2]
solar_time = seq_gen("입춘우수경칩춘분청명곡우힙하소만망종하지소서대서")
for k in solar_time:
print(k, end=', ')
# Generator를 사용하지 않은 경우
data = "입춘우수경칩춘분청명곡우힙하소만망종하지소서대서"
for k in (data[idx:idx+2] for idx in range(0, len(data),2)):
print( k, end=', ')
def foo():
return 1
print(foo())
'''
1
'''
def bar():
yield 1
print(bar())
'''
<generator object bar at 0x7f33b269cf50>
'''
b = bar()
next(b)
'''
1
'''
def bar1():
print("A")
yield 1
print("B")
yield 2
print("C")
yield 3
b1 = bar1()
- 한개씩 선언하고 대기. 다시 선언하면 그 다음게 나옴
next(b1)
'''
A
1
'''
next(b1)
'''
B
2
'''
next(b1)
'''
C
3
'''
2. Decorator
2.1. First-Class-Citizen
- 파이썬에서 함수는 first-class citizen
- 이름을 가짐
- 리턴값으로 사용할 수 있음
여기까진 일반적인 다른 언어와 공통점이다
다른 언어와 다른점:
- 다른 변수에 대입 가능
- 인수로 전달가능
- 컬렉션에 저장할 수 있음(list, tuple, dictionary)
- 함수 자체를 변수에 넣을 수 있음
def add(a,b):
print( a+b )
plus = add
plus(1,2)
'''
3
'''
2.2. Local Function
- 다른 함수 안에 정의되는 도우미 함수
- 함수 내부의 반복되는 코드를 통합하여 관리가 용이하게 함
def calc_sum(n):
def add(a, b):
return a+b
sum = 0
for i in range(n+1):
sum = add(sum, i)
return sum
print ("~100= ", calc_sum(100))
'''
~100= 5050
'''
- 상호 평등한 관계로 작성할 경우 동작에는 문제가 없음
- 단, calc_sum이 add에 종속되어 독립성이 떨어지고 재사용이 번거로운 단점이 있음
def add(a, b):
return a+b
def calc_sum(n):
sum = 0
for i in range(n+1):
sum = add(sum, i)
return sum
print ("~100= ", calc_sum(100))
2.3. Decorator
- 함수에 원하는 코드를 추가하는 기법
- 함수 래핑(wrapping)
- 원하는 코드 추가 및 원래 함수를 대리 호출하여 기능을 확장
def inner():
print("결과를 출력")
def outer(func):
print('-'*20)
func()
print('-'*20)
outer(inner)
'''
--------------------
결과를 출력
--------------------
'''
- 호출 구문이 직관적이지 않다
- 해결책은??
def inner():
print("결과를 출력")
def outer(func):
def wrapper():
print('-'*20)
func()
print('-'*20)
return wrapper
inner = outer(inner)
inner()
'''
--------------------
결과를 출력
--------------------
'''
- Example
def para(func):
def wrapper():
return "<p>" +str(func()) + "</p>"
return wrapper
@para
def outname():
return 'James Bond'
@para
def outage():
return '29'
print(outname())
print(outage())
'''
<p>James Bond</p>
<p>29</p>
'''
- 래핑되는 함수가 인수를 가지는 경우 대리호출시에도 인수가 그대로 전달됨
def para(func):
def wrapper():
return "<p>" +str(func()) + "</p>"
return wrapper
@para
def outname(name):
return 'Name: ' + name
@para
def outage(age):
return 'Age: ' + str(age)
print(outname('James Bond'))
print(outage(29))
'''
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-36-ae6ac92a202c> in <module>()
12 return 'Age: ' + str(age)
13
---> 14 print(outname('James Bond'))
15 print(outage(29))
16
TypeError: wrapper() takes 0 positional arguments but 1 was given
'''
- wrapper은 func() 형태로만 대리호출 하기 때문에 인수가 적용되지 않음
- wrapper이 가변 인수를 받아야 함
def para(func):
def wrap(*args, **kwargs):
return "<p>" +str(func(*args, **kwargs)) + "</p>"
return wrap
@para
def outname(name):
return 'Name: ' + name
@para
def outage(age):
return 'Age: ' + str(age)
print(outname('James Bond'))
print(outname.__name__)
print(outage(29))
print(outage.__name__)
'''
<p>Name: James Bond</p>
wrap
<p>Age: 29</p>
wrap
'''
- outname함수의 name 속성이 wrapper로 출력됨
- @wraps 데코레이터 -> 데코레이터 간 중첩시 문제를 해결
from functools import wraps
def para(func):
@wraps(func)
def wrapper(*args, **kwargs):
return "<p>" +str(func(*args, **kwargs)) + "</p>"
return wrapper
@para
def outname(name):
return 'Name: ' + name
@para
def outage(age):
return 'Age: ' + str(age)
print(outname('James Bond'))
print(outname.__name__)
print(outage(29))
print(outage.__name__)
'''
<p>Name: James Bond</p>
outname
<p>Age: 29</p>
outage
'''
2.4. Class Decorator
- 객체를 괄호 붙여 호출하는 경우 call 메서드가 자동 호출됨
- call 메서드에서 원래 함수 호출 전후 추가 작업 실행
class Outer:
def __init__(self,func):
self.func = func
def __call__(self):
print('-'*20)
self.func()
print('-'*20)
def inner():
print ('print result')
inner = Outer(inner)
inner()
'''
--------------------
print result
--------------------
'''
- inner()
- 객체를 함수 형식으로 호출하면 래핑한 함수가 호출됨
- 위 구문을 간단하게 줄여 클래스 데코레이터를 만듬
class Outer:
def __init__(self,func):
self.func = func
def __call__(self):
print('-'*20)
self.func()
print('-'*20)
@Outer
def inner():
print ('print result')
inner()
'''
--------------------
print result
--------------------
'''
3. 동적 코드 실행
3.1. eval
- 문자열 형태로 된 파이썬 표현식을 평가하여 결과를 반환
- 실시간으로 코드를 만들어 실행할 수 있음
result = eval('2+3*4')
print(result)
a = 2
print (eval('a+3'))
city = eval("['seoul','osan','suwon','busan']")
for c in city:
print (c, end=', ')
'''
14
5
seoul, osan, suwon, busan,
'''
3.2. exec
- 파이썬 코드를 직접 실행하는 함수
exec('val=3')
print(val)
exec("for i in range(5): print(i,end=', ')")
'''
3
0, 1, 2, 3, 4,
'''
- eval 함수는 표현식을 평가하지만 문장을 실행하는 것은 아님
eval('val=3')
print(val)
eval("for i in range(5): print(i,end=', ')")
'''
File "<string>", line 1
val=3
^
SyntaxError: invalid syntax
'''
3.3. compile
- 여러 줄 코드의 반복 처리도 가능
- 계속 실행할 코드를 미리 해석 해 놓으면 동작이 빨라짐
- 나중에 exec, eval로 실행할 수 있음
- 나중에 실행할 수 있는 파이썬 코드 오브젝트를 리턴함
compile (source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
- source - normal string, byte string or AST object
- filename - 코드를 읽을 파일이름. 파일에서 읽는게 아니면 임의의 이름을 주면 됨
- mode - eval, exec, or single
- eval : single expression만 받아들임
- exec : 파이썬 expression, 클래스, 함수 등의 코드 블럭을 받아들임
- single : single interactive expression만 받아들임
code = compile("""
for i in range(5):
print (i, end=', ')
print()
""", 'test', 'exec')
for n in range(10):
exec(code)
'''
0, 1, 2, 3, 4,
0, 1, 2, 3, 4,
0, 1, 2, 3, 4,
0, 1, 2, 3, 4,
0, 1, 2, 3, 4,
0, 1, 2, 3, 4,
0, 1, 2, 3, 4,
0, 1, 2, 3, 4,
0, 1, 2, 3, 4,
0, 1, 2, 3, 4,
'''
4. args & *kwargs
4.1. *args
- 함수에 임의 갯수의 argument를 넘겨주기 위해 사용
- 임의 갯수의 argument를 iterable로 만들어 줌
from operator import mul
from functools import reduce
def multiply(*args):
return reduce(mul, args)
\>>> multiply(2,3,5)
30
4.2. **kwargs
- args와 마찬가지로 함수 선언에 사용
- 함수에 임의의 keyworded argument를 넘겨줘 함수 내에서 dictionary로 억세스 할 수 있게 해 줌
def display_stuff(**kwargs):
if kwargs is not None:
print kwargs
\>>> display_stuff(name='Jeff', passion='development', language='python')
{'passion':'development', 'name':'Jeff', 'language':'python'}
\>>>
- kwargs dictionary에 원하는 키가 없으면 KeyError가 발생
- 에러를 피하려면 억세스하려는 키가 dictionary에 존재하는지 체크
def display_stuff(**kwargs):
if kwargs is not None:
print kwargs['passion']
\>>> display_stuff(error='KeyError')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in display_stuff
KeyError: 'passion'
\>>>
4.3. &*
def print_vector(x, y, z):
print ('<%s, %s, %s>' % (x,y,z))
\>>> print_vector(0,1,0)
<0, 1, 0>
- vector가 튜플이나 리스트로 표현된 경우
\>>> tuple_vec = (1, 0, 1)
\>>> list_vec = [1, 0, 1]
\>>> print_vector(tuple_vec[0], tuple_vec[1], tuple_vec[2])
<1, 0, 1>
- '*' operator로 function argument unpacking이 가능
\>>> print_vector(*tuple_vec)
<1, 0, 1>
\>>> print_vector(*list_vec)
<1, 0, 1>
- '**' operator로 dictionary에서 keyword argument unpaking이 가능
\>>> dict_vec = {'y':0, 'z':1, 'x':1}
\>>> print_vector(**dict_vec)
<1, 0, 1>
- dictionary는 unordered이기 때문에 key값과 일치하는 함수 argument에 해당 값을 넣어 줌
- dictionary에 '*' operator를 사용하면 key가 랜덤하게 전달됨
\>>> dict_vec = {'y':0, 'z':1, 'x':1}
\>>> print_vector(**dict_vec)
<1, 0, 1>
\>>> print_vector(*dict_vec)
<y, x, z>
5. Dictionary
5.1. Ordered Dictionary
- dictionary에서는 key가 추가된 순서를 기억하지 않음
- Key가 추가된 순서를 기억하는 dictionary → OrderedDict
- Built-in 데이터 타입이 아니고 collections. OrderedDict 에 정의되어 있음
\>>> import collections
\>>> d = collections.OrderedDict(one=1, two=2, three=3)
\>>> d
OrderedDict([('one',1), ('two',2), ('three',3)])
\>>> d['four'] = 4
\>>> d
OrderedDict([('one',1), ('two',2), ('three',3), ('four',4])
\>>> d.keys()
odict_keys(['one','two','three','four'])
6. Emulating switch.case with dicts
- 파이썬에는 switch/case문이 없어 if/elif/else로 표현해야 함
>>> if cond == 'cond_a':
... handle_a()
... elif cond == 'cond_b':
... handle_b()
... else:
... handle_default()
- 파이썬에서 함수는 first-class citizen
- Input condition을 키, 호출될 함수를 값으로 dictionary를 만들어 줌
\>>> func_dict = {
... 'cond_a': handle_a,
... 'cond_b': handle_b,
... }
\>>> cond = 'cond_a'
\>>> func_dict[cond]
<function __main__.handle_a()>
\>>> func_dict[cond]()
- cond 값이 dictionary의 키에 있어야만 함. 없으면 KeyError exception 발생
→ if/elif/else에서 else 부분의 기능을 할 수 없음
- Default 케이스를 처리하기 위해 dictionary의 get 메소드를 사용
\>>> func_dict.get(cond, handle_default)()
6.1. Example
- 같지만, 아래가 가독성이 좋음
def plus(x,y):
return x+y
def minus(x,y):
return x-y
def multiply(x,y):
return x*y
def divide(x,y):
return x/y
def dispatch_if(operator, x, y):
if operator == 'add':
return plus(x,y)
elif operator == 'sub':
return minus(x,y)
elif operator == 'mul':
return multiply(x,y)
elif operator == 'div':
return div(x,y)
def plus(x,y):
return x+y
def minus(x,y):
return x-y
def multiply(x,y):
return x*y
def divide(x,y):
return x/y
def default_op(x,y):
Return None
func_dict = {
'add':plus,
'sub':minus,
'mul':multiply,
'div':divide,
}
def dispatch_dict(operator, x, y):
return func_dict.get(operator, default_op)()
def display_stuff(**kwargs):
if kwargs is not None:
display_stuff(name='Jeff', passion='development', language='python')
{'passion':'development', 'name':'Jeff', 'language':'python'}
'''
File "<ipython-input-60-ac84eb226d20>", line 3
print kwargs
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(kwargs)?
'''
반응형
'Bigdata > 파이썬_Python' 카테고리의 다른 글
Pandas Styling: 판다스 스타일링 (2) | 2022.02.11 |
---|---|
19.python_pandas_practice (0) | 2022.01.10 |
18.python_visualization (0) | 2022.01.10 |
17.python_datetime_expression (0) | 2022.01.10 |
16.python_NA_missing_duplicate_value (0) | 2022.01.10 |
Comments