def...return

□未翻訳

□翻訳中

□翻訳完了(細田謙二)

■レビュー(Omi Chiba)

def...return

関数はdefを用いて宣言します。以下は典型的なPython関数です:

Functions are declared using def. Here is a typical Python function:

1.

2.

3.

4.

>>> def f(a, b):

return a + b

>>> print f(4, 2)

6

引数や戻り値に型を指定する必要(方法)はありません。 上記の例では、関数fは2つの引数を取ることができるように定義されています。

There is no need (or way) to specify types of the arguments or the return type(s). In this example, a function f is defined that can take two arguments.

関数は、スコープや名前空間の概念を紹介するにあたって、本章で記述された最初のコード構文の特徴です。上記の例では、識別子aとbは、関数fのスコープ外では未定義になります。

Functions are the first code syntax feature described in this chapter to introduce the concept of scope, or namespace. In the above example, the identifiers a and b are undefined outside of the scope of function f:

1.

2.

3.

4.

5.

6.

7.

8.

9.

>>> def f(a):

return a + 1

>>> print f(1)

2

>>> print a

Traceback (most recent call last):

File "<pyshell#22>", line 1, in <module>

print a

NameError: name 'a' is not defined

関数スコープの外で定義された識別子は関数内でアクセスできます。以下のコードで、どのように識別子が扱われるかを確認してください。

Identifiers defined outside of function scope are accessible within the function; observe how the identifier a is handled in the following code:

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

>>> a = 1

>>> def f(b):

return a + b

>>> print f(1)

2

>>> a = 2

>>> print f(1) # new value of a is used

3

>>> a = 1 # reset a

>>> def g(b):

a = 2 # creates a new local a

return b + 2

>>> print g(2)

4

>>> print a # global a is unchanged

1

aが変更されると、その下の関数は新規のグローバルなaの値を使用するようになります。なぜなら、関数定義は識別子aの格納場所に結び付いて、関数宣言時にaそのものの値には結びついていないからです。しかし、aが関数gの中で割り当てられていれば、グローバルなaは影響されません。なぜなら、新規のローカルなaはグローバルな値を隠すからです。外部スコープの参照は、 次のようにクロージャの作成​に使用にすることができます:

If a is modified, subsequent function calls will use the new value of the global a because the function definition binds the storage location of the identifier a, not the value of a itself at the time of function declaration; however, if a is assigned-to inside function g, the global a is unaffected because the new local a hides the global value. The external-scope reference can be used in the creation of closures:

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

>>> def f(x):

def g(y):

return x * y

return g

>>> doubler = f(2) # doubler is a new function

>>> tripler = f(3) # tripler is a new function

>>> quadrupler = f(4) # quadrupler is a new function

>>> print doubler(5)

10

>>> print tripler(5)

15

>>> print quadrupler(5)

20

関数fは新しい関数を作ります。名前gのスコープは完全にfの内部に収まります。クロージャは非常に強力です。

Function f creates new functions; and note that the scope of the name g is entirely internal tof. Closures are extremely powerful.

関数の引数は、デフォルト値を持つことができ、複数の結果を返すことができます。

Function arguments can have default values, and can return multiple results:

1.

2.

3.

4.

5.

6.

7.

>>> def f(a, b=2):

return a + b, a - b

>>> x, y = f(5)

>>> print x

7

>>> print y

3

引数は名前指定によって明示的に渡すことが可能です。これにより、呼び出し側で指定した引数の順序は、関数を定義したときの引数の順序と違ってもいいようになります。

Function arguments can be passed explicitly by name, and this means that the order of arguments specified in the caller can be different than the order of arguments with which the function was defined:

1.

2.

3.

4.

5.

6.

7.

>>> def f(a, b=2):

return a + b, a - b

>>> x, y = f(b=5, a=2)

>>> print x

7

>>> print y

-3

関数はまた、可変数の引数を取ることができます。

Functions can also take a runtime-variable number of arguments:

1.

2.

3.

4.

5.

6.

7.

>>> def f(*a, **b):

return a, b

>>> x, y = f(3, 'hello', c=4, test='world')

>>> print x

(3, 'hello')

>>> print y

{'c':4, 'test':'world'}

ここで、名前付きで渡されなかった引数(3、'hello')はリストaに格納され、名前付きで渡された(cとtest)は辞書bに格納されます。

Here arguments not passed by name (3, 'hello') are stored in list a, and arguments passed by name (c and test) are stored in the dictionary b.

逆に、リストやタプルは、展開しながら、個別の位置引数を要求する関数に渡すことができます:

In the opposite case, a list or tuple can be passed to a function that requires individual positional arguments by unpacking them:

1.

2.

3.

4.

5.

>>> def f(a, b):

return a + b

>>> c = (1, 2)

>>> print f(*c)

3

辞書もまた、展開しながら、キーワード引数に引き渡すことができます。

and a dictionary can be unpacked to deliver keyword arguments:

1.

2.

3.

4.

5.

>>> def f(a, b):

