Diary?

2009-07-01
Wed

(01:00)

Python ネタなら俺の出番だ。

要するにこれは「class の直下で変数宣言をしたい」「でも普通にそれをやるとクラス変数になってしまう」という問題なわけだな。こういう場合にどうするかというと、プロパティを使うのが多分スマートだろう。

class Hoge(object):
    def __init__(self):
        self.name = 'hoge'
        
    def name():
        def get(self):
            return self.__name
        def set(self, value):
            self.__name = value
        return get, set
    name = property(*name())

プロパティに使われる getter/setter を内部関数として定義し、その関数の名前をプロパティ名と同一にし、シャドーイングでその存在を隠蔽してるのがちょっとしたポイントだけど、これは別にやらなくてもいい事なのでどうでもいい。

プロパティの宣言が多くなるとウザったいかもしれないけど、プロパティの宣言がウザく感じるほど外部仕様としてのアクセサが多いというのは俺の感覚としてはクラスの設計かコーディングスタイルが間違っていると思う。これは Python に限らず、他の言語でも同じ。例えば Java は「getter/setter うぜえ」って話をよく聞くけど、俺に言わせりゃ getter/setter のコードが他の部分のコードを読む上で支障になるような設計あるいはコーディングスタイルという事それ自体が終わってる。

ちなみに俺の方針としては、

  • 外部仕様として公開するのならプロパティ
  • そうでなければ __init__ 内部に列挙

というのがバランスのとれたやり方かなと思ってる。

追記:hiratara さんより返信。デコレータを使った書き方は "Changed in version 2.6: The getter, setter, and deleter attributes were added." とある通り、 2.6 以降でしか使えないですね。もしも 2.6 以降を動作環境として想定できるのであれば、そちらの方が高階関数とシャドーイングを使ったやり方よりも、より宣言的でわかりやすくなると思いますね。

あと「シャドーイング」という言葉に関しては、これは本来「上位のスコープで定義されたシンボルの参照先を下位のスコープで切り替える」事を示す言葉で、例えば次のコードのようにフィールドへのアクセスが仮引数へのアクセスで隠されるような状態に対して使う……はずだけど、もしかして一般的な言葉じゃない?

class Foo {
    String foo;
    void bar(String foo) {
        dosomethingToFoo(foo); //←この時の foo へのアクセスは仮引数へのアクセス
                               //同じ事はローカル変数でも起こる
    }
}

それで先に出した property の例は、先に定義した name() 関数へのアクセスを後に定義した name プロパティで隠しているので、本来のシャドーイングとは実は全然違うのだけど、シャドーイングとしてしまった方がわかりやすいかなと。参照先を切り替える/隠すというニュアンスは変わってないと思うし(あーでも混乱の元になるか、こういう書き方は)。

(23:02)

値段ほど美味しくなかった。多分これは二度と買わない。

Creative Commons
この怪文書はクリエイティブ・コモンズ・ライセンスの元でライセンスされています。引用した文章など Kuwata Chikara に著作権のないものについては、それらの著作権保持者に帰属します。