11

PythonでPointクラスを作ろうとしています。__ str__ や __ getitem__ などのいくつかの関数は既に実装されており、うまく機能します。私が直面している唯一の問題は、__ setitem__ の実装が機能しないことです。他のものはうまくやっています。

これが私の Point クラスで、最後の関数は私の __ setitem__ です。

class point(object):
    def __init__(self,x=0,y=0):
        self.x=x
        self.y=y

    def __str__(self):
        return "point(%s,%s)"%(self.x,self.y)

    def __getitem__(self,item):
        return (self.x, self.y)[item]

    def __setitem__(self,x,y):
        [self.x, self.y][x]=y

次のように動作するはずです。

p=point(2,3)
p[0]=1 #sets the x coordinate to 1
p[1]=10 #sets the y coordinate to 10

(私は正しいですか? setitem はこのように機能しますか?) ありがとう!

4

7 に答える 7

16

座標値self.dataのみself.dataを保持します。これらの値も保存する場合は、一貫して更新される可能性がありself.x、または更新されない可能性があります。self.yself.dataself.xself.y

代わりに、から値を検索する makexおよびy プロパティself.dataを使用します。

class Point(object):
    def __init__(self,x=0,y=0):
        self.data=[x, y]

    def __str__(self):
        return "point(%s,%s)"%(self.x,self.y)

    def __getitem__(self,item):
        return self.data[item]

    def __setitem__(self, idx, value):
        self.data[idx] = value

    @property
    def x(self):
        return self.data[0]

    @property
    def y(self):
        return self.data[1]

ステートメント

[self.x, self.y][x]=y

興味深いが問題がある。それをバラバラにしましょう:

[self.x, self.y]は Python に値とを持つ新しいリストを作成させます。self.xself.y

somelist[x]=yPythonは の番目のインデックスに値yを代入します。したがって、この新しいリストは更新されます。しかし、これは、またはには影響しません。そのため、元のコードが機能していませんでした。xsomelistsomelistself.dataself.xself.y

于 2013-04-02T21:37:24.007 に答える
2

これはpython 2.6で機能します.2.7でも機能すると思います

__ setitem __メソッドは 3 つの引数 (self、index、value) を受け入れます

この場合、インデックスを int として使用して、 __スロット__タプルから座標の名前を取得します ( __スロット__のドキュメントを確認すると、パフォーマンスに非常に役立ちます)。

__スロット__で覚えておいてください __ xおよびy属性のみが許可されます! それで:

p = Point()
p.x = 2
print(p.x)  # 2.0

p.z = 4  # AttributeError
print(p.z)  # AttributeError

この方法は、@propertyデコレーターを使用することでより高速になります (10000 以上のインスタンスを使用し始めた場合)

class Point(object):
    @property
    def x(self):
        return self._data[0]  # where self._data = [x, y]
...

だからこれはあなたのための私のヒントです:)

class Point(object):

    __slots__ = ('x', 'y')  # Coordinates

    def __init__(self, x=0, y=0):
        '''
        You can use the constructor in many ways:
        Point() - void arguments
        Point(0, 1) - passing two arguments
        Point(x=0, y=1) - passing keywords arguments
        Point(**{'x': 0, 'y': 1}) - unpacking a dictionary
        Point(*[0, 1]) - unpacking a list or a tuple (or a generic iterable)
        Point(*Point(0, 1)) - copy constructor (unpack the point itself)
        '''
        self.x = x
        self.y = y

    def __setattr__(self, attr, value):
        object.__setattr__(self, attr, float(value))

    def __getitem__(self, index):
            '''
            p = Point()
            p[0]  # is the same as self.x
            p[1]  # is the same as self.y
            '''
        return self.__getattribute__(self.__slots__[index])

    def __setitem__(self, index, value):
            '''
            p = Point()
            p[0] = 1
            p[1] = -1
            print(repr(p))  # <Point (1.000000, -1.000000)>
            '''
        self.__setattr__(self.__slots__[index], value)  # converted to float automatically by __setattr__

    def __len__(self):
        '''
        p = Point()
        print(len(p))  # 2
        '''
        return 2

    def __iter__(self):
        '''
        allow you to iterate
        p = Point()
        for coord in p:
            print(coord)

        for i in range(len(p)):
            print(p[i])
        '''
        return iter([self.x, self.y])

    def __str__(self):
        return "(%f, %f)" % (self.x, self.y)

    def __repr__(self):
        return "<Point %s>" % self
于 2013-08-21T22:10:24.037 に答える
2

これはかなり古い投稿ですが、問題の解決策は非常に簡単です。

class point(object):
    def __init__(self,x=0,y=0):
        self.x=x
        self.y=y

    def __str__(self):
        return "point(%s,%s)"%(self.x,self.y)

    def __getitem__(self,item):
        return self.__dict__[item]

    def __setitem__(self,item,value):
        self.__dict__[item] = value

各クラスには、クラス内で作成されたすべてのプロパティとメソッドを含む独自の辞書があります。したがって、これで次のように呼び出すことができます。

In [26]: p=point(1,1)
In [27]: print p
point(1,1)
In [28]: p['x']=2
In [29]: print p
point(2,1)
In [30]: p['y']=5
In [31]: print p
point(2,5)

「インデックス」のような参照よりも読みやすいです。

于 2014-05-11T10:15:11.943 に答える
2

これを最小限に抑えましょう。

x, y = 2, 3
[x, y][0] = 1
print(x)

これは印刷され2ます。

なんで?

は、[x, y]2 つの要素を含むまったく新しいリストです。最初のメンバーを に再割り当てすると1、新しいリストが変更されるだけなので、最初の要素は1ではなく2. 2数値を数値に変換しません1

あなたのコードは本質的にこれと同一であるため、同じ問題があります。変数に不変の値がある限り、変数を変更することはできません。


次のようにして修正できます。

x, y = [2], [3]
[x, y][0][0] = 1
print(x[0])

これで、 が得られます1

なんで?は、それぞれがリストで[x, y]ある 2 つの要素を持つ新しいリストです。最初の要素を別のものに置き換えているのではなく、最初の要素の最初の要素を別のものに置き換えています。しかし、その最初の要素は と同じリストなのでx、 の最初の要素も別のものに置き換えてxいます。


これを頭に入れておくのが少し難しい場合は…まあ、それは通常、すべきではないことをしているというサインです。(また、x「選択xまたはyyを意味するパラメーターと「新しい値」を意味するパラメーターに使用しているという事実は、それをさらに混乱させます…)

同じことを行うためのより簡単な方法がたくさんあります。

  • 凝ろうとする代わりに、 if/ステートメントを使用してください。else
  • list2 つの整数値の代わりに 1 つの値を使用します: self.values[x] = y. (それはunutbuの答えです。)
  • dict2 つの整数値の代わりにa を使用します: self.values['xy'[x]] = y.
  • を使用しsetattr(self, 'xy'[x], y)ます。
  • namedtuple自分で同じものを構築しようとする代わりに、 a を使用してください。
于 2013-04-02T21:41:00.887 に答える
0

setitem で何が起こっているかというと、一時的なリストを作成し、値を設定してから、self.x または self.y を変更せずにこのリストを破棄します。これを試してください__setitem__

def __setitem__(self,coord,val):
    if coord == 0:
        self.x = val
    else:
        self.y = val

ただし、これはかなりの乱用__setitem__です...可能であれば、x / y座標を設定する別の方法を考え出すことをお勧めします。px と py を使用すると、実装方法に関係なく、p[0] と p[1] よりもはるかに高速になります。

于 2013-04-02T21:41:37.190 に答える