2013-03-07 15 views
5

私はPythonにはかなり新しく、私自身のデータ構造を宣言する必要がありますが、これをどうやって行うのかちょっと混乱します。私は現在持っている:Pythonのカスタムデータ構造

p1 = Particle(mass, position, velocity, force) 

すべての値がちょうど(0.0、0.0)のように終わる:

class Particle: 

    def __init__(self, mass, position, velocity, force): 

     self.mass = mass 
     self.position, self.velocity, self.force = position, velocity, force 

    def __getitem__(self, mass): 
     return self.mass 

    def __getitem__(self, position): 
     return self.position 

    def __getitem__(self, velocity): 
     return self.velocity 

    def __getitem__(self, force): 
     return self.force 

これは私がして、クラスのインスタンスを定義しようとすると、しかし、動作していません(速度と力の値です)。

誰かが私が間違っていると説明してもらえますか、私がデータ構造から必要とするのは、データをそこから引き出すことができることだけです。 (編集:実際には、申し訳ありませんが、私は少し後にそれらを変更する必要があります)

おかげ

+2

これは私のために動作します。 – askewchan

+2

すべての '__getitem__'定義は同じメソッドです。実際に検索されている項目を確認する必要があります。 –

+3

@askewchanすべきではありません。 –

答えて

15

まず、__getitem__が構文的な砂糖であることを理解する必要があります。それはいいですが、必要がない場合は使用しないでください。あなたは、このする必要がない場合は、それについて心配しないでください

p= Particle(foo) 
bar = p[0] 

:あなたのようなブラケット表記を使用して、オブジェクトからアイテムにアクセスできるようにしたい場合は__getitem____setitem__は基本的にあります。

今、他のすべてに。 __init__の定義であなたのオブジェクトが持ち歩きたい主な特徴を持っているようです。これは問題ありません。今、あなたは実際にselfを使用して、オブジェクトにそれらの値をバインドする必要があります。

class Particle: 
    def __init__(self, mass, position, velocity, force): 
     self.mass = mass 
     self.position = position 
     self.velocity = velocity 
     self.force = force 

本当にそれだこと。あなたは今では同様に、ドット表記を使用して、これらの値にアクセスすることができます。私たちはこのから抜け出す素敵な物事の

mass,pos,vel,f = 0,0,0,0 # just for readability 
p = Particle(mass,pos,vel,f) 
print p.mass, p.position, p.velocity, p.force 

一つは、我々はpが何であるかのpythonに言わせれば、それはそれはのインスタンスであることを教えてくれますということですそのようなParticleタイプ:理論的には

in [1]: p 
out[1]: <__main__.Particle instance at 0x03E1fE68> 

、あなたがこのようなオブジェクトを操作するときに、彼らがアクセスしたり、操作していないことを、ユーザーとデータがこのような間の「抽象化層」があるようにしたいですデータを直接。これを行うには、クラスメソッドを使用してユーザーとデータの間のやりとりを仲介するための関数(__getitem__と同じように)を作成します。これはいいですが、しばしば必要ではありません。お使いのシンプルな場合

、これらの属性の値を更新するために、あなただけの直接我々はドット表記で、それらにアクセスし、同じようにそれを行うことができます:あなたはすでにこれを考え出したかもしれない

in [2]: p.mass 
out[2]: 0 

in [3]: p.mass = 2 
in [4]: p.mass 
out[4]: 2 

が、 __init__関数、またはclassの定義(あなたのクラスの属性とメソッドの大部分を定義しているはずです)についても不思議なことはありません。特定の種類のオブジェクトは、いつでもどこでも属性を追加できるという点でかなり許容されています。これは便利かもしれませんが、一般的には非常にハッキーであり、良い練習ではありません。私はあなたがこれをすることを示唆するものではなく、可能であることをあなたに示しています。

in [5]: p.newattr ='foobar!' 
in [6]: p.newattr 
out[6]: 'foobar!' 

奇妙な権利ですか?これがあなたの肌を這うならば...まあ、たぶんそれはすべきです。しかし、それは可能であり、私はあなたができることとできないことを言う人です。クラスの仕組みの味です。

+0

それは素晴らしいです、ありがとう!ただし、パーティクルのインスタンスを作成した後に値を変更するにはどうすればよいですか? – djcmm476

