2007-11-09

Pythonではなぜ string.len() でなく len() なのか?

http://anond.hatelabo.jp/20071021143442

その理由は知らないが、なければ作ればいいじゃないか。

class MyString(str):
    def length(self):
        return len(self)

というクラスを作って

string = MyString("Hello world")
print string.count("o"), string.length()

Rubyライクにやれば

2 11

とでるよ。え、リストもlist.length()が使いたいって?それも簡単。

class MyList(list):
    def length(self):
        return len(self)

l = MyList([1, 2, 3, 4, 5, 6])
l.length()

6

きちんと他のメソッドも使えるよ。

l[1:]

[2, 3, 4, 5, 6]

l.reverse()
l

[6, 5, 4, 3, 2, 1]

ね。簡単でしょ。

Pythonは仕組みが統一されているものが多いので、いじりやすいのですよ。上の例のやつは組み込みクラスオブジェクトユーザー定義のクラスオブジェクトがおおむね統一されているからこそ簡単にできる。他にも関数なんかもほかのオブジェクトと同じオブジェクトなので、高階関数なんてもの簡単に作ることができて関数プログラミングぽくできる。例えば今はなきapply関数なんかは

def myApply(func, *args):
    return func.__call__(*args)

と定義できる。実際に

def sumUpThree(num1, num2, num3):
    return num1 + num2 + num3

でためしてみる。

myApply(sumUpThree, 1, 2, 3)

結果はちゃんと

6

とでる。将来廃止されそうなmap関数も簡単に定義できる。他にも複数の引数をもつ関数の部分適用のようなことを行う関数も次のように簡単に定義できる。

def partial(func, *oldArgs):
    def wrapper(*newArgs):
        return func.__call__(*(oldArgs + newArgs))
    return wrapper

sumUpThree関数テストすると

sum_1 = partial(sumUpThree, 1)
sum_1(2, 3)

6

sum_1_5 = partial(sum_1, 5)
sum_1_5(9)

15

sum_10_20 = partial(sumUpThree, 10, 20)
sum_10_20(30)

60

こういう風に高階関数が簡単にできるのは関数オブジェクト関数の実行とはメソッドの呼び出しにすぎないからだ。以上のように組み込みオブジェクトユーザー定義オブジェクトの差があまりないことや関数オブジェクトであることに見られるようにPythonは仕組みが統一されていてシンプルだ。そのためひとつのことがわかれば他のこともわかることが多いし、簡単にいじることもできる。

だからなければpythonをいじればいいと思うよ。

最後にラムダ式信者のためにpartialをラムダ式を使って書いておく。

def partial(func, *oldArgs):
    return lambda *newArgs:func.__call__(*(oldArgs + newArgs))

Pythonラムダ式がだめだといわれているが、こんな風にかけたとして何がうれしいというのだ。

記事への反応 -

記事への反応(ブックマークコメント)

ログイン ユーザー登録
ようこそ ゲスト さん