블로그 이미지
Peter Note
Web & LLM FullStacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Category

Recent Post

2024. 8. 11. 14:31 LLM FullStacker/Python

 

1. Dictionary 병합

LangChain 소스를 분석하다 이런 코드를 보았다.

class ChatPromptTemplate(BaseChatPromptTemplate):
    def __init__(
        self,
        messages: Sequence[MessageLikeRepresentation],
        *,
        template_format: Literal["f-string", "mustache", "jinja2"] = "f-string",
        **kwargs: Any,
    ) -> None:
        ...
        // 파이썬 초보자가 봤을 때 이게 뭐지?  
        kwargs = {
            **dict(
                input_variables=sorted(input_vars),
                optional_variables=sorted(optional_variables),
                partial_variables=partial_vars,
            ),
            **kwargs,
        }

이 코드에서 kwargs 변수를 정의하는 방식은 Python에서 딕셔너리를 병합하는 기법 중 하나입니다. 이 코드의 주요 목적은 두 개의 딕셔너리를 결합하여 하나의 딕셔너리를 만드는 것입니다. 여기서 kwargs는 일반적으로 함수나 메소드에서 사용되는 키워드 인수들을 담고 있는 딕셔너리입니다.

코드의 의미 분석

kwargs = {
    **dict(
        input_variables=sorted(input_vars),
        optional_variables=sorted(optional_variables),
        partial_variables=partial_vars,
    ),
    **kwargs,
}
  1. dict(...):
    • dict(...) 표현식은 새로운 딕셔너리를 생성합니다.
    • 이 딕셔너리는 세 개의 키-값 쌍을 가지고 있습니다:
      • input_variables: input_vars를 정렬한 리스트.
      • optional_variables: optional_variables를 정렬한 리스트.
      • partial_variables: partial_vars라는 변수에 담긴 값.
  2. sorted(input_vars)sorted(optional_variables):
    • sorted(input_vars)sorted(optional_variables)는 각각 input_varsoptional_variables 리스트를 정렬한 결과를 반환합니다.
    • 이 결과는 새로운 딕셔너리의 값으로 사용됩니다.
  3. **dict(...):
    • ** 연산자는 딕셔너리 언패킹 연산자입니다. 이 연산자를 사용하면 딕셔너리의 키-값 쌍을 다른 딕셔너리로 풀어서 넣을 수 있습니다.
    • **dict(...)input_variables, optional_variables, partial_variables라는 키와 그에 대응하는 값들을 풀어서 {}로 감싸인 새로운 딕셔너리로 만듭니다.
  4. **kwargs:
    • 기존의 kwargs 딕셔너리도 **kwargs로 언패킹되어 추가됩니다.
    • 이때, 만약 kwargs 딕셔너리에 input_variables, optional_variables, partial_variables와 동일한 키가 존재하면, kwargs 딕셔너리의 값이 우선하여 기존 값을 덮어씁니다.
  5. 최종 kwargs 딕셔너리:
    • 최종적으로, 첫 번째 dict(...)로 생성된 딕셔너리와 기존의 kwargs 딕셔너리가 병합된 새로운 kwargs 딕셔너리가 만들어집니다.
    • 이 딕셔너리는 함수나 메소드에 전달될 키워드 인수들로 사용될 수 있습니다.

예시

input_vars = ['var3', 'var1', 'var2']
optional_variables = ['opt3', 'opt1', 'opt2']
partial_vars = {'part1': 'value1'}

kwargs = {'input_variables': ['override_var'], 'new_key': 'new_value'}

kwargs = {
    **dict(
        input_variables=sorted(input_vars),
        optional_variables=sorted(optional_variables),
        partial_variables=partial_vars,
    ),
    **kwargs,
}

print(kwargs)

위 코드를 실행하면, 최종 kwargs 딕셔너리는 다음과 같이 출력됩니다:

{
    'input_variables': ['override_var'],  # kwargs에서 덮어씌워짐
    'optional_variables': ['opt1', 'opt2', 'opt3'],
    'partial_variables': {'part1': 'value1'},
    'new_key': 'new_value'
}

요약

  • 이 코드는 dict(...)로 만든 딕셔너리와 기존 kwargs 딕셔너리를 병합하여 새로운 kwargs 딕셔너리를 생성합니다.
  • **dict(...)**kwargs를 사용하여 두 딕셔너리를 결합합니다. 중복되는 키가 있을 경우, kwargs에 있는 값이 우선합니다.
  • 이 기법은 키워드 인수를 동적으로 처리할 때 유용합니다.

2. sorted 용법에 대한 궁금증

sorted는 Python의 내장 함수 중 하나로, 주어진 iterable(리스트, 튜플, 문자열 등)의 요소들을 정렬하여 새로운 리스트로 반환하는 함수입니다. sorted는 원본 데이터를 변경하지 않고, 정렬된 새로운 리스트를 반환합니다.

 

sorted 함수의 기본 사용법

sorted(iterable, key=None, reverse=False)

iterable: 정렬할 대상이 되는 iterable 객체(예: 리스트, 튜플, 문자열 등).

