2016-11-08 49 views
0

我看到一个Python函数调用方式Keras'教程这样的:在Python中调用函数的意义?

from keras.layers import Input, Dense 
from keras.models import Model 

# this returns a tensor 
inputs = Input(shape=(784,)) 

# a layer instance is callable on a tensor, and returns a tensor 
x = Dense(64, activation='relu')(inputs) 

但是,我不知道的功能是什么意思调用形式:

x = Dense(64, activation='relu')(inputs) 

为什么会出现“(输入)”在功能“密集”的参数列表的括号之外?

+1

的[?什么是“柯里”]可能的复制(http://stackoverflow.com/questions/36314/what-is- currying) –

回答

5

因为Dense(...)返回一个可调用函数(基本上是一个函数),因此可以依次调用它。这里有一个简单的例子:

def make_adder(a): 
    def the_adder(b): 
     return a + b 
    return the_adder 

add_three = make_adder(3) 
add_three(5) 
# => 8 

make_adder(3)(5) 
# => 8 

这里,make_adder(3)返回被定义为

def the_adder(b) 
    return 3 + b 

然后参数调用5回报8该函数的功能。如果您跳过将返回值make_adder(3)分配给单独变量的步骤,则会得到您询问的表单:make_adder(3)(5)与您的问题中的Dense(64, activation='relu')(inputs)是一样的。

编辑:从技术上讲,Dense没有被分类为Python中的函数,而是作为一个类; Dense(...)因此是一个构造函数的调用。有问题的类定义了__call__方法,它使得这个类的对象“可调用”。可以通过用参数列表调用它们来调用函数和可调用对象,两者之间的区别根本不会影响解释。但是,这里有一个简单的调用,更接近平行Dense的例子:

class Adder: 
    def __init__(self, a): 
     self.a = a 
    def __call__(self, b): 
     return self.a + b 

adder_of_three = Adder(3) 
adder_of_three(5) 
# => 8 

Adder(3)(5) 
# => 8 
+0

这个例子可能会引起误解,因为在这种情况下[Dense](https://github.com/fchollet/keras/blob/master/keras/layers/core.py#L607)是一个定义'__call__ ',但示例显示了一个工厂函数。 – SethMMorton

+1

@SethMMorton:在概念上,'Dense'是一个返回可调用的函数(作为定义'__call__'方法的类的构造函数)。 'make_adder'也是一个返回可调用对象的函数(通过返回一个函数,这个函数根据定义可调用)。他们没有那么不同。从技术上讲,肯定 - '密集'是一个类,'make_adder'是一个函数 - 在引擎盖下有很多差异。嗯,我可以补充说,虽然... – Amadan

+0

是的,我同意这是一个类是如何建立在引擎盖下。但对于新用户来说,描述可能会让人困惑,因为如果他们将源代码视为“密集”,他们会将其定义为类而不是函数。我想说的是,这个答案不会连接工厂函数和可调用类之间的点,如果建立连接,它可能会使其得到改进。虽然OP已经接受,所以也许这不值得。 – SethMMorton