LANGUAGE/Python, Django

python 도움되는 메서드들

axelrod입니다 2024. 12. 2. 18:28

 

- 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로 사용하게 된다.