Excel & IT Info

아이엑셀러 닷컴, 엑셀러TV

Python

프로그래머가 인식하지 못하는 파이썬 숨겨진 기능

권현욱(엑셀러) 2024. 1. 3. 20:00
반응형

누구나 일상적인 코딩에 사용할 수 있는 기술이나 기능이지만 평범함을 뛰어넘는 것이 있습니다. 끊임없이 진화하는 파이썬 생태계에서 중요한 몇 가지 기능을 소개합니다.

 

권현욱(엑셀러) | 아이엑셀러 닷컴 대표 · Microsoft Excel MVP · Excel 솔루션 프로바이더 · 작가

 

※ 이 글은 아래 기사 내용을 토대로 작성되었습니다만, 필자의 개인 의견이나 추가 자료들이 다수 포함되어 있습니다.


  • 원문: Python: Hidden Features ㅡ part 1
  • URL: https://pravash-techie.medium.com/python-hidden-features-part-1-3d9817a0385e

1. 함수 객체

파이썬의 모든 것은 어떤 클래스에서 인스턴스화된 객체입니다. 여기에는 기능도 포함되지만, 이 사실을 받아들이는 것이 처음에는 직관에 어긋나는 것처럼 느껴질 때가 많습니다. 예를 들어 보겠습니다.

def add_subject(name, subject, subjects=[]):
    subjects.append(subject)
    return {'name': name, 'subjects': subjects}

add_subject('person1', 'subject1')
add_subject('person2', 'subject2')
add_subject('person3', 'subject3')


output - 
{'name': 'person1', 'subjects': ['subject1']}
{'name': 'person2', 'subjects': ['subject1', 'subject2']}
{'name': 'person3', 'subjects': ['subject1', 'subject2', 'subject3']}

 

Python의 가변성은 아마도 가장 오해되고 간과되는 개념 중 하나일 것입니다. 함수의 기본 매개변수는 함수가 정의되는 순간 바로 평가됩니다. 따라서 함수가 정의되자마자 함수 객체는 해당 __defaults__속성에 기본 매개변수를 저장합니다. 아래에서 이를 확인할 수 있습니다.

def my_functions(a=1, b=2, c=3):
    pass

print(my_functions.__defaults__)

output - (1, 2, 3)

 

따라서 함수에 변경 가능한 기본 매개변수를 지정하고 이를 변경하는 경우 해당 함수에 대한 향후 모든 호출에 대해 자신도 모르게, 의도치 않게 매개변수를 수정하게 됩니다.

이는 아래 데모에 나와 있습니다. 함수를 호출할 때마다 새 목록을 만드는 대신 Python은 요소를 동일한 복사본에 추가합니다.

def add_subject(name, subject, subjects=[]):
    subjects.append(subject)
    return {'name': name, 'subjects': subjects}

print(add_subject.__defaults__)

add_subject('person1', 'subject1')
print(add_subject.__defaults__)

add_subject('person2', 'subject2')
print(add_subject.__defaults__)

add_subject('person3', 'subject3'))
print(add_subject.__defaults__)

Output - 
([],)
(['subject1'],)
(['subject1', 'subject2'],)
(['subject1', 'subject2', 'subject3'],)

 

피하는 방법

함수 정의에 변경 가능한 기본 매개변수를 지정하는 대신 None. 함수 호출 중에 함수가 해당 값을 받지 못하면 함수 내부에 가변 객체를 생성합니다.

def add_subject(name, subject, subjects=None):
    if subjects is None:
        subjects = []

    subjects.append(subject)
    return {'name': name, 'subjects': subjects}

print(add_subject.__defaults__)
print(add_subject('person1', 'subject1'))
print(add_subject('person2', 'subject1'))
print(add_subject('person3', 'subject1'))


## Output - 
(None,)
{'name': 'person1', 'subjects': ['subject1']}
{'name': 'person2', 'subjects': ['subject1']}
{'name': 'person3', 'subjects': ['subject1']}

 