key: 정렬 기준을 지정하는 함수. 각 요소에 대해 이 함수가 호출된 결과를 기준으로 정렬합니다.

reverse: True로 설정하면 내림차순으로 정렬하고, 기본값인 False는 오름차순으로 정렬합니다.

 

예시

 

1. 리스트 정렬:

numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]
sorted_numbers = sorted(numbers)
print(sorted_numbers)  # [1, 1, 2, 3, 4, 5, 5, 6, 9]

 

2. 문자열 정렬:

word = "python"
sorted_letters = sorted(word)
print(sorted_letters)  # ['h', 'n', 'o', 'p', 't', 'y']

 

3. 튜플 정렬:

tuples = [(1, 'b'), (3, 'a'), (2, 'c')]
sorted_tuples = sorted(tuples)
print(sorted_tuples)  # [(1, 'b'), (2, 'c'), (3, 'a')]

 

4. key 매개변수 사용:

key 매개변수는 정렬 기준을 정의하는 함수입니다. 각 요소에 대해 이 함수가 호출된 결과를 기준으로 정렬됩니다.

words = ["apple", "banana", "cherry", "date"]
sorted_words = sorted(words, key=len)
print(sorted_words)  # ['date', 'apple', 'banana', 'cherry']

 

5. reverse=True 사용:

정렬 결과를 내림차순으로 반환합니다.

numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]
sorted_numbers_desc = sorted(numbers, reverse=True)
print(sorted_numbers_desc)  # [9, 6, 5, 5, 4, 3, 2, 1, 1]

 

요약

 

sorted 함수는 iterable의 요소를 정렬하여 새로운 리스트로 반환합니다.

key 매개변수를 사용하여 정렬 기준을 설정할 수 있으며, reverse 매개변수를 사용하여 정렬 방향(오름차순/내림차순)을 설정할 수 있습니다.

원본 데이터는 변경되지 않으며, 정렬된 새로운 리스트가 반환됩니다.


3. cast 에 대한 궁금증

cast는 Python의 타입 힌팅(type hinting)과 관련된 기능 중 하나로, typing 모듈에서 제공하는 함수입니다. cast는 특정 값을 지정된 타입으로 “캐스팅”한다고 표시하는 역할을 합니다. 그러나 실제로 값을 변환하거나 변경하지는 않으며, 주로 타입 힌팅을 통해 코드의 가독성을 높이고, 정적 분석 도구들이 올바른 타입을 추론하도록 돕기 위한 목적으로 사용됩니다.

 

cast의 기본 사용법

from typing import cast

cast(typ, val)

typ: 캐스팅할 타입. Python의 타입(예: int, str, List[int] 등)이나 사용자 정의 클래스 등을 지정할 수 있습니다.

val: 실제 값. typ로 캐스팅할 값입니다.

 

cast의 역할

 

정적 분석 지원: cast는 Python 코드에서 변수나 표현식의 타입을 명시적으로 지정하는 데 사용됩니다. 정적 분석 도구나 IDE에서 코드의 타입을 더 잘 이해하고, 타입 관련 경고나 오류를 감지하는 데 도움이 됩니다.

런타임에는 아무 영향 없음: cast는 런타임에 아무런 영향을 미치지 않습니다. 즉, cast를 사용해도 실제로 값의 타입이 변경되거나 변환되지 않습니다.

 

예시

 

1. 기본 사용법:

from typing import cast, List

def get_items() -> List[str]:
    return ["apple", "banana", "cherry"]

items = cast(List[str], get_items())
print(items)  # ['apple', 'banana', 'cherry']

여기서 cast(List[str], get_items())get_items()의 반환값이 List[str] 타입임을 명시적으로 지정합니다.

 

2. 변수 타입 힌트:

from typing import cast

value: int = cast(int, "42")  # 정적 분석 도구에게 value가 int임을 알려줌
print(value)  # "42", 실제로는 str 타입임

이 예시에서 cast(int, "42")"42"int 타입이라고 명시하지만, 실제로는 str 타입입니다. 이 코드에서 cast는 단지 정적 타입 힌팅을 위한 것이며, value의 타입이 실제로 int로 변환되지 않습니다.

 

3. 사용자 정의 클래스:

from typing import cast

class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

def get_animal() -> Animal:
    return Dog()

animal = cast(Dog, get_animal())
print(animal.speak())  # "Woof!", 정적 분석 도구는 animal을 Dog로 간주함

여기서 cast(Dog, get_animal())get_animal()이 반환하는 객체가 Dog 타입임을 명시적으로 지정하여, animal 변수가 Dog로 간주되도록 합니다. 실제로는 get_animal()이 반환하는 객체가 Dog이기 때문에 문제가 없지만, 정적 분석 도구에 명시적으로 알려주기 위해 사용됩니다.

 

요약

 

cast는 Python에서 타입 힌팅을 명시적으로 지정하기 위한 도구로, 런타임에는 영향을 미치지 않습니다.

주로 정적 분석 도구나 IDE에서 타입 추론을 돕기 위해 사용됩니다.

cast는 값의 실제 타입을 변경하지 않으며, 코드의 가독성과 안전성을 높이는 역할을 합니다.

posted by Peter Note