파이썬에서 다른 함수에 인수가있는 함수를 전달 하시겠습니까?


203

파이썬에서 인수가있는 함수를 다른 함수에 전달할 수 있습니까?

다음과 같이 말하십시오 :

def perform(function):
    return function()

그러나 전달 될 함수는 다음과 같은 인수를 갖습니다.

action1()
action2(p)
action3(p,r)

답변:


289

당신은 이것을 의미합니까?

def perform( fun, *args ):
    fun( *args )

def action1( args ):
    something

def action2( args ):
    something

perform( action1 )
perform( action2, p )
perform( action3, p, r )

10
명명 된 매개 변수는 어떻습니까? 즉 def action1(arg1, arg2=None, arg3=None), 예를 들어 arg3에 할당하려는 인수를 어떻게 전달할 수 있습니까?
ChaimKut


어떤 경우 performaction1, action2다른 파일에? @ S.Lott
alper

@alper 수입
pfabri

122

이것이 람다의 목적입니다.

def Perform(f):
    f()

Perform(lambda: Action1())
Perform(lambda: Action2(p))
Perform(lambda: Action3(p, r))

7
또한 호기심으로 람다는 왜이 사건에 좋지 않은지 말해 줄 수 있습니까?
Joan Venge

11
람다는 좋은 프로그래밍 언어의 최고의 기능 중 하나입니다. 불행히도 파이썬의 구현은 심각하게 제한되어 있습니다. 그러나이 경우에는 완벽하게 맞습니다
Javier

3
제한된 구문이 거의 불투명하다는 것을 알았습니다. 그들은 n00bz에 설명하기 어렵다. 예, 여기에서 작동하며 구문의 혼란스러운 기능이 없습니다. 이것은 아마도 모호하지 않은 람다에서 본 유일한 예일 것입니다.
S.Lott 2016

11
전달 된 함수의 결과를 검색 할 수 있도록 f ()를 호출하는 것보다 Perform ()이 "return f ()"를 호출하는 것이 더 좋지 않습니다.
mhawke 2009

나는 람다 버전이 매우 깔끔하다고 생각하지만, 테스트에서 다른 답변에서 논의 된 fn (* args) 메소드보다 람다를 통해 함수를 호출하는 것이 느리다고 생각합니다.
Richard Shepherd

39

functools에서 부분 기능을 사용할 수 있습니다.

from functools import partial

def perform(f):
    f()

perform(Action1)
perform(partial(Action2, p))
perform(partial(Action3, p, r))

키워드와도 작동

perform(partial(Action4, param1=p))

1
functools.partialperform에 추가 매개 변수를 넘겨야하는 경우에도 더욱 다양합니다 f. 예를 들어, 전화를 걸 perform(partial(Action3, p))거나 perform(f)다음과 같은 작업을 수행 할 수 f("this is parameter r")있습니다.
Robert

13

람다가 아닌 functools.partial을 사용하십시오! 그리고 ofc Perform은 쓸모없는 기능이므로 직접 함수를 전달할 수 있습니다.

for func in [Action1, partial(Action2, p), partial(Action3, p, r)]:
  func()


3
수행의 호출 사이트에서 인수를 평가할지 여부에 따라 다릅니다.
Dave

6

(몇 달 후) 람다가 유용한 작은 실제 예는 부분적으로는 아닙니다
.
quadf( x, f )1-d를 취하여 다양한를 f호출합니다 x.
y = -110에서 수직 절단과 x = -110에서 수평 절단에 대해 호출하려면,

fx1 = quadf( x, lambda x: f( x, 1 ))
fx0 = quadf( x, lambda x: f( x, 0 ))
fx_1 = quadf( x, lambda x: f( x, -1 ))
fxy = parabola( y, fx_1, fx0, fx1 )

f_1y = quadf( y, lambda y: f( -1, y ))
f0y = quadf( y, lambda y: f( 0, y ))
f1y = quadf( y, lambda y: f( 1, y ))
fyx = parabola( x, f_1y, f0y, f1y )

내가 아는 한, partial이것을 할 수 없습니다.

quadf( y, partial( f, x=1 ))
TypeError: f() got multiple values for keyword argument 'x'

(이에 numpy, partial, lambda 태그를 추가하는 방법은 무엇입니까?)


5

이를 부분 함수라고하며이를 수행하는 방법에는 최소한 3 가지가 있습니다. 내가 가장 좋아하는 방법은 추가 패키지에 대한 종속성을 피하고 가장 장황하지 않기 때문에 람다를 사용하는 것입니다. 함수가 있고 다른 함수가에 대한 값을 결정하도록 매개 변수로 다른 함수 add(x, y)에 전달하려고 한다고 가정하십시오 .add(3, y)y

람다 사용

# generic function takes op and its argument
def runOp(op, val):
    return op(val)

# declare full function
def add(x, y):
    return x+y

# run example
def main():
    f = lambda y: add(3, y)
    result = runOp(f, 1) # is 4

나만의 래퍼 만들기

여기서 부분 함수를 반환하는 함수를 만들어야합니다. 이것은 훨씬 더 장황하다.

# generic function takes op and its argument
def runOp(op, val):
    return op(val)

# declare full function
def add(x, y):
    return x+y

# declare partial function
def addPartial(x):
    def _wrapper(y):
        return add(x, y)
    return _wrapper

# run example
def main():
    f = addPartial(3)
    result = runOp(f, 1) # is 4

functools에서 부분 사용

이것은 lambda위에 표시된 것과 거의 동일합니다 . 그렇다면 왜 우리는 이것을 필요로합니까? 있다 몇 가지 이유가 . 요컨대, partial어떤 경우에는 조금 더 빠를 수 있으며 ( 구현 참조 ) 초기 바인딩과 람다의 늦은 바인딩에 사용할 수 있습니다.

from functools import partial

# generic function takes op and its argument
def runOp(op, val):
    return op(val)

# declare full function
def add(x, y):
    return x+y

# run example
def main():
    f = partial(add, 3)
    result = runOp(f, 1) # is 4

1

클로저로 수행하는 방법은 다음과 같습니다.

    def generate_add_mult_func(func):
        def function_generator(x):
            return reduce(func,range(1,x))
        return function_generator

    def add(x,y):
        return x+y

    def mult(x,y):
        return x*y

    adding=generate_add_mult_func(add)
    multiplying=generate_add_mult_func(mult)

    print adding(10)
    print multiplying(10)

어쨌든 하나의 함수를 다른 하나의 클로저에 전달하는 것 이상을 수행해야합니다.
jake77
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.