Say I have a Graph class and a Vertex class, defined as below
Graph.py
class Graph:
def __init__(self):
self.adjacencyList = {}
def __str__(self):
return str(self.adjacencyList)
def addVetex(self,key,value):
if Vertex(key,value) not in self.adjacencyList:
self.adjacencyList[Vertex(key,value)] = []
Vertex.py
class Vertex:
def __init__(self,key,value):
self.key = key
self.value = value
def __str__(self):
return "Key: ",str(self.key)," Value: ",str(self,value)
def __hash__(self):
return self.key
if I do this:
G = Graph()
G.addVetex(1,None)
G.addVetex(2,None)
G.addVetex(1,3)
print G
It print out {<Vertex.Vertex instance at 0x110295b90>: [], <Vertex.Vertex instance at 0x110295bd8>: []} But I am expecting something like {"Key:1 Value:None":[]...}
My question is what I am doing wrong? When a diction got print out, why it does not try to call the str function of its keys/values?
Thanks.
I believe the method you want to implement to get the string you want with your current code is Vertex.__repr__, which is what the python dictionary uses to get string representations of keys.
Here's a related stackoverflow answer that sheds some light on the difference between __repr__ and __str__
Joe's answer is correct, here is the tested version of the code:
def __repr__(self):
return "Key: "+str(self.key)+" Value: "+str(self.value)
to be implemented in Vertex. Also important is that a string is given back, not a tuple as in the question.
This will do it. Note the addition of the repr method (and a little cleanup of the str method).
class Vertex:
def __init__(self,key,value):
self.key = key
self.value = value
def __str__(self):
return "{Key: "+str(self.key)+" Value: "+str(self.value)+"}"
def __hash__(self):
return self.key
def __repr__(self):
return str(self)
You might consider subclassing a dict, though, for your vertex class. You get all the benefits of a dict but can add methods to suit your needs. The simplest version of this would look like:
class Vertex(dict):
pass
You can do smth like:
class Graph(object):
def __str__(self):
return ", ".join("Key: " + str(i.key) + " Value: " + str(i.value) for i in self.adjacencyList)
Related
I'm developing a program using Python 3.6
I have a problem: if I use the deterministic hash function (from standard library of the language) on the same object, the string that results in output (after a run), is different for some runs!
For example:
class Generic:
def __init__(self, id, name, property):
self.id = id
self.name = name
self.property = property
def main():
my_object = Generic(3,'ddkdjsdk','casualstring')
print(hash(my_object))
I would like the output to always be the same (deterministic), but unfortunately different strings appear on the console:
8765256330262, -9223363264515786864, -9223363262437648366 and others...
Why this happens? I would like to guarantee the determinism with this function throughout my application! How do I solve the problem?
In this case it's probably easiest to define your own __eq__ function and __hash__ function. This will return the same hash every time for you:
class Generic:
def __init__(self, id, name, property):
self.id=id
self.name = name
self.property = property
def __eq__(self, other):
assert self.__class__ == other.__class__, "Types do not match"
return self.id == other.id and self.name == other.name and self.property == other.property
def __hash__(self):
return hash ( (self.id, self.name, self.property) )
This will also make hashes of equivalent objects equal, as well:
>>>obj = Generic(1, 'blah', 'blah')
>>>obj2 = Generic(1, 'blah', 'blah')
>>>obj == obj2
True
>>>hash(obj) == hash(obj2)
True
hope that helps!
For those looking to get hashes of built-in types, Python's built in hashlib might be easier than subclassing to redefine __hash__. Here's an example with for string.
from hashlib import md5
def string_hash(string):
return md5(string.encode()).hexdigest()
This will return the same hash for different string objects so long as the content is the same. Not all objects will work, but it could you save you time depending on your use case.
we know that :
str.format('{:+>10}', 'sometext')
will return :
'++sometext'
or :
'{:+>10}'.format('sometext') will return '++sometext'
my question, is there away to override format method of instance of a class.... i have try this:
class A:
def __format__(self, spec):
return spec.format(self)
then instantiate it :
a = A()
a.__format__('{:+>20}')
returning '+>20' how could this happen...
thanks before
In def __format__(self,spec):, spec is the format string itself. If you want to format the class using that spec, you need to specify it as a format to the content of the class instance in some way, such as:
class Value:
def __init__(self,value):
self.value = value
def __format__(self,fmt): # fmt='03' from below.
return f'Value({self.value:{fmt}})' # f'Value({self.value:03})' is evaluated.
v = Value(5)
print(f'{v:03}') # Python 3.6+
print('{:04}'.format(v)) # Python <3.6
Output:
Value(005)
Value(0005)
You could create a class like this which takes in an initial int value as the length. I tested in Python 3 and this works.
class Padded:
def __init__(self, length: int=10, pad='+'):
self.value = '{{:{}>{}}}'.format(pad, length)
def format(self, value):
return self.value.__format__(value)
a=Padded(20)
print(a.__format__('Sometext'))
#++++++++++++Sometext
Can override format this way (refered from python cookbook)
_formats = {
'ymd' : '{d.year}-{d.month}-{d.day}',
'mdy' : '{d.month}-{d.day}-{d.year}'
}
class Date:
def __init__(self,year,month,day):
self.year = year
self.month = month
self.day = day
def __format__(self,code):
fmt = _formats[code]
return fmt.format(d=self) #passed self as instance to d (Note using this d in _formats to get the attribute)
d = Date(2021,8,23)
#format method can be called from either these 2 ways
print(d.__format__('ymd'))
print(format(d,'mdy'))
#output
2021-8-23
8-23-2021
I am new to python and trying to implement graph data structure in Python.
I have written this code, but i am not getting the desired result i want.
Code:
class NODE:
def __init__(self):
self.distance=0
self.colournode="White"
adjlist={}
def addno(A,B):
global adjlist
adjlist[A]=B
S=NODE()
R=NODE()
V=NODE()
W=NODE()
T=NODE()
X=NODE()
U=NODE()
Y=NODE()
addno(S,R)
for keys in adjlist:
print keys
I want the code to print {'S':R} on the final line but it is printing this:
<__main__.NODE instance at 0x00000000029E6888>
Can anybody guide me what am i doing wrong? Also what to do if i want to add another function call like addnode(S,E) and printing should be {S:[R,E]}
You node needs to have a label to print. You can't use just the variable name. The node has no way knowing name of your variable.
class NODE:
def __init__(self, name):
self.name=name
def __repr__(self):
return self.name
adjlist={}
def addno(A,B):
global adjlist
adjlist[A]=B
S=NODE('S')
R=NODE('R')
addno(S,R)
print adjlist
>>> {S: R}
However python dict may have only one value for each key, so you wont be able to save {S: R} and {S: V} at the same time. Instead you will need to save aj array of nodes:
class NODE:
def __init__(self, name):
self.name=name
def __repr__(self):
return self.name
adjlist={}
def addno(A,B):
global adjlist
if A not in adjlist:
adjlist[A] = []
adjlist[A].append(B)
S=NODE('S')
R=NODE('R')
V=NODE('V')
W=NODE('W')
addno(S,R)
addno(S,V)
addno(R,W)
print adjlist
{S: [R, V], R: [W]}
As a side note, using unnessesary global variables is a bad habit. Instead make a class for the graph:
class Node:
def __init__(self, name):
self.name=name
def __repr__(self):
return self.name
class Graph:
def __init__(self):
self.adjlist={}
def addno(self, a, b):
if a not in self.adjlist:
self.adjlist[a] = []
self.adjlist[a].append(b)
def __repr__(self):
return str(self.adjlist)
G=Graph()
S=Node('S')
R=Node('R')
V=Node('V')
W=Node('W')
G.addno(S,R)
G.addno(S,V)
G.addno(R,W)
print G
>>> {R: [W], S: [R, V]}
You get that output because Node is an instance of a class ( you get that hint form the output of your program itself see this: <main.NODE instance at 0x00000000029E6888> ).
i think you are trying to implement adjacency list for some graph algorithm. in those cases you will mostly need the color and ``distanceto othernodes`. which you can get by doing :
for keys in adjlist:
print keys.colournode , keys.distance
New to python and this might be a silly question, but how does one properly implement the repr method?
I wrote a quick little program to simulate a game of cards but I don't know what to write for the repr method. The repr method for the Card class was pretty straight forward, but I don't know what to do for the DeckOfCards class Here's my code:
import random
class Card:
'''Create a single card, by id number'''
# Class variables, created once for the class
suits = [ '\u2660', '\u2661', '\u2662', '\u2663' ]
ranks = [ 'A','2','3','4','5','6','7','8','9','10','J','Q','K' ]
def __init__(self, n=0):
# instance variables for _num, _rank, _suit, _value
if 0 <= n < 52:
self._num = n
self._rank = Card.ranks[n%13] # note referencing class vars
self._suit = Card.suits[n//13]
self._value = n%13 + 1
if self._rank == 'A':
self._value = 14
else: # invalid card indicators
self._rank = 'x'
self._suit = 'x'
self._value = -1
def __repr__(self):
return self._rank + self._suit
def __lt__(self,other):
return self._value < other._value
def __le__(self,other):
return self._value <= other._value
def __eq__(self,other):
return self._value == other._value
class DeckOfCards:
'''A Deck is a collection of cards'''
def __init__(self):
self._deck = [ Card(i) for i in range(52) ]
def __repr__(self):
return 'Deck : ', self._deck
def shuffle(self):
return random.shuffle(self._deck)
def deal_a_card(self, i=-1):
#that way player can choose where to draw from
return self._deck.pop(i)
def cards_left(self,count):
return len(self._deck)
new_deck = DeckOfCards()
Also, feel free to comment on anything you'd like, whether it be a design flaw or redundancy in code, literally anything. Thanks in advance!
You should return a string type, for example in Deck:
def __repr__(self):
...
return 'Deck : '+str(self._deck)
__repr__ ideally could return the representation of the object that you would use to create this instance.
From repr():
For many types, this function makes an attempt to return a string that would yield an object with the same value when passed to eval(), otherwise the representation is a string enclosed in angle brackets that contains the name of the type of the object together with additional information often including the name and address of the object.
First, It should be noted that you don't have to implement the __repr__ method. Python provides a somewhat reasonable default (it'll at least tell you the type).
If you want to implement __repr__, the "rule of thumb" is that where it makes sense, you should provide enough information about the object that a user could reconstruct it. In your case, there doesn't seem to be any real difference from one deck to another, so
def __repr__(self):
return 'Deck()'
might be a reasonable return value. This doesn't get the state right (after shuffling), but you don't provide an interface for constructing a deck in a particular state. If you did, it might look like:
def __repr__(self):
return 'Deck(%s)' % self._deck
This is some code I found on the internet. I'm not sure how it is meant to be used. I simply filled members with the enum keys/values and it works, but I'm curious what this metaclass is all about. I am assuming it has something to do with ctypes, but I can't find much information on subclassing ctypes. I know EnumerationType isn't doing anything the way I'm using Enumeration.
from ctypes import *
class EnumerationType(type(c_uint)):
def __new__(metacls, name, bases, dict):
if not "_members_" in dict:
_members_ = {}
for key,value in dict.items():
if not key.startswith("_"):
_members_[key] = value
dict["_members_"] = _members_
cls = type(c_uint).__new__(metacls, name, bases, dict)
for key,value in cls._members_.items():
globals()[key] = value
return cls
def __contains__(self, value):
return value in self._members_.values()
def __repr__(self):
return "<Enumeration %s>" % self.__name__
class Enumeration(c_uint):
__metaclass__ = EnumerationType
_members_ = {}
def __init__(self, value):
for k,v in self._members_.items():
if v == value:
self.name = k
break
else:
raise ValueError("No enumeration member with value %r" % value)
c_uint.__init__(self, value)
#classmethod
def from_param(cls, param):
if isinstance(param, Enumeration):
if param.__class__ != cls:
raise ValueError("Cannot mix enumeration members")
else:
return param
else:
return cls(param)
def __repr__(self):
return "<member %s=%d of %r>" % (self.name, self.value, self.__class__)
And an enumeration probably done the wrong way.
class TOKEN(Enumeration):
_members_ = {'T_UNDEF':0, 'T_NAME':1, 'T_NUMBER':2, 'T_STRING':3, 'T_OPERATOR':4, 'T_VARIABLE':5, 'T_FUNCTION':6}
A metaclass is a class used to create classes. Think of it this way: all objects have a class, a class is also an object, therefore, it makes sense that a class can have a class.
http://www.ibm.com/developerworks/linux/library/l-pymeta.html
To understand what this is doing, you can look at a few points in the code.
_members_ = {'T_UNDEF':0, 'T_NAME':1, 'T_NUMBER':2, 'T_STRING':3, 'T_OPERATOR':4, 'T_VARIABLE':5, 'T_FUNCTION':6}
globals()[key] = value
Here it takes every defined key in your dictionary: "T_UNDEF" "T_NUMBER" and makes them available in your globals dictionary.
def __init__(self, value):
for k,v in self._members_.items():
if v == value:
self.name = k
break
Whenever you make an instance of your enum, it will check to see if the "value" is in your list of allowable enum names when you initialized the class. When the value is found, it sets the string name to self.name.
c_uint.__init__(self, value)
This is the actual line which sets the "ctypes value" to an actual c unsigned integer.
That is indeed a weird class.
The way you are using it is correct, although another way would be:
class TOKEN(Enumeration):
T_UNDEF = 0
T_NAME = 1
T_NUMBER = 2
T_STRING = 3
T_OPERATOR = 4
T_VARIABLE = 5
T_FUNCTION = 6
(That's what the first 6 lines in __new__ are for)
Then you can use it like so:
>>> TOKEN
<Enumeration TOKEN>
>>> TOKEN(T_NAME)
<member T_NAME=1 of <Enumeration TOKEN>>
>>> T_NAME in TOKEN
True
>>> TOKEN(1).name
'T_NAME'
The from_param method seems to be for convenience, for writing methods that accept either an int or an Enumeration object. Not really sure if that's really its purpose.
I think this class is meant to be used when working with external APIs the use c-style enums, but it looks like a whole lot of work for very little gain.