作者: 機械伯爵
日時: 2003/3/18(22:14)
 ども、機械です。

>>  まぁ、アクティブな皆さんには説明不要と思いますが、リスナーの方々にはち
>
>  うーん、分かりません。いや、なんとなく分かりますが。
>  ちょっと調べても見つからなかったので何かポインタを示してもらえると助かり
ま
>す。

 すみません・・・どーも先走りすぎて(感じ悪いよな
ぁ、私って)

 廣島さんや中村さんが書いてるので、大体理解された
かと思いますが、つまりこーいうことです。

>>> def func():
...   print 'Hello!'
...
>>> a = func
>>> a()
Hello!
>>>

 funcという識別子は、括弧をつけて呼び出さないと基
本的に関数オブジェクトとして扱われます。

 ですから、変数に代入もできますし、コレクションの
要素にもなりえます。

 廣島さんがPerlの例を書いてくれましたが、例えばC言
語でも、関数ポインタという形で扱うことは出来ないこ
とはないと思います。

 ただし、CやPerlの場合は「参照」を指定しなければな
らない時点で「ファーストクラスプロシージャ」ではそ
もそも無いわけです。

 Pythonは、括弧を省略する記法を犠牲にする代わりに、
括弧をつければ関数呼び出し、括弧無しならオブジェク
ト(即ち関数ポインタみたいなの)という、書き分けを
してるわけです。

 そのおかげで、例えばPythonにはSwich文はありません
が、関数オブジェクトをリストや辞書として扱うことに
よって、Swhich文のようなことをすることが比較的簡単
にできます(中村さんのコードは、リストとして使った
例です)

>>> def func0():
...   print '0!'
...
>>> def func1():
...   print '1!'
...
>>> def func2():
...   print '2!'
...
>>> funcdic={'zero':func0, 'one':func1, 'two': func2}
>>> funcdic['zero']()
0!
>>> funcdic[raw_input()]()
two
2!
>>>

 raw_inputはキー入力用関数ですので、文字列を受け取
って関数を起動したことになります。

 また、関数オブジェクトを返す関数なんかも、簡単に
書けます。

>>> def func0(a):
...   def func1(b):
...     return a + b
...   return func1
...
>>> f = func0(100)
>>> f(200)
300
>>> j = func0(50)
>>> j(500)
550
>>> f(300)
400
>>>

 アクセスする度に返り値が増加する関数の生成は、こんな感じかな?

[Python 2.2以降・・・]

>>> def func(a):
...   def funcx():
...     print funcx.v
...     funcx.v += 1
...   funcx.v = a
...   return funcx
...
>>> p = func(1)
>>> q = func(100)
>>> p()
1
>>> p()
2
>>> q()
100
>>> q()
101
>>> p()
3
>>>

 Pythonには、変数内部を直接変更する演算子は無いの
で、変更には代入を用いるため、スコープについて用心
しないと、ヘンな結果になることがあります。

 Perl式とどっちが便利なのかは・・・う〜む(私は
Pythonに慣れてるけど・・・)

   /機械伯爵/