Programming,  Python

[Python] 함수의 특징 – 2

가변 인자

Python에서도 C와 C++처럼 가변인자가 존재한다.
Python에선 * 를 통해서 가변인자를 인식하며, 해당 가변인자들은 tuple 타입으로 전달된다.

def fprintf(file, fmt, *args):
    file.write(fmt % args)
#   file.write(fmt % (42, "hello world", 3.45)) // Same

fprintf(sys.stdout, "%d %s %f", 42, "hello world", 3.45)
42 hello world 3.450000

위 코드같은 경우엔 args 인자들이 tuple (42, “hello world”, 3.45) 타입으로 들어온다.

위 코드를 C style printf() 함수로 구현해본다면 다음과 같다.

def printf(fmt, *args):
    fprintf(sys.stdout, fmt, *args)

printf("%d %s %f", 42, "hello world", 3.45)

가변 인수

기본적으로 함수의 인자는 순서대로 넣는게 맞지만, 순서에 상관없이 symbol name을 통해 넣을 수 있다.

def foo(x, w, y, z):
    print(x,w,y,z)

foo(x=3, y=22, w='hello', z=[1,2])
3 hello 22 [1, 2]

키워드 인자를 쓸 때 키워드 인자를 안쓸 경우엔 반드시 순서대로 인자가 전달되기 때문에 다음과 같은 경우를 유의해야한다.

foo(3, 22, w='hello', z=[1,2])
TypeError Traceback (most recent call last)
in
—-> 1 foo(3, 22, w=’hello’, z=[1,2])
TypeError: foo() got multiple values for argument ‘w’

w는 이미 22로 assign이 됐는데 다시 한 번 w에 ‘hello’를 입력했기 때문에 error가 발생했다.

가변 키워드 인수

가변 키워드 인수는 키워드 자체를 유저가 키워드 또한 인자값과 함께 전달할 수 있다.

def make_table(data, **parms):
    fgcolor = parms.pop("fgcolor", "black")
    bgcolor = parms.pop("bgcolor", "white")
    width = parms.pop("width", None)
    print(fgcolor)
    print(bgcolor)
    print(width)
    if parms:
        raise TypeError("UnSupported configuration options %s"% list(parms))
items=[1,2,3]
make_table(items, fgcolor="red", bgcolor="black",
          border=1, borderstyle="grooved",width=400)
red
black
400

TypeError Traceback (most recent call last)
in
10 items=[1,2,3]
11 make_table(items, fgcolor=”red”, bgcolor=”black”,
—> 12 border=1, borderstyle=”grooved”,width=400)
in make_table(data, **parms)
7 print(width)
8 if parms:
—-> 9 raise TypeError(“UnSupported configuration options %s”% list(parms))
10 items=[1,2,3]
11 make_table(items, fgcolor=”red”, bgcolor=”black”,
TypeError: UnSupported configuration options [‘border’, ‘borderstyle’]

위 함수를 분석해보면 ** 매크로는 가변 키워드 인수를 뜻하는데, 원하는 키워드의 인수를 parsing 할 수 있다.

parms.pop("fgcolor", "black") 는 fgcolor 키워드의 인자가 들어오면 그 값을 fgcolor 변수에 저장하고, 그렇지 않을 경우 default로 “black” 을 저장하라는 의미다.

만약 parms에 추가적으로 인자들이 남아있을 경우에 if statement에 들어가면서 error handling이 되도록 program 되어있다.

키워드 매개변수만 받는 함수

def recv(maxsize, *, block=True):
    print(maxsize, block)

recv(8192, block=False)        
try:
    recv(8192, False)          
except TypeError as e: # 예외처리
    print(e)

Python에서 인자가 *이면 가변인자가 된다고 말했다. 위 코드는 두 번째 인자인 block에 값을 전달할 때 반드시 키워드 block 을 입력해야지 error가 발생하지 않는다.
이 방법을 통해 block 키워드를 입력시키도록 하여서 가독성을 높일 수 있다.

def minimum(*values, clip=None):
    m = min(values)
    if clip is not None:
        m = clip if clip > m else m
    return m

print(minimum(1, 5, 2, -5, 10))
print(minimum(1, 5, 2, -5, 10, clip=0))
-5
0

위 함수에서 키워드 매개 변수 clip을 따로 지정하지 않게 되면 모두 values가변 인자로 전달된다.
위 코드를 분석해보면, clip 이 들어오지 않으면 최소값을 전달하며, clip 값이 전달되면 최소 값이 clip 보다 작으면 clip 을 전달하고 그렇지 않으면 최소 값을 전달하도록 된다.

a = [1, 2, 3, 4, 5]
def square(items):
    for i, x in enumerate(items):
        items[i] = x * x

square(a)
print(a)
[1, 4, 9, 16, 25]

위 코드에서 for 문에 i, x가 있는데, i에는 index가 들어가며 x에는 list의 값이 들어간다. 이는 enumerate() 함수의 return 값으로 index와 value를 리턴하기 때문이다.
실제 결과를 list와 dict 타입으로 변환해 출력해보면 다음과 같다.

a = [1, 2, 3, 4, 5]
b = list(enumerate(a))
c = dict(enumerate(a))
print(b)
print(c)
[(0, 1), (1, 4), (2, 9), (3, 16), (4, 25)]
{0: 1, 1: 4, 2: 9, 3: 16, 4: 25}

Python에선 함수의 return을 2개 또는 3개 이상으로도 전달 할 수 있다.

def divide(a,b):
    return (a//b,a%b)

x, y = divide(10,3)
print(x)
print(y)
3
1

devide 함수의 return은 tuple type이기 때문에 tuple unpacking에 의해서 lvalue의 x와 y에 각각 assign 된다.

Leave a Reply

Your email address will not be published. Required fields are marked *