+0

@Incredidave Assignmentは変数と同じように(微妙な違いがありますが、ほとんどの人は何も理解していないので、大丈夫です^^): 'p.mass = new value' – delnan

+0

@delnanロット。 – djcmm476

1

あなたがそれを使用する前に控え、このクラス定義を置くことができます。あなたはそれを宣言したい場合は、このサイトでご確認ください:ところでhttp://www.diveintopython.net/getting_to_know_python/declaring_functions.html

を、あなたの質問は、この記事のようになります。Is it possible to forward-declare a function in Python?もこのポスト:あなたのクラスがありふりをしたい場合はIs it possible to use functions before declaring their body in python?

7
class Particle: 
    def __init__(self, mass, position, velocity, force): 
     self.mass = mass 
     self.position = position 
     self.velocity = velocity 
     self.force = force 

particle = Particle(1, 2, 3, 4) 
print(particle.mass) # 1 

プロパティ、あなたは@propertyデコレータ使用することができます。

class Particle: 
    def __init__(self, mass, position, velocity, force): 
     self.mass = mass 
     self.position = position 
     self.velocity = velocity 
     self.force = force 

    @property 
    def acceleration(self): 
     return self.force/self.mass 

particle = Particle(2, 3, 3, 8) 
print(particle.acceleration) # 4.0 
+0

これは素晴らしいです、ありがとう。私はPythonにはかなり新しく、これを記述するために何かを見つけるのに苦労していました。いつものようにPythonでは、答えは私が思ったより簡単です。 – djcmm476

+0

興味がありません、実際にプロパティを持っているときに*簡単にプロパティを持つのはなぜ簡単ですか? – delnan

+0

@delnan他の2つのプロパティに依存する式でプロパティが定義されているとします。それらのうちの1つ(質量のようなもの)を変更すると、加速を更新する必要があります。これはたぶんバグや乱雑なコードを意味します。 –

4

collections.namedtupleようだが、あなたが後にしているものです:

from collections import namedtuple 

Particle = namedtuple('Particle', 'mass position velocity force') 
p = Particle(1, 2, 3, 4) 
print p.velocity 
+1

オブジェクトの存続期間中に属性を変更する必要がなく、シーケンスであれば問題ありません。メソッドを追加する必要があるときや、コンストラクタのようなものを追加する必要があるときには、名前付きタプルの綺麗さが損なわれます(まだ便利ですが、うまく動作させるには慎重な扱いと醜いコードが必要です)。 – delnan

+1

@delnan真実ですが、私は、データ構造から必要なものは、それ以外のデータを引き出すことができるというOPの声明になります。 –

+0

ええ、あなたの答えは問題ありません。それは、たとえ重要であったとしても、私がそれらの言葉に言及する習慣を覚えたときでさえ、その限界をほとんど見かけることはほとんどありません。 – delnan

0

(C言語structと同様に)いくつかの属性値を格納するために、あなただけの必要がある場合は、あなただけ行うことができます。あるとして

class myContainer(object): 
    pass # Do nothing 

myContainerObj = myContainer() 
myContainerObj.storedAttrib = 5 
print myContainerObj.storedAttrib 
+0

Nah、それは辞書を書くのにはちょっとひどい方法です。非常に強い理由なしにオブジェクトに属性を追加したり削除したりする機能を使用することに反対します。これは、エラーを見つけにくくします(時には属性に属性がありますが、時にはそれが制御フローによって異なります)。 – delnan

+0

@delnan私は一般的に同意しますが、Pythonを初めて使う人にとっては、簡単な解決策であり、辞書、ハッシュ、および 'get()'メソッドを理解する必要はありません。 (これはPythonのチュートリアルの文書でもあります:http://docs.python.org/3/tutorial/classes.html#odds-andends) – neilr8133

+0

編集:(_insert_: "' get() 'メソッドは値を指定します属性が存在しない場合、または定義されているかどうかを調べる他の方法」)。個人的には、私はむしろ、 '__init__'で完全なクラスを見て、すべてのプロパティの適切なget/setメソッドを見ていましたが、私の(誤ったかもしれない)意見ではOPのニーズを満たしていました。 – neilr8133