web-dev-qa-db-ja.com

X、Y座標を配列、クラスオブジェクト、または2つの変数として保存する必要がありますか?

X座標とY座標を持つMyObjectがあります。

私が見る限り、次の3つの方法で保管できます。

class MyObject:
    def __init__(self, x, y):
        self.x = x
        self.y = y

class MyObject:
    def __init__(self, x, y):
        self.position = [x, y]

class MyObject:
    def __init__(self, x, y):
        self.position = Coord(x,y) #Coord class created elsewhere

これにはどちらの方法でもベストプラクティスがありますか?

これが関連すると私が考えているのは、これらの座標を他のメソッドに渡すときです。

例えば。

myObj = MyObject(0,0)
searchLocation(myObj.x, myObj.y)
searchLocation2(myObj.position)
5
dwjohnston

決定するのに十分なデータがない場合は、最も柔軟なオプションを選択してください。オブジェクトを選択すると、他の2つのオプションをプロパティとして使用できます。 (コメントからわかるように、リストからタプルを選択しますが。)

2

これを行うときに使用するいくつかのルールがあります。これらは、x座標とy座標だけでなく、検索条件、フラグのセット、数値パラメーターのセットなど、あらゆる種類の物に適用されます。

とはいえ、誰もがこれらの原則を使用しているわけではなく、他の決定を行う高品質のコードを見つけることがよくあります。

通常、4つ以上のパラメーターをオブジェクトにリファクタリングする必要があります

関数が4つ以上のパラメーターを取る場合、それらを一緒にグループ化するオブジェクトにリファクタリングする必要があります。

その理由は、関数の4つのパラメーターは通常単純すぎるであるためです。関数呼び出しでは、特に一部のパラメーターがデフォルト値を取るかオプションである場合、どの引数がどのパラメーターを意味するかを追跡するのが難しくなります。

次のようなコード行は、非常にイライラします。

SomeMethod(1, null, null, 1, 0)
SomeMethod(1, 1, 1, null, 5)

名前付き仮パラメーターをサポートする言語では、これはそれほど問題ではありません。しかし、通常、必要がないときにパラメータの名前を指定する必要はありません。

また、リファクタリング後も4つ以上のパラメーターを持つ関数に直面している場合は、おそらくさらに大きな問題があります。

一緒に頻繁に表示される2+パラメーターのセットは、オブジェクトにリファクタリングする必要があります

座標を含むプロジェクトでは、通常、それらをパラメータとして受け取る多くの関数を定義する必要があるため、この場合は座標の場合に触れます。

これらのパラメーターがメソッド呼び出しで頻繁に表示される場合は、おそらくそれらの間に強いリンクがあります。

拡張可能な機能を制御するパラメータのセットは、オブジェクトに配置する必要があります

たとえば、次のようなメソッドがあるとします。

Search(string name, int age, DateTime date, ...)

パラメータのリストを他の基準を追加して拡張することが理にかなっている場合は、基準のセットをオブジェクトに配置する必要があります。

0
GregRos

パフォーマンスが最も重要な場合は、2つの変数として保存してください。つまり、割り当てられるヒープオブジェクトが少なくなるため、ガベージコレクションのオーバーヘッドが低くなります。

もちろん、OPはPythonについて尋ねたので、OPはおそらくパフォーマンスについてそれほど気にしませんが、誰かがこれを読んでJavaなどを使用している可能性があります。この場合、パフォーマンスが重要になる場合があります。

コードを2次元からN次元に拡張する計画がある場合は、配列(またはPythonの場合はタプル)を使用できます。それ以外の場合は、気にしないでください。

0
juhist

xなしでyをどのくらいの頻度で使用しますか?答えがめったにないか、まったくない場合は、それらをグループ化してタプルまたはクラスにします。タプルとクラスのどちらを使用するかは、別の問題です。一般的な経験則の1つは、クラスに2つ以上のメソッドがある場合はクラスを使用し、それ以外の場合はタプルを使用することです。 namedtupleは、通常のタプルと同じくらい軽量でありながら、クラスメンバーの命名に便利です。

この答え は、例のように、ポイントでnamedtupleを使用することを話します。

0
Michael

コードオーバーヘッドなしで必要なすべての動作を実現する答えは、Pandas Seriesを使用することです。これは、インデックスによるアクセス、フィールド名(つまり.xおよび.y)によるアクセスをサポートします。 、そして要素ごとの操作をそのまま使用できるので、演算子をオーバーロードすることなく座標を加算および減算できます。

0
Nir Friedman

標準ライブラリのnamedtuple *クラスを見てみましょう。これは基本的に、各フィールドに対応する名前付きプロパティを持つタプルをサブクラス化する自動化された方法です。

ベクトルと行列の演算を行う必要がある場合は、代わりにNumPyを調べてください。これは、非常に機能的な数値データ型で構成されています。

0
StarWeaver

MyObjectの3番目の実装は、オブジェクトを座標系の2D数学から分離するため、最良であると思います。 (座標の完全な数学ライブラリを実装でき、作成したオブジェクトから完全に独立しています)。次に、オブジェクトをより柔軟にするために、xとyの2つの数値またはCoordオブジェクトのいずれかを取る関数を作成し、システムの成長に応じてさらに追加できるようにします。

0
Gus

ええ、それはその地位が「一流の市民」のどれだけであるかに依存します。他の多くのオブジェクトがそれを消費または生成する場合、および/または(Gusの回答に従って)キャプチャ/強制したい位置に関連する動作がある場合は、おそらくそれを独自のクラスにすることをお勧めします。

do独自のクラスにする場合は、definitelyコンストラクタのx要素とy要素をMyObjectから取得せずに、代わりにPositionオブジェクトを取得する必要があります。 。 MyObjectが、Positionオブジェクトを作成する必要があることに気づく必要がある理由はおそらくありません。少なくとも、与えられた例からは明らかではありません(状況によっては、これを行わない理由があるかもしれませんが)。

0
Jon Kloske