私はPythonに慣れていないので、独自のデータ構造を宣言する必要がありますが、これを行う方法について少し混乱しています。現在、次のようになっています。
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
ただし、次のコマンドでクラスのインスタンスを定義しようとすると、これは機能しません。
p1 = Particle(mass, position, velocity, force)
すべての値は、最終的に(0.0、0.0)(速度と力の値)になります。
誰かが私がどこで間違っているのか説明できますか?データ構造から必要なのは、データをそこから引き出すことができることだけです。 (編集:実際、申し訳ありませんが、後で少し変更する必要があります)
ありがとう
まず、__getitem__
がシンタックスシュガーであることを理解する必要があります。持っているのはいいことですが、必要ない場合は使用しないでください。 __getitem__
と__setitem__
は基本的に、次のような角かっこ表記を使用してオブジェクトからアイテムにアクセスできるようにする場合に使用します。
p= Particle(foo)
bar = p[0]
これが必要ない場合でも、心配する必要はありません。
さて、他のすべてに。 __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
これから得られる素晴らしい点の1つは、python p
とは何か」と尋ねると、次のように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!'
変だよね?これがあなたの肌を這わせるなら...まあ、多分そうすべきです。しかし、それは可能であり、あなたができることとできないことを私が言うのは誰ですか。これがクラスの仕組みの味です。
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
のように思える collections.namedtuple
はあなたが求めているものです:
from collections import namedtuple
Particle = namedtuple('Particle', 'mass position velocity force')
p = Particle(1, 2, 3, 4)
print p.velocity
使用する前に、このクラス定義を先に置くことができます。宣言したい場合は、次のサイトを確認してください: http://www.diveintopython.net/getting_to_know_python/declaring_functions.html
ちなみに、あなたの質問はこの投稿に似ています: Pythonで関数を前方宣言することは可能ですか? そしてこの投稿も: 本体を宣言する前に関数を使用することは可能ですか?) Pythonで?
justいくつかの属性値を格納する必要がある場合(C言語struct
と同様)、次のことを実行できます。
class myContainer(object):
pass # Do nothing
myContainerObj = myContainer()
myContainerObj.storedAttrib = 5
print myContainerObj.storedAttrib