4

私はPythonと一般的なOOPの初心者です。エラーが発生"...instance has no attribute '__getitem__'"しました。作成したオブジェクトがリストではないことを理解しています。どうすればリストオブジェクトにすることができますか。クラスファイルは次のとおりです。

#!/usr/bin/python -tt

import math, sys, matrix, os

class Point:
    'Class for points'
    pointCount = 0

    def __init__(self, x, y, z):
        'initialise the Point from three coordinates'
        self.x = x
        self.y = y
        self.z = z
        Point.pointCount += 1

    def __str__(self):
        'print the Point'
        return 'Point (%f, %f, %f)' %(self.x, self.y, self.z)

    def copyPoint(self, distance):
        'create another Point at distance from the self Point'
        return Point(self.x + distance[0], self.y + distance[1], self.z + distance[2])

    def __del__(self):
        'delete the Point'
        Point.pointCount -= 1
        #print Point.pointCount
        return '%s deleted' %self

内部に3つの座標(x、y、z)を持つポイントとしてそれを持っている必要があり、それらの座標は[]を使用したリストインスタンスのように「呼び出し可能」である必要があります。

私は同様のトピックを読みましたが、あまり理解していませんでした。簡単な言葉と例で説明してください。

4

3 に答える 3

5

メソッドを書く__getitem__

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

これによりtuple、x、y、zのaが作成され、Python独自のインデックス作成機能を使用してアクセスします。

または、独自の内部ストレージをタプルに切り替えて、x、y、zのプロパティを作成することもできます。

def __init__(self, x, y, z):
    self.coords = (x, y, z)

@property
def x(self):  # sim. for y, z
    return self.coords[0]

def __getitem__(self, item):
    return self.coords[item]
于 2012-07-19T14:49:55.810 に答える
0

はい、定義する必要がありますが__getitem__、おそらく次のようにクラスを設計します。これにより、座標への属性とインデックスのアクセスが可能になります。

from collections import namedtuple

class Point(object):
    def __init__(self, x, y, z):
        self._coords = namedtuple('Coords', 'x y z')._make( (x, y, z) )

    @property
    def coords(self):
        return self._coords

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

    def copy_point(self, distance):
        return Point(*(el + distance for el in self.coords))

    def __repr__(self):
        return 'Point: {}'.format(self.coords)

p = Point(1, 2, 3)
p.copy_point(20), p.coords[0], p.coords.x
# (Point: Coords(x=21, y=22, z=23), 1, 1)
于 2012-07-19T15:14:56.807 に答える
0

collections.namedtupleファクトリ関数を使用してPointクラスを作成することを検討することをお勧めします。これにより、組み込みtupleクラスのサブクラスになります。これにより、ボイラープレートの作業を節約できます。クラスには、のような名前とのようなインデックスのnamedtuple両方でアクセスできる属性があります。p.xp[0]

また、tuplesのようにメモリ効率が非常に高く、クラスインスタンスを多数持つ場合に重要になる可能性があります。

サブクラス化することで返されるものをさらに特殊化するか、verboseオプションを使用してソースコードをキャプチャし、必要に応じて変更することができます。

上記にリンクされているドキュメントには、2Dクラスの作成に使用されていることを示す例がありPointます。これは、特定のユースケースで非常に役立つ可能性があるようです。

サブクラス化を介してカスタム3Dポイントクラスを定義する方法を示す例を次に示します。

from collections import namedtuple

class Point(namedtuple('Point', 'x y z')):
    __slots__ = ()  # prevent creation of instance dictionaries to save memory
    point_count = 0  # instance counter

    def __init__(self, *args):
        super(Point, self).__init__(*args)
        Point.point_count += 1

    def distance(self, other):
        return sum((self[i]-other[i])**2 for i in xrange(len(self))) ** 0.5

    def copy_point(self, distance):
        'create another Point at distance from the self Point'
        return Point(*[dimension+distance for dimension in self])

p1 = Point(0, 0, 0)
print 'p1:', p1
p2 = p1.copy_point(20)
print 'p2: Point(%s)' % ', '.join(str(p2[i]) for i in xrange(len(p2)))
print 'distance p1 <-> p2: %.3f' % p1.distance(p2)

出力:

p1: Point(x=1, y=2, z=3)
p2: Point(21, 22, 23)
distance p1 <-> p2: 34.641

を使用することで、自分で実装したり、メソッドを記述したりnamedtupleする必要がないことに注意してください。が必要だった唯一の理由は、追加されたクラスインスタンスカウンターをインクリメントする必要があるためでした。これは、デフォルトではないか、実行されません。__getitem__()__str__()__init__()namedtuple

于 2012-07-19T16:17:15.433 に答える