3

私の質問は、関数内で数回必要とされ、他の場所では必要とされないコードの編成について言及しています。

次の使用例を想定しています。

class A(object):
    def __init__(self, base):
        self.base = base

    def foo(self):
        result = self.base + 2    # Should go to an extra function.
        result = result * 4
        if result > 10:
            result = result + 2   # Should go to an extra function.
        return result

    def bar(self):
        pass

私のプロジェクトでは、抽象化する必要がある 20 行のコード (別のオブジェクトの 20 の属性に値を追加する)foo()の部分に繰り返しがあります。x + 2しかし、それらをどこに置くのですか?それを行うには3つの方法があります。

(1.)ネストされた関数:

class A(object):
    # ...

    def foo(self):
        def plus_two(value):
            return value + 2

        result = plus_two(self.base)
        result = result * 4
        if result > 10:
            result = plus_two(result)
        return result

    # ...

これは、メソッド内で発生することのみに関連する非常に特殊なユース ケースであるため、理にかなっているように思われます。

ただし、テストできません。単体テストのためにネストされた関数に外部からアクセスすることはできません。そして、これをの一部としてテストしたくありません.2回すべてfoo()テストする必要があるためです(両方の場合)。単体テストでは、個別にテストすることが可能であるべきであり、.plus_twoplus_twofoo()

(2.)ヘルパー メソッド:

class A(object):
    # ...

    def foo(self):
        result = self.plus_two(self.base)
        result = result * 4
        if result > 10:
            result = self.plus_two(result)
        return result

    def plus_two(self, value):
        return value + 2

    # ...

ただし、そのメソッドはクラス内の他のメソッドによって使用されることはなく、 へのアクセスも必要selfないため、そのクラスのメソッドになるべきではありません。オブジェクトへのアクセスを必要としない、またはインターフェイスの一部として上書きする必要がないクラスで関数を収集することは Pythonic ではありません。

(3.)モジュール機能:

def plus_two(value):
    return value + 2

class A(object):
    # ...

    def foo(self):
        result = plus_two(self.base)
        result = result * 4
        if result > 10:
            result = plus_two(result)
        return result

    # ...

しかし: これにより、いくつかのヘルパー関数が非常に具体的なコンテキストから取り出されます。つまり、カプセル化には従いません。これはここでは問題ではないようで、解決策のように見えるかもしれませんが、私のプロジェクトでは、関数は一般的にモジュールに関連していないため、これはモジュール全体を本当に混乱させますが、前述のように、非常に具体的ですつまり、これをそのコンテキストから遠く離れた場所に分割すると、コードが非常に読みにくくなり、pythonic が少なくなります。

他に方法はありますか、またはここに示す 3 つの方法のいずれかを選択する必要がありますか?

4

2 に答える 2

0

個人的には、オプション 1 または 2 のいずれかが最もクリーンだと思います。あなたが言及したように、オプション3はモジュール関数として定義される非常にコンテキスト固有です。

オプション 1 か 2 のどちらかを決定するには、そのコードの特定の部分を単体テストできることがどれほど重要かを決定する必要があります。単体テストの重要性については既に基本的に回答済みであり、foo() 内から単体テストできるかどうかを考えると、

そして、これを foo() の一部としてテストしたくありません

次に、オプション2のいくつかのバリアントを使用する必要があります。理想的には、プライベートメソッドがここに進む方法ですが、Pythonはそれをサポートしていないため、少なくとも名前を付けることを検討__plus_two()してください Pythonの先頭の二重アンダースコアに関する関連する質問は次のとおりです。オブジェクト名の前にある単一アンダースコアと二重アンダースコアの意味は何ですか? プライベート メソッドに関連するもう 1 つの質問があります。Python の「プライベート」メソッドが実際にはプライベートではないのはなぜですか?

于 2013-06-05T10:58:11.677 に答える