6

私はしばらくの間 Python でプログラミングしており、Python スタイルの知識をカバーしましたが、クラスを適切に使用する方法についてはまだ問題があります。オブジェクト指向の講義を読んでいると、Single Responsibility Principle のようなルールをよく見かけます。

「単一責任の原則は、クラスには変更する理由が 1 つだけあるべきだと言っています。」

これを読むと、次のように 1 つのクラスを 2 つに分割することを考えるかもしれません。

class ComplicatedOperations(object):
    def __init__(self, item):
        pass

    def do(self):
        ...

    ## lots of other functions

class CreateOption(object):
    def __init__(self, simple_list):
        self.simple_list = simple_list

    def to_options(self):
        operated_data = self.transform_data(self.simple_list)
        return self.default_option() + operated_data

    def default_option(self):
        return [('', '')]

    def transform_data(self, simple_list):
        return [self.make_complicated_operations_that_requires_losts_of_manipulation(item)
                        for item in simple_list]

    def make_complicated_operations_that_requires_losts_of_manipulation(self, item):
            return ComplicatedOperations(item).do()

これは、私にとって、さまざまな疑問を投げかけます。お気に入り:

  • クラス変数を使用したり、クラス関数で引数を渡す必要があるのはいつですか?
  • ComplicatedOperationsクラスはクラスであるべきか、それとも単なる関数の集まりであるべきか?
  • __init__メソッドを使用して最終結果を計算する必要があります。それはそのクラスをテストするのを難しくしますか。
  • Pythonists のルールは何ですか?

回答後に編集:

したがって、アウグスト理論を読むと、次のようになります。

class ComplicatedOperations(object):
    def __init__(self):
        pass

    def do(self, item):
        ...

    ## lots of other functions

def default_option():
    return [('', '')]

def complicate_data(item):
    return ComplicatedOperations().do(item)

def transform_data_to_options(simple_list):
    return default_option() + [self.complicate_data(item)
                    for item in simple_list]

(また、default_option の小さなバグを修正しました。)

4

4 に答える 4

1

クラスは通常、オブジェクトのタイプを表します。クラス インスタンスは、その型の特定のオブジェクトです。古典的な例はAnimalクラスです。acatは のインスタンスになりますAnimal。クラス変数 (クラス オブジェクト自体ではなくインスタンスに属するものを意味すると思います) は、インスタンスの属性に使用する必要があります。この場合、たとえば、またはcolourとして設定されるクラス属性である可能性があります。引数は、値がクラス外の何らかのソースから取得される可能性がある場合に使用する必要があります。クラスにメソッドがある場合、動物が眠っている睡眠時間と姿勢を知る必要があるかもしれません。動物 とは関係がないため、メソッドの引数になりますが、 cat.colour = "white"bear.colour = "brown"Animalsleepdurationposture動物によって決定されるため、クラス変数になります。

Python では、クラスは通常、状態を共有する一連の関数と変数をグループ化するために使用されます。上記の例を続けると、特定の動物には、そのメソッド間で共有され、その属性によって定義される状態があります。クラスが、クラスの状態にまったく依存しない単なる関数のグループである場合、それらは簡単に個別の関数になる可能性があります。

を使用して最終結果を計算する場合(結果を返すことができない__init__ため、クラスの属性に格納する必要があります)、関数を使用することもできます。__init__ただし、一般的なパターンは__init__、クラスの他のいくつかの、場合によってはプライベートなメソッドを介して多くの処理を行うことです。その理由は、大規模で複雑な関数は、より小さな個別のタスクに分割し、それぞれを個別にテストできるようにすると、テストが容易になることが多いためです。ただし、これは通常、とにかくクラスが必要な場合にのみ行われます。

ビジネス全体に対する 1 つのアプローチは、必要な機能を決定することから始めることです。すべてが同じオブジェクトに作用するか適用される関数または変数のグループがある場合、それらをクラスに移動するときが来ました。オブジェクト指向プログラミング (OOP) は、一部のタスクに適した設計手法ですが、本質的に関数型プログラミングよりも優れているわけではないことを覚えておいてください (実際、一部のプログラマーは反対のことを主張するでしょう!)。必要。

于 2013-02-11T15:41:54.890 に答える
1

クラス変数を使用したり、クラス関数で引数を渡したりする必要がある場合

itemあなたの例では、メソッドに渡しますdo。また、これは任意の言語でのプログラミングに関連しており、必要な情報のみをクラスに与え (最小権限)、パラメーターを介してアルゴリズムの内部にないすべてのものを渡します (依存性注入) ComplicatedOperations。それ自体を初期化する場合は、init パラメーターとして指定しないでください。ジョブを実行するためにアイテムが必要な場合は、パラメーターとして指定します。

ComplicatedOperationsクラスはクラスであるべきか、それとも単なる関数の集まりであるべきか

私が言うには、依存します。さまざまな種類の操作を使用していて、それらがある種のインターフェイスまたは契約を共有している場合は、絶対に。操作が何らかの概念を反映しており、すべてのメソッドがクラスに関連している場合は、そうです。しかし、それらが緩くて関連がない場合は、関数を使用するか、単一の責任についてもう一度考えて、メソッドを他のクラスに分割することができます

最終結果を計算するために init メソッドを使用する必要があります。それはそのクラスをテストするのを難しくしますか?

いいえ、init メソッドは初期化用です。別のメソッドで作業を行う必要があります。

CreateOption補足として、コンテキストが不足しているため、の役割が何であるかがわかりませんでした。上記のようにのみ使用する場合は、削除することもできます...

于 2013-02-11T15:26:09.360 に答える
1

私は個人的にクラスを概念と考えています。操作のように動作する操作クラスを定義するので、do() メソッドと、それを一意にする他のすべてのメソッド/プロパティが含まれます。

mgilson が正しく言っているように、概念を定義して分離することができない場合は、単純な機能的アプローチの方がよいでしょう。

質問に答えるには:

  • 特定のプロパティがインスタンス間で共有されている場合は、クラス属性を使用する必要があります (Python では、クラス属性はコンパイル時に初期化されるため、異なるオブジェクトは同じ値を参照します。通常、クラス属性は定数である必要があります)。インスタンス属性を使用して、オブジェクト固有のプロパティを渡さずにメソッドで使用できるようにします。これは、すべてを自分自身に入れる必要があるという意味ではありませんが、オブジェクトの特徴を考慮したものだけです。渡された変数を使用して、オブジェクトを考慮せず、外部オブジェクトの状態 (またはプログラムの実行) に依存する可能性がある値を設定します。
  • 上で述べたように、1 つのクラス Operation を保持し、Operation オブジェクトのリストを使用して計算を行います。
  • init メソッドは、オブジェクトをインスタンス化し、オブジェクトの適切な動作に必要なすべての処理を行います (つまり、読み取って使用します)。
  • モデル化しようとしているアイデアについて考えてみてください。
于 2013-02-11T15:30:57.630 に答える