How to retrieve a variable name given its value - python

class type_name:
def __init__(self, *field_names):
self.x = field_names[0]
self.y = field_names[1]
self._fields = [x for x in field_names]
def get_y(self):
return self.y
def __getitem__(self, ind):
fstr = 'self.get_' + str(self._fields[ind]) #this would give me 5 i want self.y so I construct a string such as 'self.get_y()'
#and then return eval on that string to return the value
Using this code above,
Point = pnamedtuple('Point', ['x','y'], mutable = False)
origin = Point(0,5)
print(origin[1])
It should also work with origin['y']

Related

Is there a way to have a object type of your choice (i.e. LinkedEdge) hash as part of a 'union.set()' processing?

I have the following code and it works until it gets to the 'union.set()' part. It says, "unhashable type: 'LinkedEdge' " . I am not sure why this is the case since I have looked at other sources on the web and in reference books to know that the 'g.addVertex()' method and the 'g.addEdge()' method as well as the arguments being passed should lead correctly to an output like this:
5 Vertices: A C B E D
5 Edges: A>B:3 A>C:2 B>D:1 C>D:1 D>E:2
class LinkedEdge(object):
def __init__(self, fromVertex, toVertex, weight = None):
self._vertex1 = fromVertex
self._vertex2 = toVertex
self._weight = weight
self._mark = False
def clearMark(self):
self._mark = False
def __eq__(self, other):
if self is other: return True
if type(self) != type(other):
return False
return self._vertex1 == other._vertex1 and self._vertex2 == other._vertex2
def getOtherVertex(self, thisVertex):
if thisVertex == None or thisVertex == self._vertex2:
return self._vertex1
else:
return self._vertex2
def getToVertex(self):
return self._vertex2
def getWeight(self):
return self._weight
def isMarked(self):
return self._mark
def setMark(self):
self._mark = True
def setWeight(self, weight):
self._weight = weight
def __str__(self):
return str(self._vertex1) + ">" + str(self._vertex2) + ":" + str(self._weight)
class LinkedVertex(object):
def __init__(self, label):
self._label = label
self._edgeList = []
self._mark = False
def clearMark(self):
self._mark = False;
def getLabel(self):
return self._label
def isMarked(self):
return self._mark
def setLabel(self, label, g):
g._vertices.pop(self._label, None)
g._vertices[label] = self
self._label = label
def setMark(self):
self._mark = True
def __str__(self):
return str(self._label)
def addEdgeTo(self, toVertex, weight):
edge = LinkedEdge(self, toVertex, weight)
self._edgeList.append(edge)
def getEdgeTo(self, toVertex):
edge = LinkedEdge(self, toVertex)
try:
return self._edgeList[self._edgeList.index(edge)]
except:
return None
def incidentEdges(self):
return iter(self._edgeList)
def neighboringVertices(self):
vertices = []
for edge in self._edgeList:
vertices.append(edge.getOtherVertex(self))
return iter(vertices)
def removeEdgeTo(self, toVertex):
edge = LinkedEdge(self, toVertex)
if edge in self._edgeList:
self._edgeList.remove(edge)
return True
else:
return False
class LinkedDirectedGraph(object):
def __init__(self, collection = None):
self._vertexCount = 0
self._edgeCount = 0
self._vertices = {}
if collection != None:
for label in collection:
self.addVertex(label)
# Methods for clearing, marks, sizes, string rep
def clear(self):
self._vertexCount = 0
self._edgeCount = 0
self._vertices = {}
def clearEdgeMarks(self):
for edge in self.edges():
edge.clearMark()
def clearVertexMarks(self):
for vertex in self.vertices():
vertex.clearMark()
def isEmpty(self):
return self._vertexCount == 0;
def sizeEdges(self):
return self._edgeCount
def sizeVertices(self):
return self._vertexCount
def __str__(self):
result = str(self.sizeVertices()) + " Vertices: "
for vertex in self._vertices:
result += " " + str(vertex)
result += "\n";
result += str(self.sizeEdges()) + " Edges: "
for edge in self.edges():
result += " " + str(edge)
return result
def addVertex(self, label):
self._vertices[label] = LinkedVertex(label)
self._vertexCount += 1
def containsVertex (self, label):
return label in self._vertices
def getVertex(self, label):
return self._vertices[label]
def removeVertex(self, label):
removedVertex = self._vertices.pop(label, None)
if removedVertex is None:
return False
# Examine all vertices
for vertex in self.vertices():
if vertex.removeEdgeTo(removedVertex):
self._edgeCount -= 1
self._vertexCount -= 1
return True
def addEdge(self, fromLabel, toLabel, weight):
fromVertex = self.getVertex(fromLabel)
toVertex = self.getVertex(toLabel)
fromVertex.addEdgeTo(toVertex, weight)
self._edgeCount += 1
def containsEdge(self, fromLabel, toLabel):
return self.getEdge(fromLabel, toLabel) != None
def getEdge(self, fromLabel, toLabel):
fromVertex = self._vertices[fromLabel]
toVertex = self._vertices[toLabel]
return fromVertex.getEdgeTo(toVertex)
def removeEdge (self, fromLabel, toLabel):
fromVertex = self.getVertex(fromLabel)
toVertex = self.getVertex(toLabel)
edgeRemovedFlg = fromVertex.removeEdgeTo(toVertex)
if edgeRemovedFlg:
self._edgeCount -= 1
return edgeRemovedFlg
# Iterators
def edges(self):
result = set()
for vertex in self.vertices():
edges = vertex.incidentEdges()
result = result.union(set(edges))
return iter(result)
def vertices(self):
return iter(self._vertices.values())
def incidentEdges(self, label):
return self._vertices[label].incidentEdges()
def neighboringVertices(self, label):
return self._vertices[label].neighboringVertices
g = LinkedDirectedGraph()
# Insert vertices
g.addVertex("John")
g.addVertex("Sam")
g.addVertex("Megan")
g.addVertex("Jennifer")
g.addVertex("Rick")
# Insert weighted edges
g.addEdge("John", "Sam", 3)
g.addEdge("John", "Megan", 2)
g.addEdge("Sam", "Jennifer", 1)
g.addEdge("Megan", "Jennifer", 1)
g.addEdge("Jennifer", "Rick", 2)
print(g)
If you override __eq__, then Python intentionally makes your class unhashable, since there is no longer a guarantee that the default hashing algorithm (based on the object's location in memory) is compatible with your __eq__ algorithm. "Compatible" here just means that equal objects must have equal hashes. By default, nothing is equal, so when you make some things equal using an __eq__ method, you impose a requirement on what a proper hash function must do.
If you want a custom class with a custom __eq__ method to be hashable, you must implement a __hash__ method yourself.
It could be as simple as being based on the hash of the corresponding tuple:
def __hash__(self):
return hash((type(self), self._vertex1, self._vertex2))
The Python docs explain this here.

newList = list - self

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.

How to check if one list is equal to another list created using a class?

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

'int' object has no attribute 'x'

I'm trying to make a program to add vectors using __add __:
class vects:
def __init__(self,x,y):
self.x = x
self.y = y
def __add__(self, vect):
total_x = self.x + vect.x
total_y = self.y + vect.y
return vects(total_x, total_y)
plusv1 = vects.__add__(2,5)
plusv2 = vects.__add__(1,7)
totalplus = plusv1 + plusv2
The error produced is as follows:
line 12, in <module> plusv1 = vects.__add__(2,5)
line 7, in __add__ total_x = self.x + vect.x
AttributeError: 'int' object has no attribute 'x'
You don't use __add__ like that! :-) __add__ will get implicitly invoked when + is used on an instance of the Vects class.
So, what you should first do is initialize two vector instances:
v1 = Vects(2, 5)
v2 = Vects(1, 7)
and then add them:
totalplus = v1 + v2
If you add a nice __str__ to get a nice representation of your new vector:
class Vects:
def __init__(self,x,y):
self.x = x
self.y = y
def __add__(self, vect):
total_x = self.x + vect.x
total_y = self.y + vect.y
return Vects(total_x, total_y)
def __str__(self):
return "Vector({}, {})".format(self.x, self.y)
You can get a view of totalplus by printing it:
print(totalplus)
Vector(3, 12)

Obtaining values from dictionary in OOP: "AttributeError"

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.

Categories