return a + b

>>> c = {'a':1, 'b':2}

>>> print f(**c)

3

lambda

lambdaは非常に短い無名関数を簡単に作成する方法を提供します。

lambda provides a way to create a very short unnamed function very easily:

1.

2.

3.

>>> a = lambda b: b + 2

>>> print a(3)

5

"lambda [a]:[b]"式は、文字通り"引数[a]を持ち[b]を返す関数"として読みます。lambda}式自体は無名関数ですが、この関数は識別子aに割り当てられることで名前を獲得しています。 defのためのスコープのルールは同様にlambdaにも適用されます。実際上記のコードでは、aに関して、次のようなdefを用いた関数宣言と等価です:

The expression "lambda [a]:[b]" literally reads as "a function with arguments [a] that returns [b]". The lambda expression is itself unnamed, but the function acquires a name by being assigned to identifier a. The scoping rules for def apply to lambda equally, and in fact the code above, with respect to a, is identical to the function declaration using def:

1.

2.

3.

4.

>>> def a(b):

return b + 2

>>> print a(3)

5

lambdaを利用するメリットは簡潔さだけですが、その簡潔さは特定の状況でとりわけ便利です。リスト内のすべての項目に関数を適用し新しいリストを作成するmapと呼ばれる関数を考えてみましょう:

The only benefit of lambda is brevity; however, brevity can be very convenient in certain situations. Consider a function called map that applies a function to all items in a list, creating a new list:

1.

2.

3.

>>> a = [1, 7, 2, 5, 4, 8]

>>> map(lambda x: x + 2, a)

[3, 9, 4, 7, 6, 10]

このコードは、lambdaの代わりにdefを用いると倍のサイズになります。lambdaの主要な欠点は(Pythonの実装では)、1つの式しか取れないことです。しかし、長い関数のためにはdefが利用でき、関数の名前を提供する余分なコストは、関数の長くなるにつれ減ります。defと同様に 、lambdaはカリー関数として利用できます。すなわち、新規の関数は、既存の関数を、新規の関数が異なる引数セットを持つようにして、ラップして作成することができます。

This code would have doubled in size had def been used instead of lambda. The main drawback of lambda is that (in the Python implementation) the syntax allows only for a single expression; however, for longer functions, def can be used and the extra cost of providing a function name decreases as the length of the function grows. Just like def, lambda can be used to curryfunctions: new functions can be created by wrapping existing functions such that the new function carries a different set of arguments:

1.

2.

3.

4.

>>> def f(a, b): return a + b

>>> g = lambda a: f(a, 3)

>>> g(2)

5

カリー化はさまざまな状況で有用ですが、中でもweb2pyにおいて、キャッシュとして直接的に有用です。たとえば、次のような引数が素数であるかどうかをチェックするという高くつく関数を考えてください:

There are many situations where currying is useful, but one of those is directly useful in web2py: caching. Suppose you have an expensive function that checks whether its argument is prime:

1.

2.

3.

4.

5.

def isprime(number):

for p in range(2, number):

if (number % p) == 0:

return False

return True

この関数は明らかに時間がかかるものです。

This function is obviously time consuming.

ここで、キー、関数、秒数の3つの引数を取るキャッシュ関数cache.ramを考えてください。

Suppose you have a caching function cache.ram that takes three arguments: a key, a function and a number of seconds.

1.

value = cache.ram('key', f, 60)

1回目に呼ばれたときは、関数f()が呼び出され、その出力がメモリー内の辞書に保存され、それが返されます。したがってvalueは次のようになります:

The first time it is called, it calls the function f(), stores the output in a dictionary in memory (let's say "d"), and returns it so that value is:

1.

value = d['key']=f()

2回目に呼ばれたときは、もしそのキーが辞書内に保持されていて、指定された秒数(60)より古くない場合は、関数の呼び出し無しに対応する値を返します。

The second time it is called, if the key is in the dictionary and not older than the number of seconds specified (60), it returns the corresponding value without performing the function call.

1.

value = d['key']

任意の入力に対するisprime関数の出力をどのようにキャッシュすればよいのでしょうか?下記例を参考にしてみましょう。

How would you cache the output of the function isprime for any input? Here is how:

1.

2.

3.

4.

5.

6.

>>> number = 7

>>> seconds = 60

>>> print cache.ram(str(number), lambda: isprime(number), seconds)

True

>>> print cache.ram(str(number), lambda: isprime(number), seconds)

True

出力結果は常に同じですが、1回目にcache.ramが呼び出されるとisprimeが呼び出されます。しかし、2回目は呼び出されません。

The output is always the same, but the first time cache.ram is called, isprime is called; the second time it is not.

defやlambdaによって作られたPython関数は、異なる引数セットに関して、既存の関数をリファクタリングすることが可能です。cache.ramとcache.diskはweb2pyのキャッシュ関数です。

Python functions, created with either def or lambda allow re-factoring existing functions in terms of a different set of arguments. cache.ram andcache.disk are web2py caching functions.