How to create a list object? instance does not have attribute '__getitem__'

I am new to Python and to OOP in general. I have the error "...instance has no attribute '__getitem__'" , and I understand that the object I created is not a list. How can I make a list object. Here is the class file:

 #!/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 

I need to have it as a point with three coordinates inside (x, y, z), and these coordinates should be โ€œcallableโ€, as in a list instance with [].

I read similar topics, but did not quite understand. Please describe this in simple words and examples.

+4
source share
3 answers

I suggest you consider creating a Point class using the collections.namedtuple factory function, which will make it a subclass of the built-in class, in the tuple class. This will save you some work on the slabs. The namedtuple class has attributes that can be accessed by name, for example px , and by index, for example p[0] .

They are also very memory efficient, such as tuple s, which can be important if you have many instances of the class.

You can also specialize in what is returned by subclassing, or use the verbose parameter to capture the source code and, if necessary, change this parameter.

Here is an example in the above documentation showing that it is used to create a 2D Point class, which seems to be very useful in your particular use case.

Here is an example showing how you can define your own 3D Point class through a subclass:

 from collections import namedtuple class Point(namedtuple('Point', 'xy 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) 

Conclusion:

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

Note that when using namedtuple you do not need to implement __getitem__() yourself and not write the __str__() method. The only reason __init__() was needed was because of the need to increase the counter of instances of the class that was added, because namedtuple does not have or does by default.

+1
source

Write the __getitem__ method:

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

This creates a tuple for x, y and z and uses Python's own indexing facilities to access it.

Alternatively, you can switch your own internal storage to a tuple and create properties for x, y, and 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] 
+6
source

Yes, you need to define __getitem__ , but I would probably develop a class as follows that allows available attributes and indexes to coordinates.

 from collections import namedtuple class Point(object): def __init__(self, x, y, z): self._coords = namedtuple('Coords', 'xy 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) 
+1
source

All Articles