メソッドのself
最近『初めてのRuby』を読んでいる。Pythonのメソッドの第一引数にselfを書かなくてはいけないが、Rubyと対比して理由がなんとなく分かったので検討してみる。
まずPythonではRubyと同様、インスタンスメソッドとトップレベル関数の区別がない。Pythonではメソッドと関数という呼び方をする。関数およびメソッドは単なるオブジェクトの属性である。つまりメソッドはクラスオブジェクトのcallableな属性、関数はモジュールオブジェクトのcallableな属性である。Pythonでも全てがオブジェクトなので、この区別をしないということが重要となる。
ここで、以下のクラス定義を考えてみる。
>>> class Foo: ... a = 1 ... def foo(self): ... a # エラー (1) ... Foo.a # OK (2) ... self.a # OK (3) ...
クラス内に関数を定義した場合、ローカル変数(グローバル変数)、クラス変数、インスタンス変数の区別を考えなくてはならない。Rubyでは変数の頭に「何も付けない」、「@を付ける」、「@@を付ける」で構文上区別している。Pythonでは以下のようになる。
1. クラス内で関数を定義すると属性になるので、クラス内で変数を定義しても属性とする
-
- 属性なので、Foo.a のような構文で参照させる
2. 次にローカル変数(グローバル変数)とそれ以外のクラス変数、インスタンス変数を区別するため以下のようにする
3. selfをどうにかしないといけない
ここで、ポイントとしてはRubyのようにselfは省略可とした場合、インスタンス変数に特殊な構文を用意しない限り、ローカル変数とインスタンス変数の区別がつかなくなってしまう。構文上区別しなくても良いが、lookupの規則が複雑になり遅くなる。また同じ変数名が使用できないという制限も付いてしまう。なので通常は違うものであるとして区別したいので、selfを導入するしかない。
4. Rubyのような暗黙のselfはどうだったのか?
〜使い
一覧表が見つからなかったのでまとめてみた。ご指摘大歓迎。
Python | Pythonista |
---|---|
Ruby | Rubyist |
Perl | Perl Monger |
PHP | PHPer (ぺちぱー) |
Scheme | Schemer |
Lisp | Lisper |
ML | MLer |
Java | Javanese |
C# | C#er (C Sharper) |
C | C屋、Cげんがー |
C++ | C++屋、Cぷらぷらー |
Delphi | Delphian |
Smalltalk | Smalltalker |
OCaml | Caml rider |
Haskell | Haskeller |
Scala | ? |
Erlang | ? |
Prolog | ? |
JavaScript | JavaScripter |
Brainfuck | ? |
Java、C#、C++なども呼び名があるべき。呼び名がないのは言語が愛されていない証拠?
OSその他も追加してみた。他の呼び方もいろいろありそうだが、自分のメモ代わりに一般的っぽいのを書いてみた。
Mac | マカー |
---|---|
Windows | ドザ |
Linux | リナー |
Tex | TeXニシャン(テフニシャン) |
メモ
「ときどきの雑記帖 i戦士篇」日記経由でメモ。あとで読む。
- Haskell プログラミング 〜 純粋関数型言語への誘い〜(http://www.mew.org/~kazu/haskell.pdf)
以下、Python版の実装。出典元は省略。
def qsort(L): if len(L) <= 1: return L return qsort([lt for lt in L[1:] if lt < L[0]]) + L[0:1] + \ qsort([ge for ge in L[1:] if ge >= L[0]])
- エラトステネスのふるい
from itertools import ifilter, count def sieve(): g = count(2) while True: prime = g.next() yield prime g = ifilter(lambda x, prime=prime: x%prime, g)
Pythonさん、無限リストの取り扱いをもっと一般化してください。