goodthings4me.tistory.com
효율적 개발로 이끄는 파이썬 실천 기술 - 내장함수와 특수메서드
(참고용으로 사용할 부분만 간략하게 정리)
내장 함수(embeded function)
- 객체 타입 조사 : isinstance(), issubclass(), callable()
- 객체 속성 관련 함수 : hasattr(), getattr(), setattr(), delattr()
- 이터러블 객체 받는 함수 : zip(), sorted(), filter(), map(), all(), any()
# ininstance(), issubclass() - 동적 타입 판정
d = {}
print(isinstance(d, dict))
print(isinstance(d, (int, list, dict))) # 튜플의 여러 클래스에서 동시 비교
print(issubclass(dict, object))
print(issubclass(bool, int))
print(issubclass(bool, (list, dict, int, float)))
[결과]
True
True
True
True
True
# 값을 꺼낼 때 dict 타입인지 체크
def get_value(obj, key):
if not isinstance(obj, dict): # obj가 dict 타입이 아니면
raise ValueError
return obj[key]
from collections import UserDict
# collections.UserDict는 사용자 정의 딕셔너리 객체를 생성하는 클래스
class MyDict(UserDict):
pass
my_dict = MyDict()
my_dict['a'] = 1
print(my_dict['a'])
#get_value(my_dict, 'a') # ValueError: , dict의 서브클래스 아니므로 에러 발생
[결과]
1
# callable() - 객체의 호출 가능 여부 판정
# 함수나 클래스, 메서드 등 ()를 붙여 호출할 수 있는 객체를 '호출 가능 객체(callable object)'라고 함
# 특수 메서드 __call__()을 가진 인스턴스도 ()를 붙여 호출 가능
class Threshold:
def __init__(self, threshold):
self.threshold = threshold
def __call__(self, x):
return self.threshold < x
threshold = Threshold(2) # 인스턴스화 시 임계값 지정
print(threshold(3)) # __call__() 메서드가 호출됨
print(threshold(2))
[결과]
True
False
# hasattr() - 객체의 속성 유무 판정
def is_package(module_or_package):
return hasattr(module_or_package, '__path__') # __path__ 속성 가지는 패키지 여부 판단
import json, os
print(is_package(json)) # json은 패키지임
print(is_package(os)) # os는 패키지 아님
[결과]
True
False
# getattr(), setattr(),delattr() - 객체 속성 조작
class Mutable:
def __init__(self, dic):
for k, v in dic.items():
setattr(self, str(k), v) # key를 인스턴스 변수로 하여 값 셋팅
mu = Mutable({'a': 10, 'b': 20})
print(getattr(mu, 'a'), mu.a) # getattr(mu, 'a') == mu.a
delattr(mu, 'b') # 삭제됨
#print(mu.b) # AttributeError: 'Mutable' object has no attribute 'b'
# getattr()은 인스턴스 메서드도 얻을 수 있다
strT = 'python' # 문자열 객체의 인스턴스
ins_method = getattr(strT, 'upper') # upper() 메서드
print(ins_method())
print(strT.upper())
[결과]
10 10
PYTHON
PYTHON
# zip() - 다수의 이터러블 엘리먼트를 동시에 튜플로 반환(이터레이터 생성 내장함수)
x = [1, 2, 3]
y = [4, 5, 6, 7]
res = zip(x, y) # 작은 쪽에 맞춰 반환
print(type(res), res)
print(list(res)) # 내용 확인 위해 리스트로 변환
# 긴쪽에 맞추기는 itertools.zip_longest() 사용
from itertools import zip_longest
print(list(zip_longest(x,y, fillvalue=0)))
[결과]
<class 'zip'> <zip object at 0x7efd9584d8c0>
[(1, 4), (2, 5), (3, 6)]
[(1, 4), (2, 5), (3, 6), (0, 7)]
# sorted() - 이터러블 엘리먼트 정렬, 새로운 객체 반환, 반환값은 리스트임
# 숫자, 문자가 섞여있는 경우, 인수 key에 인수를 하나만 얻는 함수 지정하여 각 엘리먼트를 비교할 값으로 반환하여 사용
x = ['1', '4', 3, 5, '2']
res = sorted(x, key=lambda v: int(v)) # reverse=True 인수 추가하여 역순 정렬도 가능
print(res)
[결과]
['1', '2', 3, '4', 5]
# filter() - 조건에 맞는 엘리먼트만을 포함한 이터레이터 반환, 인수를 하나만 받는 함수를 첫 번째 인수로 지정
x = (1, 4, 3, 5, 2)
res_fil = filter(lambda i: i > 3, x)
print(type(res_fil), res_fil)
print(list(res_fil))
# filter() 조건에 None 전달 시 참(True)이 되는 객체만 남김
x = (1, 0, None, 2, [], 'python')
print(list(filter(None, x))) # filter(None, x)
[결과]
<class 'filter'> <filter object at 0x7efd95216910>
[4, 5]
[1, 2, 'python']
# map() - 이터러블의 모든 엘리먼트에 대해 같은 함수를 적용, 반환 결과는 이터레이터임
x = (1, 4, 3, 5, 2)
res = map(lambda i: i * 10, x)
print(type(res), res)
print(list(res))
# map() 인수로 여러 이터러블 객체를 받기, 첫 번째 인수 함수에 전달하는 인수의 개수와 이터러블 객체의 수는 일치해야 함
k = ('q', 'limit', 'page')
v = ('python', 10, 2)
res = map(lambda i, j: f'{i} = {j}', k, v) # 인수의 개수 일치
print(list(res))
# join()과 조합해 문자열 작성
'?'+'&'.join(map(lambda i, j: f'{i}={j}', k, v))
[결과]
<class 'map'> <map object at 0x7efd94d05d10>
[10, 40, 30, 50, 20]
['q = python', 'limit = 10', 'page = 2']
?q=python&limit=10&page=2
# itemgetter() - sorted()와 조합 시 편리한 모듈 (key를 받고 딕셔너리에서 해당 키(들)에 대응하는 값을 찾아 반환)
from operator import itemgetter
d = {'word': 'python', 'count': 3}
fn = itemgetter('count') # key가 되는 값 받고
print(fn(d)) # 딕셔너리 d에서 찾아 반환, d['conut']를 반환
# sorted()와 조합
counts = [{'word': 'python', 'count': 3},
{'word': 'practice', 'count': 3},
{'word': 'book', 'count': 2}]
res1 = sorted(counts, key=itemgetter('count'))
print(res1)
res2 = sorted(counts, key=itemgetter('count', 'word'))
print(res2)
[결과]
3
[{'word': 'book', 'count': 2}, {'word': 'python', 'count': 3}, {'word': 'practice', 'count': 3}]
[{'word': 'book', 'count': 2}, {'word': 'practice', 'count': 3}, {'word': 'python', 'count': 3}]
# all(), any() - 한 개의 이터러블을 받고, all()은 모든 엘리먼트가 참이면 True, any()는 참인 엘리먼트가 한 개 이상이면 True 반환
print(all([3, '1', 'book']), all([3, 0, 'book']))
print(any([3, None, '']), all([None, 0, {}]))
[결과]
True False
True False
특수 메서드(Special method)
- 파이썬이 암묵적으로 호출하는 특수한 메서드(파이썬의 특징)
- 메서드 이름 앞뒤로 언더스코어 두개(__) 붙음
- 객체를 문자열로 표현 : str(), repr()
- 객체를 논리값으로 평가 : bool()
- 인스턴스를 함수처럼 다룸 : call()
- 속성으로의 동적 접근 : setattr(), delattr(), getattr(), getattribute()
- 이터러블 객체로서 동작 : iter(), next()
- 컨테이너 객체로서 동작 : getitem(), setitem(), contains()
# __str__(), __repr__() - 객체의 이름(변수)를 입력하면 해당 객체의 문자열로 표현, 이 둘은 차이가 있다
# 객체 이름만 입력 시 __repr__() 호출, print()에 인수로 전달 시 __str__() 호출
s = 'string'
s
# 'string'
print(s)
# string
# __repr__()은 디버그 등에 도움이 되는 정보 제공용 특수 메서드
# __str__()은 print(), str(), f'{}' 등에서 사용하는 사용자 친화적 문자열 반환하는 특수 메서드
# __str__()이 없으면 __repr__() 호출됨
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f'Point({self.x}, {self.y})'
p = Point(2, 3)
print(p)
[결과]
Point(2, 3)
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f'({self.x}, {self.y})'
p = Point(2, 3)
print(p)
[결과]
(2, 3)
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f'({self.x}, {self.y})'
p = Point(2, 3)
p
[결과]
<__main__.Point at 0x7efd8f1b65d0>
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f'({self.x}, {self.y})'
def __repr__(self):
return f'Point({self.x}, {self.y})'
p = Point(2, 3)
p
[결과]
Point(2, 3)
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f'({self.x}, {self.y})'
def __repr__(self):
return f'Point({self.x}, {self.y})'
p = Point(2, 3)
print(p)
[결과]
(2, 3)
# __call__() - 이 메서드를 구현한 클래스에서는 인스턴스를 함수처럼 호출 가능, 인수턴스 상태 유지 가능(함수와의 차이점)
class Adder:
def __init__(self):
self._values = []
def add(self, x):
self._values.append(x)
def get_values(self):
return sum(self._values)
adder = Adder()
adder.add(10)
adder.add(5)
#adder() # TypeError: 'Adder' object is not callable
adder.get_values() # 결과 보는 메서드 호출
[결과]
15
class Adder:
def __init__(self):
self._values = []
def add(self, x):
self._values.append(x)
def __call__(self):
return sum(self._values)
adder = Adder()
adder.add(10)
adder.add(5)
adder() # 함수처럼 호출
[결과]
15
# 함수 객체의 실체는 __call__()을 구현한 function 클래스의 인스턴스
def fn():
return 1
print(type(fn)) # <class 'function'>
print(hasattr(fn, '__call__')) # '__call__' 속성 존재 확인
dir(fn)
[결과]
<class 'function'>
True
['__annotations__',
'__call__',
'__class__',
'__closure__',
'__code__',
'__defaults__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__get__',
'__getattribute__',
'__globals__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__kwdefaults__',
'__le__',
'__lt__',
'__module__',
'__name__',
'__ne__',
'__new__',
'__qualname__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__']
# __setattr__() - 속성에 대입해 호출하는 특수 메서드, p.x = 1 처럼 __setattr__(self, x, 1) 대입
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __setattr__(self, name, value):
if name not in('x', 'y'):
raise AttributeError('Not allowed')
super().__setattr__(name, value) # 자신의 속성 호출로 무한루프에 빠지는 것 방지
p = Point(2, 3)
print(p.x)
print(p.y)
#p.z = 5 # AttributeError: Not allowed
[결과]
2
3
# __getattr__() - 속성에 접근해 호출
class Point:
pass
p = Point()
p.__dict__ # {}
p.x = 1
p.__dict__ # {'x': 1}
p.y = 2
p.__dict__ # {'x': 1, 'y': 2}
# 인스턴스 이름공간에는 속성 __dict__ 에는 대입된 속성이 저장되어 있다
print(hasattr(p, '__dict__')) # True
dir(p)
[결과]
True
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'x',
'y']
# __delattr__() - 속성의 삭제 호출
class Point:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __delattr__(self, name):
if name in('x', 'y'):
raise AttributeError('Not allowed')
super().__delattr__(name)
p = Point(1, 2, 3)
#del p.x # AttributeError: Not allowed
del p.z
hasattr(p, 'z')
[결과]
False
이터러블
- iter()를 구현한 객체
- iter()의 반환값은 임의의 이터레이터
이터레이터
- iter()와 next()를 구현한 객체
- iter()의 반환값은 자신(self)
# __iter__()
# 이터레이터 객체로 반환, 사용자 정의 클래스에서도 이 메서드를 구현해 이터러블로 사용 가능, for i in x: 에서 for 문은 x의 __iter__()를 호출해 그 반환값(이터레이터 객체)을 사용함
class Iterable:
def __init__(self, num):
self.num = num
def __iter__(self):
return iter(range(self.num)) # range() 반환 이터레이터
for i in Iterable(3): # __iter__() 호출
print(i)
print(iter(range(3)))
[결과]
0
1
2
<range_iterator object at 0x7efd92be97b0>
it = iter(range(10))
print(next(it))
next(it)
[결과]
0
1
# next() - 다음 엘리먼트 반환
class Reverser:
def __init__(self, x):
self.x = x
def __iter__(self):
return self
def __next__(self):
try:
return self.x.pop()
except IndexError:
raise StopIteration()
[val for val in Reverser([3, 1, 6, 4])]
[결과]
[4, 6, 1, 3]
# __getitem__(), __setitem__() - 인덱스와 키를 통해 접근해 호출 (x[1], x['key] 등)
from collections import defaultdict # 초기값은 int 타입 0
class CountDict:
def __init__(self):
self._data = {}
self._get_count = defaultdict(int)
self._set_count = defaultdict(int)
def __getitem__(self, key): # c['x'] 등 참조 시 호출
self._get_count[key] += 1
return self._data[key]
def __setitem__(self, key, value): # c['x'] = 1 등 대입 시 호출
self._set_count[key] += 1
self._data[key] = value
@property
def count(self):
return{
'set': list(self._set_count.items()),
'get': list(self._get_count.items()),
}
c = CountDict()
c['x'] = 10
c['x'] = 20
c['y'] = 30
c.count
[결과]
{'get': [], 'set': [('x', 2), ('y', 1)]}
[참고/출처] 효율적 개발로 이끄는 파이썬 실천 기술 - 파이썬에 숨겨진 힘을 이용해 개발 효율을 높이자!
블로그 인기글
폐업 신고 절차와 부가가치세 신고하는 방법
폐업 신고 시 세무서 안 가고 온라인으로 신고하는 방법인 '국세청 홈택스를 이용하여 폐업 신고하는 절차와 폐업 후 해야 하는 부가가치세 신고, 인건비 저리, 종합소득세 신고 등에 대해 포스팅합니다. 폐업 신고 시 홈택스 이용하는 방법과 부가가치세 등 신고 절차 여러가지 사유로 폐업을 해야 할 때, 예전에는 세무서를 방문해야 했지만 국세청 홈택스가 생긴 이후에는 사업자 등록이나 폐업 등을 인터넷으로 할 수가 있게 되었습니다. 특히, 코로나 시국인 요즘은 더더욱 온라인 신청 업무가 더 활성화되었죠. 폐업을 한다는 것 자체가 우울한 일인데, 발품을 파는 것보다는 커피 한잔 하면서 인터넷으로 간단하게 처리하는 게 좋을 듯하여 그 절차를 올려봅니다. 폐업은 폐업 신고와 함께 폐업 후 절차까지 모두 마쳐야 불이익이..
goodthings4me.tistory.com
[엑셀] 근무연수 및 근무 개월수 계산하는 함수
직장을 다니다 보면 몇 년 몇 개월 또는 전체 며칠을 다니고 있는지 궁금할 때가 있다. 아니면, 총무나 인사 일을 할 때 직원들의 근속연수 또는 근속개월수 등을 계산하고 싶을 때도 있다. 이런 경우 엑셀 함수를 활용하면 어떨까!! 근무연수 및 근무 개월수 계산 함수 알아보기 엑셀에서 근무연수 또는 근무 개월수 계산하는 것은 datedif() 함수를 사용하면 간단하게 해결할 수 있다. 아래 이미지를 보면서 설명하면, 셀 E1에 기준일자를 입력하고, 근무연수를 구할 때는 =datedif(B3,$E$1,"Y")&"년" 을 입력한다. 근무개월수는 =datedif(B3,$E$1,"M")&"개월" 처럼 입력한다. 일수까지 파악할 때문 별로 없지만, 심심풀이로 구해보고 싶을 때 =datedif(B3,$E$1,"D")..
goodthings4me.tistory.com
[국세청] 현금영수증가맹점으로 가입바랍니다. 메시지 해결방법(개인사업자)
▶ 현금영수증 가맹점 가입 메시지를 받고... 온라인 쇼핑몰 사업을 시작하려고 사업자등록증을 발급받고 난 후 얼마 안 있어서 국세청으로부터 어느 시점까지 '현금영수증 가맹점'으로 가입하라는 문자메시지가 받았었다. 그 메시지 기한이 오늘 도래했는데, 인터넷에서 찾아보니 홈택스에서 현금영수증 발급 사업자 신청을 할 수가 있었다. [관련내용] 홈>국세정책/제도>전자(세금)계산서/현금영수증/신용카드>현금영수증∙신용카드>가맹점가입 ▶ 홈택스 사이트에서 신청하는 절차는 다음과 같다. 우선, 홈택스에 로그인을 해야 합니다. 세상이 좋아져서 공인인증서 없이도 손쉽게 간편인증 로그인이 가능하다. 여러 인증방법 중 카카오톡 인증이 가장 편리한 거 같다. 간편인증 로그인 후 상단 '조회/발급' 탭 클릭 후 '현금영수증>현금..
goodthings4me.tistory.com
'코딩 연습 > 코딩배우기' 카테고리의 다른 글
[Python] 문자열 내 특수문자 제거 - replace(), isalnum(), join() 등 사용 (0) | 2021.06.23 |
---|---|
[Python] 폴더(디렉토리) 만들기 - mkdir() or makedirs() (0) | 2021.06.22 |
파이썬 실천 기술 #05 - 이름공간, 스코프 (0) | 2021.06.03 |
파이썬 실천 기술 #04 - 클래스와 인스턴스 (1) | 2021.05.26 |
파이썬 실천 기술 #03 - 함수 (0) | 2021.05.25 |
댓글