위에 표시된 대로 함수가 호출될 때 아무런 값도 받지 못한 경우 새 목록을 만듭니다. 이를 통해 동일한 객체를 변경하는 예기치 않은 동작을 방지할 수 있습니다.

 

2. 클래스 객체를 함수처럼 동작하게 만들기

클래스 객체를 호출 가능하게 만들려면, 즉 함수처럼 동작하게 하려면 __applet__ 메서드를 정의하면 됩니다. 이 메소드를 사용하면 함수처럼 호출될 때 객체의 동작을 정의할 수 있습니다.

class Multiplier:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

    def __call__(self, x):
        return (self.a * x**2) + (self.b * x**2) + (self.c * x**2)


func = Multiplier(2, 4, 6)
print(func(2))    # 48
print(func(4))    # 192
print(callable(func))    # True

 

이는 많은 장점을 가질 수 있습니다. 예를 들어 유연하고 직관적인 방식으로 사용할 수 있는 객체를 구현할 수 있습니다. 게다가 익숙한 함수 호출 구문을 사용하면 코드를 더 읽기 쉽게 만들 수 있습니다.

이를 통해 callable이 예상되는 컨텍스트에서 클래스 객체를 사용할 수 있습니다. 예를 들어 클래스를 데코레이터로 사용합니다.

 

3. 스트링 메서드

최근에 파이썬의 문자열 메서드에 대해 알게 된 새롭고 멋진 사실이 있습니다.

파이썬에서는 문자열의 시작과 끝에서 하위 문자열을 일치시키는 데 일반적으로 startswith 및 endswith 문자열 메서드를 사용합니다.

places = ["India", "London", "Poland", "Netherlands"]
for place in places:
    if place.startswith('Lo') or place.startswith('Po'):
        print(place)

 

그러나 여러 하위 문자열을 이러한 메서드에 튜플로 전달할 수도 있다는 것을 아시나요?

places = ["India", "London", "Poland", "Netherlands"]
for place in places:
    if place.startswith(('Lo', 'Po')):
        print(place)

 

이렇게 하면 동일한 기능을 유지하면서 여러 조건을 작성하는 것을 방지할 수 있습니다.

 

4. Frozenset 사용

Python의 사전에는 키가 변경 불가능해야 합니다. 결과적으로 세트는 변경 가능하므로 키로 사용할 수 없습니다.

set_ex = {1, 2, 3}
dict_obj = {set_ex: "This is a Set"}

## Error - TypeError: unhashable type: 'set'

 

세트를 사용하려면 이를 고정 세트로 선언하는 것이 좋습니다.

set_ex = frozenset({1, 2, 3})
dict_obj = {set_ex: "This is a Set"}

print(dict_obj[set_ex])

## Output - This is a Set

 

이는 불변 집합입니다. 즉, 생성된 후에 해당 요소를 변경할 수 없습니다. 따라서 사전의 키로 안전하게 사용할 수 있습니다.

 

5. 피클 파일

피클(Pickles)은 데이터 개체를 디스크에 덤프하는 데 널리 사용됩니다. 하지만 사람들은 종종 하나의 개체만 피클 파일에 덤프합니다. 또한 여러 개의 개체를 저장하기 위해 여러 개의 피클을 만들기도 합니다.

하지만 하나의 피클 파일 안에 원하는 만큼의 개체를 저장할 수 있다는 사실을 알고 계셨나요? 게다가 다시 로드할 때 모든 개체를 로드할 필요가 없습니다. 동일한 컨텍스트 관리자(𝐰𝐢𝐭𝐡 사용) 내에서 개체를 덤프하기만 하면 됩니다.

 

import pickle

a, b, c = 1, 2, 3

with open("data.pkl", "wb") as f:
    pickle.dump(a, f)
    pickle.dump(b, f)
    pickle.dump(c, f)
import pickle

with open("data.pkl", "rb") as f:
    a = pickle.load(f)
    b = pickle.load(f)

print(f"{a = } {b = }")

 

더욱 다양한 정보를 보려면 아이엑셀러 닷컴을 방문하세요. 최신 동영상을 보려면 YouTube 채널을 구독하세요.