I am trying to get values from my dictionary VALUES. My program creates combination of possible positions and gets the last position. Then I want to get the value. Everything works well here except indicated .get_value method. When I execute this code I receive:
AttributeError: 'Combination' object has no attribute 'get_value'
Theoretically it should be easy but I am new to OOP and I don't see what is wrong here.
X = ['A','B','C']
Y = ['1','2','3']
VALUES = {'A':10, 'B': 50, 'C':-20}
class Combination:
def __init__(self,x,y):
if (x in X) and (y in Y):
self.x = x
self.y = y
else:
print "WRONG!!"
def __repr__ (self):
return self.x+self.y
def get_x(self):
return self.x
def get_y(self):
return self.y
class Position:
def __init__(self):
self.xy = []
for i in X:
for j in Y:
self.xy.append(Combination(i,j))
def choose_last(self):
return self.xy.pop()
def __str__(self):
return "List contains: " + str(self.xy)
class Operation1:
def __init__(self):
self.operation1 = []
def __str__(self):
s = str(self.operation1)
return s
def get_value(self):
V = VALUES.get(self)
return V
pos = Position()
print pos
last_item = pos.choose_last()
print "Last item:", last_item, pos
last_value = last_item.get_value() # <---- Here is a problem
How can I obtain value of my position? Value is determined by the X value - this is A,B or C. In the dictionary I have a numeral value for the letter.
You are appending objects of Combination into xy of Position. When you say choose_last, it will return the last Combination object inserted into xy. And you are trying to invoke get_value method on a Combination object, which doesnt have that method. Thats why you are getting that error.
Always use new style classes.
Related
I have an list of objects called character like that:
characters=[character(0,0,20,20,keys1),character(50,50,50,50,keys2),character(200,200,100,20,keys1)]
where character class is defined as:
class character():
def __init__(self,x,y,w,h,keys=keys1):
self.x = x
self.y = y
self.w = w
self.h = h
self.keys = keys
self.vel = 200 /math.sqrt(self.w*self.h)
self.crashed=False
# I need an list to use here in a function of my "character" class
# my list must have all the elements in my initial list but self
what I mean is like
characters[0].myFunction() must have a list of [characters[1],characters[2]]
which is characters =[character(50,50,50,50,keys2),character(200,200,100,20,keys1)]
you have to pass as an argument to your .myFunction the full list to know from which list to exclude/filter self:
class character():
def __init__(self,x,y,w,h,keys=keys1):
self.x = x
self.y = y
self.w = w
self.h = h
self.keys = keys
self.vel = 200 /math.sqrt(self.w*self.h)
self.crashed = False
def __repr__(self):
return 'charcter({}, {}, {}, {}, {})'.format(
self.x, self.y, self.w, self.h, self.keys)
def myFunction(self, characters):
return [e for e in characters if e != self]
print(characters[0].myFunction(characters))
output:
[charcter(50, 50, 50, 50, keys2), charcter(200, 200, 100, 20, keys1)]
I Understand what you want but there are a few issues with your code that I decided to fix for you i guess. The first is to remember just for your sake that when making classes make the first letter upper case. Next your key creation does not make any sense because keys1 doesnt exsist. I assumed it to be a string in my example. Next I created an str function for your class so it can output the characters somehow so its not only the memory address. Next I created the function you want but it will be in the format
x = myFunc(characters[0], characters)
and on top of that if you print x it will give you a list of memory addresses and therefore you must loop through and print each character specifically to see which one it is. Here is the final code.
import math
class Character():
def __init__(self,x,y,w,h,keys="keys1"):
self.x = x
self.y = y
self.w = w
self.h = h
self.keys = keys
self.vel = 200 /math.sqrt(self.w*self.h)
self.crashed=False
# I need an list to use here in a function of my "character" class
# my list must have all the elements in my initial list but self
def __str__(self):
return "Character x:{}, y:{}, w:{}, h:{}, key:{}".format(self.x, self.y, self.w, self.h, self.keys)
def myFunc(chars, characters):
characters_copy = characters[:]
if chars in characters_copy:
ind = characters_copy.index(chars)
characters_copy.pop(ind)
return characters_copy
characters = [Character(0,0,20,20), Character(50,50,50,50), Character(200,200,100,20)]
x = myFunc(characters[0], characters)
for i in x:
print(i)
I believe this is somewhat what you wanted, I added the changes so its easier for me and you. But you should be able to work with this.
from math import pi
class Circle(object):
'Circle(x,y,r)'
def __init__(self, x=0, y=0, r=1):
self._r = r
self._x = x
self._y = y
def __repr__(self):
return 'Circle({},{},{})'.\
format(self.getx(), self.gety(),\
self.getr())
#silly, but has a point: str can be different from repr
def __str__(self):
return 'hello world'
def __contains__(self, item):
'point in circle'
px, py = item
return (self.getx() - px)**2 + \
(self.gety() - py)**2 < self.getr()**2
def getr(self):
'radius'
return self._r
def getx(self):
'x'
self._lst.append(self._x)
return self._x
def gety(self):
'y'
self._lst.append(self._y)
return self._y
def setr(self,r):
'set r'
self._r = r
def setx(self,x):
'set x'
self._x = x
def sety(self,y):
'set y'
self._y = y
def move(self,x,y):
self._x += x
self._y += y
def concentric(self, d):
d = self._list
def area(self):
'area of circle'
return (self.getr())**2*pi
def circumference(self):
'circumference of circle'
return 2*self.getr()*pi
My question is worded kinda awkwardly but what I am trying to do is check if 2 different circles have the same center (x,y). I think the easiest way to solve this would be to input the 2 points into a list but I am not sure how to compare the 2 lists as every time i try my code it adds everything to the same list
Add the following method to your Circle class.
def equal_center(self, other):
'check if another circle has same center'
return (self._x == other._x) & (self._y == other._y)
Usage
C1 = Circle(3, 5, 8)
C2 = Circle(3, 5, 10)
C3 = Circle(3, 2, 1)
C1.equal_center(C2) # True
C1.equal_center(C3) # False
I would recommend creating a function which takes two circle objects and returns if the coordinates are the same or not by comparing the x and y values of each object:
def same_center(circle_1, circle_2):
if circle_1.getx() == circle_2.getx() and circle_1.gety() == circle_2.gety():
return True
else:
return False
This solution is much easier than using lists and should be easy to implement.
If you have two instances of the class...
a = Circle(0,0,1)
b = Circle(0,0,1)
You could add them to a list of circles...
circles = [a,b]
And loop through the list, checking their values...
for i in circles:
for j in filter(lambda x : x != i, circles):
if i._x == j._x and i._y == j._y:
return True #two circles have same center
This should work for n instances of the class, though if its only two you want to check
if a._x == b._x and a._y == a._y:
return True
I am trying to build a iterable graph class with python 2.7. I want to be able to iterate though a dictionary containing the vertexes.
Cutting and pasting from https://github.com/joeyajames has got me so far but now I am confused as to how to make this work so that
I can test vertices dict for the presence of an vertice and add if not present. This part is maybe unneeded.
"if (a not in gra ):" because the validation is done in the Graph class itself.
The expected output is a dictionary with the vertices as keys. Actualy im not even sure a list is not better object to use.
class Vertex(object):
def __init__(self, n):
self.name = n
self.neighbors = list()
self.discovery = 0
self.finish = 0
self.color = 'black'
def add_neighbor(self, v):
if v not in self.neighbors:
self.neighbors.append(v)
self.neighbors.sort()
class Graph(object):
def __init__(self,size):
self.vertices = {}
self.hops = 0
self.count = 0
self.limit = size
def __iter__(self):
return self
def next(self):
self.count += 1
if self.count > self.limit:
raise StopIteration
def add_vertex(self,vertex):
if isinstance(vertex, Vertex) and vertex.name not in self.vertices:
self.vertices[vertex.name] = vertex
return True
else:
return False
def add_edge(u,v):
if u in self.vertices and v in self.vertices:
for key, value in self.vertices.items():
if key == u:
value.add_neighbor(v)
if key == v:
value.add_neighbor(u)
return True
else:
return False
def _dfs(self, vertex):
global hops
vertex.color = 'red'
vertex.discovery = hops
hops += 1
for v in vertex.neighbors:
if self.vertices[v].color == 'black':
self._dfs(self.vertices[v])
vertex.color = 'blue'
vertex.finish = hops
time += 1
input = ((5,3),(4 ,2),(0,1),(2 3),(0 4))
N,l = input[0]
print "N is " + str(N)
print "l is " + str(l)
gra = Graph(N)
for i in xrange(1,l):
a,b = input[i]
# Store a and b as vertices in graph object
print "a is " + str(a) + " b is " + str(b)
if (a not in gra ):
print "adding a"
gra.add_vertex(Vertex(chr(a)))
if (b not in gra ):
print "adding b"
gra.add_vertex(Vertex(chr(b)))
You are trying to use not in, which tests for containment; implement the __contains__ hook to facilitate that:
def __contains__(self, vertex):
return vertex.name in self.vertices
I've assumed you wanted to test for vertices, so create one before testing for containment:
a = Vertex(chr(a))
if a not in gra:
print "adding a"
gra.add_vertex(a)
For iteration, I'd not make Graph itself the iterator; that limits you to iterating just once. Your next() method also lacks a return statement, so all you are doing is produce a sequence of None objects.
Make it an iterable instead, so return a new iterator object each time __iter__ is called. You can most simply achieve this by making __iter__ a generator:
def __iter__(self):
for vertex in self.vertices.itervalues():
yield vertex
Note the yield. I've assumed you wanted to iterate over the vertices.
I'm new to Python and I really want to understand why I get this error.
It happens in my findLargest function, while trying to execute the second for loop. The thing is that the second for loop does basically the same thing as the first one, but for some reason I get an error as I try to call on a (class)method. How can this be? Am I not allowed to have 2 for loops for same iterable in the same function?
shapeArea=shape.area()
throws:
TypeError: 'float' object is not callable
The objective of findlargest() is to loop through the set of classes twice, first in order to find the largest value(Area) while the second tries to find if there are other values that are equal.
class Shape(object):
def area(self):
raise AttributeException("Subclasses should override this method.")
class Triangle(Shape):
def __init__(self, base, height):
self.base = base
self.height = height
def area(self):
self.area = (self.base * self.height) / 2
return self.area
def __str__(self):
return "{} with base {} and height {}".format(self.__class__.__name__, self.base, self.height)
def __eq__(self, other):
return type(other) == Triangle and self.base == other.base and self.height == other.height
class ShapeSet:
def __init__(self):
self.shape_list = []
def addShape(self, sh):
if sh not in self.shape_list:
self.shape_list.append(sh)
else:
print ("{} is already existing".format(sh.__str__()))
def __iter__(self):
return (self.shape_list)
def __str__(self):
s = ''
for shape in self.__iter__():
s+= shape.__str__() + "\n"
return s
ss = ShapeSet()
ss.addShape(Triangle(1.2,2.5))
ss.addShape(Triangle(1.4,2.5))
ss.addShape(Triangle(1.3,2.5))
ss.addShape(Triangle(1.5,2.5))
def findLargest(shapes):
maxs = None
maxA = 0.0
for shape in shapes.__iter__():
shapeArea = shape.area()
if shapeArea > maxA or maxs == None:
maxs = shape
maxA = shapeArea
maxTuple = (maxs)
for shape in shapes.__iter__():
shapeArea = shape.area()
With this:
def area(self):
self.area=(self.base*self.height)/2
return self.area
You enter the method and then immediately mask it by assigning a different name to its reference. From then on, self.area refers to that number and you can no longer access that method. Fortunately, the fix is easy: don't save a reference at all.
def area(self):
return self.base * self.height / 2
Python does not separate the names for function/method objects and for other objects. Use unique reference names for any objects you'd like to retain.
I think your problem is here:
class Triangle(Shape):
def __init__(self, base, height):
self.base=base
self.height=height
def area(self):
self.area=(self.base*self.height)/2 ###################### HERE
return self.area
If you have
shape = Triangle(1.5,2.5)
shape.area() # returns float assigned at "HERE" to shape.area
shape.area() # try to call that float assigned in previous step at "HERE"
I'm working on the MIT open courseware for CS-600 and I can't figure out why the last print statement isn't printing anything. Here's the code I wrote:
#!/usr/bin/env python
# encoding: utf-8
# 6.00 Problem Set 9
#
# Name:
# Collaborators:
# Time:
from string import *
class Shape(object):
def area(self):
raise AttributeException("Subclasses should override this method.")
class Square(Shape):
def __init__(self, h):
"""
h: length of side of the square
"""
self.side = float(h)
def area(self):
"""
Returns area of the square
"""
return self.side**2
def __str__(self):
return 'Square with side ' + str(self.side)
def __eq__(self, other):
"""
Two squares are equal if they have the same dimension.
other: object to check for equality
"""
return type(other) == Square and self.side == other.side
class Circle(Shape):
def __init__(self, radius):
"""
radius: radius of the circle
"""
self.radius = float(radius)
def area(self):
"""
Returns approximate area of the circle
"""
return 3.14159*(self.radius**2)
def __str__(self):
return 'Circle with radius ' + str(self.radius)
def __eq__(self, other):
"""
Two circles are equal if they have the same radius.
other: object to check for equality
"""
return type(other) == Circle and self.radius == other.radius
#
# Problem 1: Create the Triangle class
#
## TO DO: Implement the `Triangle` class, which also extends `Shape`.
class Triangle(Shape):
def __init__(self, base, height):
self.base = float(base)
self.height = float(height)
def area(self):
return self.base*self.height/2
def __str__(self):
return 'Triangle with base ' + str(self.base) + 'and height ' + str(self.height)
def __eq__(self, other):
return type(other) == Triangle and self.base == other.base and self.height == other.height
#
# Problem 2: Create the ShapeSet class
#
## TO DO: Fill in the following code skeleton according to the
## specifications.
class ShapeSet(object):
def __init__(self):
"""
Initialize any needed variables
"""
self.allCircles = []
self.allSquares = []
self.allTriangles = []
self.allShapes = self.allCircles + self.allSquares + self.allTriangles
self.place = None
def addShape(self, sh):
"""
Add shape sh to the set; no two shapes in the set may be
identical
sh: shape to be added
"""
if not isinstance(sh, Shape): raise TypeError('not a shape')
if isinstance(sh, Square):
for sq in self.allSquares:
if sh == sq:
raise ValueError('shape already in the set')
self.allSquares.append(sh)
if isinstance(sh, Triangle):
for tri in self.allTriangles:
if sh == tri:
raise ValueError('shape already in the set')
self.allTriangles.append(sh)
if isinstance(sh, Circle):
for circ in self.allCircles:
if sh == circ:
raise ValueError('shape already in the set')
self.allCircles.append(sh)
def __iter__(self):
"""
Return an iterator that allows you to iterate over the set of
shapes, one shape at a time
"""
self.place = 0
return self
def next(self):
if self.place >= len(self.allShapes):
raise StopIteration
self.place += 1
return self.allShapes[self.place - 1]
def __str__(self):
"""
Return the string representation for a set, which consists of
the string representation of each shape, categorized by type
(circles, then squares, then triangles)
"""
shapeList = ""
for item in self.allShapes:
shapeList += item.get__str__ + "br/"
return shapeList
#
# Problem 3: Find the largest shapes in a ShapeSet
#
def findLargest(shapes):
"""
Returns a tuple containing the elements of ShapeSet with the
largest area.
shapes: ShapeSet
"""
## TO DO
#
# Problem 4: Read shapes from a file into a ShapeSet
#
def readShapesFromFile(filename):
"""
Retrieves shape information from the given file.
Creates and returns a ShapeSet with the shapes found.
filename: string
"""
## TO DO
def main():
sq1 = Square(4.0)
sq2 = Square(5.0)
sq3 = Square(3.0)
circ1 = Circle(3.0)
circ2 = Circle(3.2)
tri1 = Triangle(3.0, 4.0)
tri2 = Triangle(4.0, 3.0)
tri3 = Triangle(1.0, 1.0)
thisSet = ShapeSet()
thisSet.addShape(sq1)
thisSet.addShape(sq2)
thisSet.addShape(sq3)
thisSet.addShape(circ1)
thisSet.addShape(circ2)
thisSet.addShape(tri1)
thisSet.addShape(tri2)
thisSet.addShape(tri3)
print thisSet
if __name__ == '__main__':
main()
This line:
self.allShapes = self.allCircles + self.allSquares + self.allTriangles
doesn't do what you think it does. It sets allShapes to an empty list, and then as you add shapes later, nothing updates allShapes.
Then your __str__ function just loops over allShapes, which is still empty, so your __str__ returns an empty string.
This line makes allShapes an empty list:
self.allShapes = self.allCircles + self.allSquares + self.allTriangles
If you modify allCircles, that doesn't affect allShapes. I would personally eliminate allShapes, and in the str method, add them at the last possible second:
for item in self.allCircles + self.allSquares + self.allTriangles:
The problem is here:
self.allShapes = self.allCircles + self.allSquares + self.allTriangles
When you concatenate lists like this, the result is a copy of the component lists. So when those lists are changed later, the concatenated list isn't changed. In this case, self.allCircles, etc. are all empty. So self.allShapes is an empty list too; the for loop in ShapeSet.__str__ doesn't append anything to ShapeList, and so the result is an empty string.
One simple way to fix this would be to make allShapes a method that you call, and that returns a new concatenation of self.allCircles... etc. each time it's called. That way, allShapes is always up-to-date.
If this is your actual code, then it must be because of
item.get__str__
which should raise an exception.
Edit: as others have noted, this isn't the actual problem, but I leave this here as a hint for further progress. Mind you, it's considered bad style ("unpythonic") to call x.__str__() directly, as you probably intended. Call str(x) instead, even in the implementation of __str__.
You assign allShapes to be the value of self.allCircles + self.allSquares + self.allTriangles at the start in your init method (when the other lists are empty).
It's value is then never changed, so it remains empty.
You need this in addShape:
self.allShapes.append(sh)