Skip to content

jiunbae/chaintools

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

chaintools

Function chaining

Function 를 활용해 함수를 연결 할 수 있습니다.

from chaintools import Function as F

def add(tar: int) -> Callable[[int], int]:
    def _wrapper(src: int) -> int:
        return src + tar
    return _wrapper

# f = int -> int -> int -> int
f = F >> add(1) >> add(2)
assert f(3) == 6

함수의 반환 형태가 Tuple[Tuple[Any, ...], Dict[str, Any]] 형태일 때는 특수한 Argument.TYPE으로 여겨지며, 다음 함수 인자에 *args, **kwargs와 같은 형태로 전달할 수 있습니다.

from chaintools import Argument

def return_args_and_kwargs() -> Tuple[Tuple[Any, ...], Dict[str, Any]]:
    return (1, 2), {'c': 1, 'd': 2}

def add_four_variable(a, b, c, d) -> int:
    return a + b + c + d

# f = None -> Tuple[Tuple[Any, ...], Dict[str, Any]](Argument.TYPE) -> int
f = F >> return_args_and_kwargs >> add_four_variable
assert f() == 6

또는 함수 사이에 Function.spread를 활용해서 Iterable형태의 결과 값을 다음 함수의 *args 형태로 전달할 수 있습니다.

def return_args() -> Iterable[int]:
    return 1, 2

def return_args_as_argument() -> Tuple[Tuple[Any, ...], Dict[str, Any]]:
    return (1, 2), None

def add_two_variable(a, b) -> int:
    return a + b

# f = None -> Iterable[int] -> [int, ...] -> int
f = F >> return_args >> F.spread() >> add_two_variable
# g = None -> Tuple[Tuple[Any, ...], Dict[str, Any]]([int, ...]) -> int
g = F >> return_args_as_argument >> add_two_variable
assert f() == g() == 3

Function map, filter

Function.mapFunction.filter를 사용해서 데이터를 처리할 수 있습니다.

def to_float(a):
    return float(a)

def to_str(a):
    return str(a)

# f = Any -> float -> str
f = F >> to_float >> to_str
result = f.map(range(10))
assert tuple(result) == tuple(map(to_str, map(to_float, range(10))))
def is_even(a):
    return a % 2 == 0

def is_not_zero(a):
    return a != 0

# f = Any -> bool -> bool
f = F >> is_even >> is_not_zero
result = f.filter(range(10))
assert tuple(result) == tuple(filter(is_not_zero, filter(is_even, range(10))))

Function.mapFunction.filter도 함수이기 때문에 chaining 할 수 있습니다. (단, 형태가 Iterable -> Iterable이어야 합니다. 즉 일반적인 Any -> Any 형태의 함수와 Iterable -> Iterable형태의 함수는 함께 사용할 수 없습니다.)

# f = Iterable[Any] -> Iterable[Any] -> Iterable[Any]
f = F >> F([add(1), to_float]).map >> F(is_even).filter >> F(add(1)).map
result = f(range(10))
assert tuple(result) == (3.0, 5.0, 7.0, 9.0, 11.0)

Function annotation

str(Function)을 이용해서 annotation을 확인할 수 있습니다. 만약 이전 함수의 반환 값과 다음 함수의 인자 형태가 맞지 않는다면 {이전 함수 반환}({다음 함수 인자})로 표시됩니다.

def int_to_str(a: int) -> str:
    return str(a)

def str_to_float(a: str) -> float:
    return float(a)

def float_to_tuple(a: float) -> Tuple[int, int]:
    return (int(a), int(a))

# f = int -> str -> float -> Tuple[int, int]
f = F >> int_to_str >> str_to_float >> float_to_tuple
# g = int -> str(float) -> Tuple[int, int]
g = F >> int_to_str >> float_to_tuple
assert str(f) == "Function(int -> str -> float -> tuple[int, int])"
assert str(g) == "Function(int -> str(float) -> tuple[int, int])"
  • Function.signature는 함수의 시그니쳐를 Iterable[Signature]형태로 반환합니다.
  • Function.annotation은 함수의 annotation을 chaintools.core.type.annotation.Annotation형태로 반환합니다.