11

私は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) (速度と力の値) になります。

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

ありがとう

4

6 に答える 6

25

__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!'

変ですよね?これがあなたの肌を這わせるなら...まあ、そうすべきかもしれません. しかし、それは可能であり、あなたができることとできないことを言うのは誰ですか. これが、クラスの仕組みの一部です。

于 2013-03-07T21:15:25.917 に答える
8
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
于 2013-03-07T21:11:20.813 に答える
4

collections.namedtupleあなたが求めているのは次のようです:

from collections import namedtuple

Particle = namedtuple('Particle', 'mass position velocity force')
p = Particle(1, 2, 3, 4)
print p.velocity
于 2013-03-07T21:14:58.870 に答える
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?

于 2013-03-07T21:11:06.977 に答える
0

いくつかの属性値を保存する必要がある場合(C 言語に似ています)、次のようにするだけstructです。

class myContainer(object):
    pass  # Do nothing

myContainerObj = myContainer()
myContainerObj.storedAttrib = 5
print myContainerObj.storedAttrib
于 2013-03-07T21:19:54.007 に答える