2008年5月30日金曜日

Python で特定の範囲の数値を数え上げる - Ruby と比較して

1. Ruby の times メソッド と 範囲を表す Range オブジェクト

「数え上げる」とは、 for ループを使って、特定の範囲にある数値を順に表示すること。

Ruby が最初に紹介されると、必ずと言っていいほど例に取り上げられる

times メソッド

ブロック付きメソッドを見たことがないときは、「なんじゃ、この表記は!?」 (@_@;) と驚いた。

10.times do |i|
	puts i
end

for ループで書くなら、

for i in 0..9
	puts i
end

0..9

というのは範囲オブジェクトを生成する表記。(cf. Range - Rubyリファレンスマニュアル)

 

Integer クラスの upto, downto, step メソッド

Ruby では、数え上げるに Integer クラスの upto, downto, step メソッドも使える。

Integer - Rubyリファレンスマニュアル によると、

times {|n| ... }

upto(max) {|n| ... }

downto(min) {|n| ... }

step(limit, step) {|n| ... }

試してみる。

1.upto(9) do |i|
	puts i
end

9.downto(0) do |i|
	puts i
end

1.step(10, 2) do |i|
	puts i
end

times メソッドと比べると、表記にぎこちなさ感じる。

無理して、ここまでメソッドを定義しなくても…

という印象を受けるのは、 Ruby に慣れていない証拠かな?

てゆうか、times メソッドが、あまりにも自然な感じに読めるので、そのギャップもある。

 

2. Python の range() 関数

Python では、数え上げを行うとき、組込みメソッドである range() を利用する。

2.1 Built-in Functions によると、

range([start,] stop[, step])

試してみる。

for i in range(1,10):
    print i

# 2 ずつ増加させたい場合
for i in range(1,10,2):
    print i
    
# 1 ずつ減らす場合
for i in range(9,0,-1):
    print i

Ruby と比べると、組込み関数 range() を使うのは、律儀な感じを受ける。Ruby のように、Range オブジェクトを生成するための簡略な表記があればいいのに。

 

組み込みオブジェクト

ところで、「組込み関数のページ」は、`2. Built-In Objects’ の章にある。

この「組込みオブジェクト」って何だろう? Ruby のように、Kernel モジュールのようなものなのだろうか?

Ruby には厳密な意味では関数はありませんが、Kernel モジュールで定義されているメソッドは (どこからでも関数形式で呼び出せるので) 他言語における関数のように使えます。

(組み込み関数 - Rubyリファレンスマニュアル より)

これに対して、Python は、

Pythonでは扱えるデータの全てがオブジェクトである。単純な数値といった基本的なデータ型をはじめ、組み込みのコンテナ型、組み込み関数など、これらは全て統一的な継承関係をもつオブジェクトであり「型」をもっている。

Python – Wikipedia より)

やはり、どこかの型に定義されているのだろうか?

`Dive Into Python’ の 4.3. Using type, str, dir, and Other Built-In Functions によると

type, str, dir, and all the rest of Python's built-in functions are grouped into a special module called __builtin__. (That's two underscores before and after.) If it helps, you can think of Python automatically executing from __builtin__ import * on startup, which imports all the “built-in” functions into the namespace so you can use them directly.

なるほど、

__builtin__

というモジュールがあるようだ。 (cf. 26.2 __builtin__ -- Built-in objects )

しかし、‘Ion – Ruby vs. Python’ に書かれているように、

There are no functions and methods separately in Ruby; all of them are methods. In Python, e.g. len() is a function, but items() is a method. Such inconsistencies remind me of PHP, *shiver*.

なぜ、Python では、

"hoge".len()

と書けるようにしないのかなぁ?

 

3. Ruby の step メソッドについて

Range - Rubyリファレンスマニュアル

step([s]) {|item| ... }

Numeric - Rubyリファレンスマニュアル

step(limit, step) {|n| ... }