17

私は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ありませんか、それともコンストラクターですべてのインスタンス変数を定義するのがベスト プラクティスですか? いたるところに新しいインスタンス変数を定義すると、スパゲッティ コードになるのではないでしょうか?

編集:このコードを単純な画像スクレーパーで使用しています。経由get_sectionで、構成ファイルのすべてのセクションを返し、それらを繰り返し処理して、画像をスクレイピングしている各サイトにアクセスします。get_section繰り返しごとに、構成ファイルの各セクションの構成設定を取得するために を呼び出します。誰かが別のアプローチを思い付くことができれば、それは大丈夫です! ありがとう!

4

2 に答える 2

14

ですべてのインスタンス変数を確実に宣言します__init__。そうしないと、複雑さが増し、予期しない副作用が発生する可能性があります。

アクセスに関して David Hall からの別の視点を提供するために、これはGoogle Python スタイル ガイドからのものです。

アクセス制御:

アクセサー関数が自明である場合は、アクセサー関数の代わりにパブリック変数を使用して、Python での関数呼び出しの余分なコストを回避する必要があります。より多くの機能が追加されたら、プロパティを使用して構文の一貫性を保つことができます

一方、アクセスがより複雑な場合、または変数へのアクセスのコストが大きい場合は、get_foo() や set_foo() などの関数呼び出しを (命名ガイドラインに従って) 使用する必要があります。以前の動作でプロパティを介したアクセスが許可されていた場合は、新しいアクセサ関数をプロパティにバインドしないでください。古い方法で変数にアクセスしようとしているコードは、複雑さの変化を認識できるように、目に見えて中断する必要があります。

PEP8から

単純なパブリック データ属性の場合は、複雑なアクセサー/ミューテーター メソッドを使用せずに、属性名のみを公開することをお勧めします。Python は、単純なデータ属性が機能的な動作を拡張する必要があることに気付いた場合に、将来の拡張への簡単な道筋を提供することに注意してください。その場合、プロパティを使用して、関数の実装を単純なデータ属性アクセス構文の背後に隠します。

注 1: プロパティは新しいスタイルのクラスでのみ機能します。

注 2: キャッシングなどの副作用は一般的に問題ありませんが、機能的な動作に副作用がないようにしてください。

注 3: 計算コストの高い操作にプロパティを使用することは避けてください。属性表記は、呼び出し元にアクセスが (比較的) 安価であると信じ込ませます。

Python は Java/C# ではなく、コードの外観と記述方法について非常に強力なアイデアを持っています。Python でコーディングしている場合、Python のように見えるようにすることは理にかなっています。他の人はあなたのコードをより簡単に理解できるようになり、あなたも他の Python コードをよりよく理解できるようになります。

于 2012-05-01T11:50:23.580 に答える
6

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

あなたのようなメソッドへの呼び出しによってのみインスタンス化されるパブリックインスタンス変数をget_info()使用して、使用するのに少し地雷原のようなクラスを作成します。

常に必要ではなく、計算に費用がかかる特定の構成値があることを心配している場合 (これが get_info() を使用して遅延実行を可能にしている理由だと思います)、その構成のサブセットを2 番目のクラスまたは値を返すプロパティまたは関数の導入。

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

インスタンス変数をカプセル化したら、単にNameError例外をスローするだけでなく、自分自身を呼び出しget_info()たり、カスタム例外をスローしたりするオプションを自分自身に与えることができます。


1. Python で 100% のカプセル化を提供することはできません。これは、先頭の二重アンダースコアで示されるプライベート インスタンス変数は、慣例によってのみプライベートであるためです。

于 2012-05-01T11:28:37.570 に答える