2012-05-01 7 views
15

私は、Pythonにかなり新たなんだと以下のクラスについて質問があります。ベストプラクティス

class Configuration: 
    def __init__(self): 
     parser = SafeConfigParser() 
     try: 
      if parser.read(CONFIG_FILE) is None: 
       raise IOError('Cannot open configuration file') 
     except IOError, error: 
      sys.exit(error) 
     else: 
      self.__parser = parser 
      self.fileName = CONFIG_FILE 

    def get_section(self): 
     p = self.__parser 
     result = [] 
     for s in p.sections(): 
      result.append('{0}'.format(s)) 
     return result 

    def get_info(self, config_section): 
     p = self.__parser 
     self.section = config_section 
     self.url = p.get(config_section, 'url') 
     self.imgexpr = p.get(config_section, 'imgexpr') 
     self.imgattr1 = p.get(config_section, 'imgattr1') 
     self.imgattr2 = p.get(config_section, 'imgattr2') 
     self.destination = p.get(config_section, 'destination') 
     self.createzip = p.get(config_section, 'createzip') 
     self.pagesnumber = p.get(config_section, 'pagesnumber') 

この例では、別の関数にget_infoをより多くのインスタンス変数を追加するにはOKですが、かコンストラクタ内のすべてのインスタンス変数を定義するのがベストプラクティスですか?新しいインスタンス変数をどこにでも定義すれば、スパゲッティコードになることはありませんか?

編集:このコードは単純な画像スクレーパーで使用しています。 Via get_section設定ファイルのすべてのセクションを返してから、それらを繰り返して、私が画像を掻き集める各サイトにアクセスします。各繰り返しに対して、get_sectionを呼び出して、設定ファイルの各セクションの設定を取得します。 誰かが別のアプローチを考え出すことができればうまくいくでしょう!ありがとう!

+0

http://stackoverflow.com/questions/2964230/python-how-should-i-make-instance-variables-available –

+0

「自己」。__init __() 'の先頭に__parser = None'を設定する必要があります。その理由は、 '__init __()'が*既存の*オブジェクトの第1のメンタとして呼ばれているからです。パーサーが設定ファイルの読み込みに失敗し、例外が発生した場合、例外はキャッチされたelswhere(プログラムが終了しない可能性があります)によって発生する可能性があります。その後、 'Configuration'クラスのオブジェクトはまだ存在し、後の' get_info()は* AttributeError:Configurationインスタンスに属性 '__parser'がありません。 – pepr

+0

@pepr '__init __。py'の最初に' self .__ parser = None'を追加するべきか、それともパーサーの初期化を '__init __。py'から別の関数に移すべきかを答えてください。 – happygoat

答えて

11

によって民間のみであるため、


1.あなたは、Pythonで100%のカプセル化を提供することはできません。そうしないと複雑さが増し、予想外の副作用が発生する可能性があります。

アクセスに関してDavid Hallの別の視点を提供するには、Google Python style guideからです。

Access Control:

If an accessor function would be trivial you should use public variables instead of accessor functions to avoid the extra cost of function calls in Python. When more functionality is added you can use property to keep the syntax consistent

On the other hand, if access is more complex, or the cost of accessing the variable is significant, you should use function calls (following the Naming guidelines) such as get_foo() and set_foo(). If the past behavior allowed access through a property, do not bind the new accessor functions to the property. Any code still attempting to access the variable by the old method should break visibly so they are made aware of the change in complexity.

From PEP8

For simple public data attributes, it is best to expose just the attribute name, without complicated accessor/mutator methods. Keep in mind that Python provides an easy path to future enhancement, should you find that a simple data attribute needs to grow functional behavior. In that case, use properties to hide functional implementation behind simple data attribute access syntax.

Note 1: Properties only work on new-style classes.

Note 2: Try to keep the functional behavior side-effect free, although side-effects such as caching are generally fine.

Note 3: Avoid using properties for computationally expensive operations; the attribute notation makes the caller believe that access is (relatively) cheap.

Pythonのは、Java/C#ではない、それは見なければならない可能性があり、書き込みがどの程度の非常に強力なアイデアを持っています。 Pythonをコーディングする場合は、Pythonのように見えるようにするのが理にかなっています。他の人があなたのコードをより簡単に理解できるようになり、他のPythonコードもよく理解できるようになります。

+1

+1私はPythonの "私たちはすべて大人だ"という理念に同意するからです。私の主な牛は、クラスを有効な状態にするために特定の関数を呼び出す必要があるクラスを持っています。 –

+0

@DavidHall最後に、pyconの "クラスを書くのを止めよう"という話が本当に興味深かった。ここには良い解説があるハッカーのニューススレッドがある。スレッドとビデオの両方が読む価値があります。 http://news.ycombinator.com/item?id=3717715 –

+0

乾杯 - 私は一見するでしょう。あなたはおそらく私がC++/C#の開発者だと言うことができるので、このような議論が読むのが大変なので、いくつかのPythonを知っています。 –

5

有効な状態にするために必要なget_info()のような関数を使って、コンストラクタ内のすべてのインスタンス変数を設定することをお勧めします。

get_info()のようなメソッドへの呼び出しによってのみインスタンス化されるpublicインスタンス変数では、使用する地雷フィールドのビットであるクラスを作成します。

常に必要とされるわけではなく、計算にコストがかかることが心配されている場合(遅延実行を許可するget_info()があると思います)、そのサブセットをリファクタリングすることを検討しますまたは、propertiesを導入するか、値を返す関数を使用します。

プロパティまたはgetスタイル関数を使用すると、クラスのコンシューマは、定義されたインターフェイスを通過し、カプセル化を改善することを推奨します。。

インスタンス変数をカプセル化したら、NameError例外を投げるだけでなく、自分でget_info()に電話するか、カスタム例外をスローすることができます。主要な2つのアンダースコアで示さプライベートインスタンス変数は、私は間違いなく__init__内のすべてのインスタンス変数を宣言するだろう大会

+0

パブリックインスタンス変数よりもプロパティへのメリットはありません。単純にすべてをパブリックインスタンス変数にすることができます。後で値を設定/取得する以外に何かを実行する必要があれば、それを常にプロパティに変換できます。 – interjay

+0

良い点 - パブリックインスタンス変数の主な問題は、get_infoのような関数でインスタンス化することで、不必要に難しいクラスを使用することです。しかし、あなたとAndrew Barretは私の答えをタッチで編集して、コンストラクターを強調しました。 –