python 도움되는 메서드들
- map() 함수
map은 반복연산을 수행하는 파이썬 내장함수이다. 즉 for문으로 대체가 가능하다.
보통 lambda 문법이 같이 나온다.
list를 안붙일 경우 map object만 출력이 된다.
근데 list comprehension으로 대체 가능해서 딱히 안써도 된다.
a = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
print(list(map(lambda x: x**2, a)))
area = ["seoul,605", "busan,770", "daegu,884"
"incheon,1063", "gwangju,501", "ulsan,1062"]
names = list(map(lambda x: x.split(',')[0], area))
areas = list(map(lambda x: x.split(',')[1], area))
print(f"names = {names}")
print(f"areas = {areas}")
- lambda 문법
파이썬에서 함수는 하나의 객체다. 즉 함수를 변수처럼 사용할 수 있다.
def get_mean(array):
return sum(array) / len(array)
a = get_mean
print(a([3,4,5]))
위처럼 a에 함수를 할 수 있다. 이제 평균을 구하는 객체는 두 개가 된다. a는 변수고 get_mean은 def로 만든 함수지만 쓰는 방법은 똑같다. 즉, def를 통해서 이름을 지운 함수명은 그 자체로 변수가 된다.
함수를 객체화해서 얻는 장점으로는, 함수를 리스트에 넣어서 다룰 수 있고, 다른 함수의 argument로 사용할 수 있다. 여기서 argument로 받는 함수를 lambda로 쓰면 def으로 정의하지 않고도 사용할 수 있다. 즉 코드의 길이를 줄일 수 있다.
아래 두개의 코드는 같은 기능을 한다.
def print_ops(func, num1, num2):
print(func(num1, num2))
def multiply(a, b):
return a * b
def plus(a, b):
return a + b
print_ops(multiply, 41, 2)
print_ops(plus, 41, 2)
def print_ops(func, num1, num2):
print(func(num1, num2))
print_ops(lambda a, b: a*b, 41, 2)
print_ops(lambda a, b: a+b, 41, 2)
lambda는 한 statement로 return할 수밖에 없는 함수만 만들 수 있다. 즉 간단한 함수를 만들 때 사용한다.
- filter() 함수
filter는 함수 이름처럼 걸러주는 역할을 한다. 두 개의 argument를 받는다. 첫 번째는 거르는 기준이 되는 함수, 두 번째는 걸러질 list를 받는다. 그러면 리스트에서 값을 하나씩 함수에 집어넣어서 결과가 True면 남기고 False면 버린다. filter도 map과 마찬가지로 list comprehension으로 대체가 된다.
- *args와 **kwargs
값을 집어 넣는 쪽의 '*'는 list나 tuple의 bracket([], ())을 없앤다. 이 문법을 starred expression이라고 부른다.
def plane(a, b, c, d):
print(f"{a}x + {b}y + {c}z = {d}")
plane(3, 4.1, -7, 2.3)
plane(*[3, 4.1, -7, 2.3])
값을 받는 입장에서 '*'가 있을 경우 *변수 양 옆으로 변수 개수에 맞게 값이 들어가고 나머지는 *변수에 list로 들어간다. 아래의 경우 c에 빈리스트가 들어간다. 이 문법을 starred assignment라고 부른다. 값을 대입하고 남는 것을 다 *변수에 넣겠다는 의미다.
a, b, *c = 3, 4
a, b, *c = 3 // error
two starr**문법은 함수에서만 사용 가능하다. **로 변수를 집어넣을 때는 dictionary 타입의 변수를 사용한다. *문법처럼 괄호를 없애는 역할을 한다.
def func(a, b, c, d):
print(f'{a}x + {b}y + {c}z +{d} + 0')
func(**{'a':2, 'b':3, 'c':7, 'd':41})
반대로 함수를 선언할 때 **가 있으면, 등장한 적 없는 이름을 argument로 명시해서 dictionary로 집어넣을 수 있다.
def func(a, **b):
print(f'a = {a}')
print(f'b = {b}')
func(2, c=3, d=4)
이름을 안밝히고 대입해서 받는 것은 positional argument라 부르고, 이름을 명시해서 집어넣는 것은 keyword argument라 부른다. 아래의 코드에서 a, b가 positional arg를 받고 c,k가 keyword arg를 받게 된다.
# example
def func(a, *b, c=3, **k):
print(f'a = {a}')
print(f'b = {b}')
print(f'c = {c}')
print(f'k = {k}')
func(1, 2, 3, 4, e=5, f=4, c=2, d=41)
!!-- output -- !!
a = 1
b = (2, 3, 4)
c = 2
k = {'e': 5, 'f': 4, 'd': 41}
- @classmethod
class Ex():
def met1(self, value):
self.vaiable = value
@classmethod
def met2(self,value):
self.vaiable = value
a = Ex()
b = Ex()
a.met2(999)
print(b.vaiable)
# output
999
위의 코드에서 a의 메소드를 통해 met2를 바꿨는데 b까지 바뀌었다.
@classmethod를 쓰면 인스턴스 내부가 아닌 클래스 전체 관점에서의 변수를 다룰 수 있다.
class인스턴스 모두가 공유하는 보편적인 값을 설정하고 싶을 때 이 문법을 사용한다.
보통, @classmethod를 쓴 메소드의 첫 번째 argument는 클래스의 보편적인 값을 다룬다는 점에서 클래스의 약자인 cls를 쓰는 경우가 많다.
class Member():
_ins = []
def __init__(self, name, height, weight, fat):
self.name = name
self.hegiht = height
self.weight = weight
self.fat = fat
self.add_instace(self)
@classmethod
def add_instacne(cls, ins):
cls._ins.append(ins)
위의 코드에서 멤버를 계속 추가하다가 전체 멤버의 평균 키가 필요할 경우, 생성자 함수에 @classmethod를 이용해 만든 함수를 넣을 경우 클래스가 선언될 때마다 자동으로 클래스 변수에 저장된다. 즉, _inst 클래스 변수가 일종의 멤버목록이 되는 것이다. 그럼 평균 키는 아래의 코드처럼 구하면 된다.
height_mean = sum([m.height for m in Member._ins]) / len(Member._ins)
- @property
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
@property
def age(self):
return self._age
p = Person('edward', 29)
print(p.age)
class의 메소드를 부를 때는 괄호를 붙여서 함수를 부르듯이 사용한다. 그러나 @property를 붙인 메소드는 사용할 때 메소드 이름만 부른다. 그렇기 때문에 @property가 붙은 함수는 argument를 받지 못한다.
이와 반대로 인스턴스 변수를 대입할 때는 @이름.setter를 사용할 수 있다. 대입 연산자 뒤의 값을 첫 번째 argument로 사용하게 된다.