Getting memory location instead of value - python

I have a node class which has a "symbol" attribute, which is a string. I pass this value into a method which eventually saves it as the key in a dictionary, but otherwise does not access the value until then.
after accessing node.symbol, I print the value
trans char: '1'
I then pass it into another function as the only parameter. In that method, I immediately print the symbol using:
print(symbol)
But it prints:
<pa3.RegEx object at 0x000001D2EFDC4640>
I would like to access the value which should be a string "1" instead of this memory location.
I know this has probably been asked many times before, but I don't know what to call this problem
class node:
def __init__(self,data):
self.left = None
self.right = None
self.symbol = None #will be a ch in alphabet, (), ~, *, or |
self.data = data
def get_symbol(self):
return self.symbol`
class RegEX
def Convert(self, nod, NFA_stack):
trans_char = node.get_symbol(nod)
print("type:", type(trans_char))
print("trans char:", trans_char, "\n")
if nod.left == None and nod.right == None:
print("passing trans_char into method")
NFA = self.Generate_NFA(trans_char)
NFA_stack.append(NFA)
def Generate_NFA(symbol, leftNFA = None, rightNFA = None): #NFA's are dictionaries, symbol is | or ~
print("in new method")
print("symbol: ", symbol)
In this method, trans_char is recognized as a string with a value of '1', but after passing trans_char into that other method, it becomes some memory address of the class. The problem is that I need to use this as a value in a dictionary, not just print it.

The first argument in method is reserved for the class object itself, so Generate_NFA(symbol,...) makes Python think that symbol is the object of the RegEx class that the method is called for it.
Editing your function definition to the below should fix the problem:
def Generate_NFA(self, symbol, leftNFA = None, rightNFA = None):

Related

Python object as property type

I'm searching for an elegant way to replace setter/getter methodes handling complex data types by properties using the #property decorator.
The class I'm working on should represent some kind of (network) dimmer. It is possible to request/send "resources" addressed by a specific ID to control the device. I'd like to represent those "resources" as properties of my class hiding the request/send mechanism and the cryptical ID numbers.
Some of those "resources" are just primitive types (int, float, ...) but some are more complex, so I've just created simple classes for them.
This works fine, but there is an ugly source of error: It is not possible to change an attribute of that property directly, I have to set the property completely everytime.
DUMMY_DB = {0x0001: bytearray([0x00])}
class State:
def __init__(self, on, value):
self.on = on
self.value = value
#staticmethod
def from_int(val):
return State(bool(val & 0x80), val & 0x7f)
def __int__(self):
return self.on << 7 | self.value
class Dimmer:
#property
def state(self) -> State:
return State.from_int(self._request(0x0001)[0]) # ID 0x0001 => State
#state.setter
def state(self, val: State):
self._send(0x0001, [int(val)]) # ID 0x0001 => State
# several more properties...
def _request(self, ident) -> bytearray:
# usually get resource 'ident' from network/file/...
return DUMMY_DB[ident]
def _send(self, ident, value):
# usually set resource 'ident' on network/file/... using value
DUMMY_DB[ident] = value
if __name__ == '__main__':
dimmer = Dimmer()
print(dimmer.state.on, dimmer.state.value) # start state
dimmer.state.on = True
dimmer.state.value = 15
print(dimmer.state.on, dimmer.state.value) # state did not change
dimmer.state = State(True, 15)
print(dimmer.state.on, dimmer.state.value) # state changed
The first print is just to show the start state ("False 0"). But the second print shows that
dimmer.state.on = True
dimmer.state.value = 15
are useless. This is because dimmer.state returns a new mutable object which is modified and destroyed without further usage. Only through the complete property assignment the setter methode is called and Dimmer._send invoked.
I think this might be extremely unintuitive and error-prone. Do you have any suggestions for a better design?

Why does this print the memory location of an object rather than what I want?

I'm not sure what's happening when I print my dictionary.
In Python 3, I have a dictionary of parse_blast objects called transSwiss. Each object's proteinID is the key with the entire object as the value.
I can print transSwiss in it's entirety and I can also print blasto.protein, but not when I combine them to get a dictionary value. I'm not sure what is happening when I use:
print(transSwiss[blasto.protein])
<__main__.parse_blast object at 0x000000373C5666A0>
Here is the code
class parse_blast(object):
def __init__(self, line):
#Strip end-of-line and split on tabs
self.fields = line.strip("\n").split("\t")
self.transcriptId, self.isoform = self.fields[0].split("|")
self.swissStuff = self.fields[1].split("|")
self.swissProtId = self.swissStuff[3]
self.percentId = self.fields[2]
def filterblast(self):
return float(self.percentId) > 95
class parse_matrix(object):
#Consider __init__ as a Constructor
def __init__(self, matrix_lines):
(self.protein,
self.Sp_ds,
self.Sp_hs,
self.Sp_log,
self.Sp_plat) = matrix_lines.strip("\n").split("\t")
def separate_tuples(one_tuple):
return "\t".join(one_tuple)
blastmap = map(parse_blast, blast_output.readlines())
filtered = filter(parse_blast.filterblast, blastmap)
matrixmap = map(parse_matrix, matrix_output.readlines()[1:])
transSwiss = {blasto.transcriptId:blasto for blasto in filtered}
for matrixo in matrixmap:
print(transSwiss[matrixo.protein])
Because your object is defined by you, you also need to tell python how you want it to print. You can do this by defining a function called "__str__" that returns how you want to print your object.
https://en.wikibooks.org/wiki/Python_Programming/Classes#str

Python recursive setattr()-like function for working with nested dictionaries [duplicate]

This question already has answers here:
Is it possible to index nested lists using tuples in python?
(7 answers)
Closed 7 months ago.
There are a lot of good getattr()-like functions for parsing nested dictionary structures, such as:
Finding a key recursively in a dictionary
Suppose I have a python dictionary , many nests
https://gist.github.com/mittenchops/5664038
I would like to make a parallel setattr(). Essentially, given:
cmd = 'f[0].a'
val = 'whatever'
x = {"a":"stuff"}
I'd like to produce a function such that I can assign:
x['f'][0]['a'] = val
More or less, this would work the same way as:
setattr(x,'f[0].a',val)
to yield:
>>> x
{"a":"stuff","f":[{"a":"whatever"}]}
I'm currently calling it setByDot():
setByDot(x,'f[0].a',val)
One problem with this is that if a key in the middle doesn't exist, you need to check for and make an intermediate key if it doesn't exist---ie, for the above:
>>> x = {"a":"stuff"}
>>> x['f'][0]['a'] = val
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'f'
So, you first have to make:
>>> x['f']=[{}]
>>> x
{'a': 'stuff', 'f': [{}]}
>>> x['f'][0]['a']=val
>>> x
{'a': 'stuff', 'f': [{'a': 'whatever'}]}
Another is that keying for when the next item is a lists will be different than the keying when the next item is a string, ie:
>>> x = {"a":"stuff"}
>>> x['f']=['']
>>> x['f'][0]['a']=val
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
...fails because the assignment was for a null string instead of a null dict. The null dict will be the right assignment for every non-list in dict until the very last one---which may be a list, or a value.
A second problem, pointed out in the comments below by #TokenMacGuy, is that when you have to create a list that does not exist, you may have to create an awful lot of blank values. So,
setattr(x,'f[10].a',val)
---may mean the algorithm will have to make an intermediate like:
>>> x['f']=[{},{},{},{},{},{},{},{},{},{},{}]
>>> x['f'][10]['a']=val
to yield
>>> x
{"a":"stuff","f":[{},{},{},{},{},{},{},{},{},{},{"a":"whatever"}]}
such that this is the setter associated with the getter...
>>> getByDot(x,"f[10].a")
"whatever"
More importantly, the intermediates should /not/ overwrite values that already exist.
Below is the junky idea I have so far---I can identify the lists versus dicts and other data types, and create them where they do not exist. However, I don't see (a) where to put the recursive call, or (b) how to 'build' the deep object as I iterate through the list, and (c) how to distinguish the /probing/ I'm doing as I construct the deep object from the /setting/ I have to do when I reach the end of the stack.
def setByDot(obj,ref,newval):
ref = ref.replace("[",".[")
cmd = ref.split('.')
numkeys = len(cmd)
count = 0
for c in cmd:
count = count+1
while count < numkeys:
if c.find("["):
idstart = c.find("[")
numend = c.find("]")
try:
deep = obj[int(idstart+1:numend-1)]
except:
obj[int(idstart+1:numend-1)] = []
deep = obj[int(idstart+1:numend-1)]
else:
try:
deep = obj[c]
except:
if obj[c] isinstance(dict):
obj[c] = {}
else:
obj[c] = ''
deep = obj[c]
setByDot(deep,c,newval)
This seems very tricky because you kind of have to look-ahead to check the type of the /next/ object if you're making place-holders, and you have to look-behind to build a path up as you go.
UPDATE
I recently had this question answered, too, which might be relevant or helpful.
I have separated this out into two steps. In the first step, the query string is broken down into a series of instructions. This way the problem is decoupled, we can view the instructions before running them, and there is no need for recursive calls.
def build_instructions(obj, q):
"""
Breaks down a query string into a series of actionable instructions.
Each instruction is a (_type, arg) tuple.
arg -- The key used for the __getitem__ or __setitem__ call on
the current object.
_type -- Used to determine the data type for the value of
obj.__getitem__(arg)
If a key/index is missing, _type is used to initialize an empty value.
In this way _type provides the ability to
"""
arg = []
_type = None
instructions = []
for i, ch in enumerate(q):
if ch == "[":
# Begin list query
if _type is not None:
arg = "".join(arg)
if _type == list and arg.isalpha():
_type = dict
instructions.append((_type, arg))
_type, arg = None, []
_type = list
elif ch == ".":
# Begin dict query
if _type is not None:
arg = "".join(arg)
if _type == list and arg.isalpha():
_type = dict
instructions.append((_type, arg))
_type, arg = None, []
_type = dict
elif ch.isalnum():
if i == 0:
# Query begins with alphanum, assume dict access
_type = type(obj)
# Fill out args
arg.append(ch)
else:
TypeError("Unrecognized character: {}".format(ch))
if _type is not None:
# Finish up last query
instructions.append((_type, "".join(arg)))
return instructions
For your example
>>> x = {"a": "stuff"}
>>> print(build_instructions(x, "f[0].a"))
[(<type 'dict'>, 'f'), (<type 'list'>, '0'), (<type 'dict'>, 'a')]
The expected return value is simply the _type (first item) of the next tuple in the instructions. This is very important because it allows us to correctly initialize/reconstruct missing keys.
This means that our first instruction operates on a dict, either sets or gets the key 'f', and is expected to return a list. Similarly, our second instruction operates on a list, either sets or gets the index 0 and is expected to return a dict.
Now let's create our _setattr function. This gets the proper instructions and goes through them, creating key-value pairs as necessary. Finally, it also sets the val we give it.
def _setattr(obj, query, val):
"""
This is a special setattr function that will take in a string query,
interpret it, add the appropriate data structure to obj, and set val.
We only define two actions that are available in our query string:
.x -- dict.__setitem__(x, ...)
[x] -- list.__setitem__(x, ...) OR dict.__setitem__(x, ...)
the calling context determines how this is interpreted.
"""
instructions = build_instructions(obj, query)
for i, (_, arg) in enumerate(instructions[:-1]):
_type = instructions[i + 1][0]
obj = _set(obj, _type, arg)
_type, arg = instructions[-1]
_set(obj, _type, arg, val)
def _set(obj, _type, arg, val=None):
"""
Helper function for calling obj.__setitem__(arg, val or _type()).
"""
if val is not None:
# Time to set our value
_type = type(val)
if isinstance(obj, dict):
if arg not in obj:
# If key isn't in obj, initialize it with _type()
# or set it with val
obj[arg] = (_type() if val is None else val)
obj = obj[arg]
elif isinstance(obj, list):
n = len(obj)
arg = int(arg)
if n > arg:
obj[arg] = (_type() if val is None else val)
else:
# Need to amplify our list, initialize empty values with _type()
obj.extend([_type() for x in range(arg - n + 1)])
obj = obj[arg]
return obj
And just because we can, here's a _getattr function.
def _getattr(obj, query):
"""
Very similar to _setattr. Instead of setting attributes they will be
returned. As expected, an error will be raised if a __getitem__ call
fails.
"""
instructions = build_instructions(obj, query)
for i, (_, arg) in enumerate(instructions[:-1]):
_type = instructions[i + 1][0]
obj = _get(obj, _type, arg)
_type, arg = instructions[-1]
return _get(obj, _type, arg)
def _get(obj, _type, arg):
"""
Helper function for calling obj.__getitem__(arg).
"""
if isinstance(obj, dict):
obj = obj[arg]
elif isinstance(obj, list):
arg = int(arg)
obj = obj[arg]
return obj
In action:
>>> x = {"a": "stuff"}
>>> _setattr(x, "f[0].a", "test")
>>> print x
{'a': 'stuff', 'f': [{'a': 'test'}]}
>>> print _getattr(x, "f[0].a")
"test"
>>> x = ["one", "two"]
>>> _setattr(x, "3[0].a", "test")
>>> print x
['one', 'two', [], [{'a': 'test'}]]
>>> print _getattr(x, "3[0].a")
"test"
Now for some cool stuff. Unlike python, our _setattr function can set unhashable dict keys.
x = []
_setattr(x, "1.4", "asdf")
print x
[{}, {'4': 'asdf'}] # A list, which isn't hashable
>>> y = {"a": "stuff"}
>>> _setattr(y, "f[1.4]", "test") # We're indexing f with 1.4, which is a list!
>>> print y
{'a': 'stuff', 'f': [{}, {'4': 'test'}]}
>>> print _getattr(y, "f[1.4]") # Works for _getattr too
"test"
We aren't really using unhashable dict keys, but it looks like we are in our query language so who cares, right!
Finally, you can run multiple _setattr calls on the same object, just give it a try yourself.
>>> class D(dict):
... def __missing__(self, k):
... ret = self[k] = D()
... return ret
...
>>> x=D()
>>> x['f'][0]['a'] = 'whatever'
>>> x
{'f': {0: {'a': 'whatever'}}}
You can hack something together by fixing two problems:
List that automatically grows when accessed out of bounds (PaddedList)
A way to delay the decision of what to create (list of dict) until you accessed it by the first time (DictOrList)
So the code will look like this:
import collections
class PaddedList(list):
""" List that grows automatically up to the max index ever passed"""
def __init__(self, padding):
self.padding = padding
def __getitem__(self, key):
if isinstance(key, int) and len(self) <= key:
self.extend(self.padding() for i in xrange(key + 1 - len(self)))
return super(PaddedList, self).__getitem__(key)
class DictOrList(object):
""" Object proxy that delays the decision of being a List or Dict """
def __init__(self, parent):
self.parent = parent
def __getitem__(self, key):
# Type of the structure depends on the type of the key
if isinstance(key, int):
obj = PaddedList(MyDict)
else:
obj = MyDict()
# Update parent references with the selected object
parent_seq = (self.parent if isinstance(self.parent, dict)
else xrange(len(self.parent)))
for i in parent_seq:
if self == parent_seq[i]:
parent_seq[i] = obj
break
return obj[key]
class MyDict(collections.defaultdict):
def __missing__(self, key):
ret = self[key] = DictOrList(self)
return ret
def pprint_mydict(d):
""" Helper to print MyDict as dicts """
print d.__str__().replace('defaultdict(None, {', '{').replace('})', '}')
x = MyDict()
x['f'][0]['a'] = 'whatever'
y = MyDict()
y['f'][10]['a'] = 'whatever'
pprint_mydict(x)
pprint_mydict(y)
And the output of x and y will be:
{'f': [{'a': 'whatever'}]}
{'f': [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {'a': 'whatever'}]}
The trick consist on creating a defaultdict of objects that can be either a dict or a list depending how you access it.
So when you have the assigment x['f'][10]['a'] = 'whatever' it will work the following way:
Get X['f']. It wont exist so it will return a DictOrList object for the index 'f'
Get X['f'][10]. DictOrList.getitem will be called with an integer index. The DictOrList object will replace itself in the parent collection by a PaddedList
Access the 11th element in the PaddedList will grow it by 11 elements and will return the MyDict element in that position
Assign "whatever" to x['f'][10]['a']
Both PaddedList and DictOrList are bit hacky, but after all the assignments there is no more magic, you have an structure of dicts and lists.
It is possible to synthesize recursively setting items/attributes by overriding __getitem__ to return a return a proxy that can set a value in the original function.
I happen to be working on a library that does a few things similar to this, so I was working on a class that can dynamically assign its own subclasses at instantiation. It makes working with this sort of thing easier, but if that kind of hacking makes you squeamish, you can get similar behavior by creating a ProxyObject similar to the one I create and by creating the individual classes used by the ProxyObject dynamically in the a function. Something like
class ProxyObject(object):
... #see below
def instanciateProxyObjcet(val):
class ProxyClassForVal(ProxyObject,val.__class__):
pass
return ProxyClassForVal(val)
You can use dictionary like I've used in FlexibleObject below would make that implementation significantly more efficient if this is the way you implement it. The code I will providing uses the FlexibleObject though. Right now it only supports classes that, like almost all of Python's builtin classes are capable of being generated by taking an instance of themselves as their sole argument to their __init__/__new__. In the next week or two, I'll add support for anything pickleable, and link to a github repository that contains it. Here's the code:
class FlexibleObject(object):
""" A FlexibleObject is a baseclass for allowing type to be declared
at instantiation rather than in the declaration of the class.
Usage:
class DoubleAppender(FlexibleObject):
def append(self,x):
super(self.__class__,self).append(x)
super(self.__class__,self).append(x)
instance1 = DoubleAppender(list)
instance2 = DoubleAppender(bytearray)
"""
classes = {}
def __new__(cls,supercls,*args,**kws):
if isinstance(supercls,type):
supercls = (supercls,)
else:
supercls = tuple(supercls)
if (cls,supercls) in FlexibleObject.classes:
return FlexibleObject.classes[(cls,supercls)](*args,**kws)
superclsnames = tuple([c.__name__ for c in supercls])
name = '%s%s' % (cls.__name__,superclsnames)
d = dict(cls.__dict__)
d['__class__'] = cls
if cls == FlexibleObject:
d.pop('__new__')
try:
d.pop('__weakref__')
except:
pass
d['__dict__'] = {}
newcls = type(name,supercls,d)
FlexibleObject.classes[(cls,supercls)] = newcls
return newcls(*args,**kws)
Then to use this to use this to synthesize looking up attributes and items of a dictionary-like object you can do something like this:
class ProxyObject(FlexibleObject):
#classmethod
def new(cls,obj,quickrecdict,path,attribute_marker):
self = ProxyObject(obj.__class__,obj)
self.__dict__['reference'] = quickrecdict
self.__dict__['path'] = path
self.__dict__['attr_mark'] = attribute_marker
return self
def __getitem__(self,item):
path = self.__dict__['path'] + [item]
ref = self.__dict__['reference']
return ref[tuple(path)]
def __setitem__(self,item,val):
path = self.__dict__['path'] + [item]
ref = self.__dict__['reference']
ref.dict[tuple(path)] = ProxyObject.new(val,ref,
path,self.__dict__['attr_mark'])
def __getattribute__(self,attr):
if attr == '__dict__':
return object.__getattribute__(self,'__dict__')
path = self.__dict__['path'] + [self.__dict__['attr_mark'],attr]
ref = self.__dict__['reference']
return ref[tuple(path)]
def __setattr__(self,attr,val):
path = self.__dict__['path'] + [self.__dict__['attr_mark'],attr]
ref = self.__dict__['reference']
ref.dict[tuple(path)] = ProxyObject.new(val,ref,
path,self.__dict__['attr_mark'])
class UniqueValue(object):
pass
class QuickRecursiveDict(object):
def __init__(self,dictionary={}):
self.dict = dictionary
self.internal_id = UniqueValue()
self.attr_marker = UniqueValue()
def __getitem__(self,item):
if item in self.dict:
val = self.dict[item]
try:
if val.__dict__['path'][0] == self.internal_id:
return val
else:
raise TypeError
except:
return ProxyObject.new(val,self,[self.internal_id,item],
self.attr_marker)
try:
if item[0] == self.internal_id:
return ProxyObject.new(KeyError(),self,list(item),
self.attr_marker)
except TypeError:
pass #Item isn't iterable
return ProxyObject.new(KeyError(),self,[self.internal_id,item],
self.attr_marker)
def __setitem__(self,item,val):
self.dict[item] = val
The particulars of the implementation will vary depending on what you want. It's obviously significantly easier to just override __getitem__ in the proxy than it is to override both __getitem__ and __getattribute__ or __getattr__. The syntax you are using in setbydot makes it look like you would be happiest with some solution that overrides a mixture of the two.
If you are just using the dictionary to compare values, using =,<=,>= etc. Overriding __getattribute__ works really nicely. If you are wanting to do something more sophisticated, you will probably be better off overriding __getattr__ and doing some checks in __setattr__ to determine whether you want to be synthesizing setting the attribute by setting a value in the dictionary or whether you want to be actually setting the attribute on the item you've obtained. Or you might want to handle it so that if your object has an attribute, __getattribute__ returns a proxy to that attribute and __setattr__ always just sets the attribute in the object (in which case, you can completely omit it). All of these things depend on exactly what you are trying to use the dictionary for.
You also may want to create __iter__ and the like. It takes a little bit of effort to make them, but the details should follow from the implementation of __getitem__ and __setitem__.
Finally, I'm going to briefly summarize the behavior of the QuickRecursiveDict in case it's not immediately clear from inspection. The try/excepts are just shorthand for checking to see whether the ifs can be performed. The one major defect of synthesizing the recursive setting rather than find a way to do it is that you can no longer be raising KeyErrors when you try to access a key that hasn't been set. However, you can come pretty close by returning a subclass of KeyError which is what I do in the example. I haven't tested it so I won't add it to the code, but you may want to pass in some human-readable representation of the key to KeyError.
But aside from all that it works rather nicely.
>>> qrd = QuickRecursiveDict
>>> qrd[0][13] # returns an instance of a subclass of KeyError
>>> qrd[0][13] = 9
>>> qrd[0][13] # 9
>>> qrd[0][13]['forever'] = 'young'
>>> qrd[0][13] # 9
>>> qrd[0][13]['forever'] # 'young'
>>> qrd[0] # returns an instance of a subclass of KeyError
>>> qrd[0] = 0
>>> qrd[0] # 0
>>> qrd[0][13]['forever'] # 'young'
One more caveat, the things being returned is not quite what it looks like. It's a proxy to what it looks like. If you want the int 9, you need int(qrd[0][13]) not qrd[0][13]. For ints this doesn't matter much since, +,-,= and all that bypass __getattribute__ but for lists, you would lose attributes like append if you didn't recast them. (You'd keep len and other builtin methods, just not attributes of list. You lose __len__.)
So that's it. The code's a little bit convoluted, so let me know if you have any questions. I probably can't answer them until tonight unless the answer's really brief. I wish I saw this question sooner, it's a really cool question, and I'll try to update a cleaner solution soon. I had fun trying to code a solution into the wee hours of last night. :)

Printing individual list objects within __str__ using .format(**self.__dict__)

I'm printing a stat block for a game character object. In a previous question I was demonstrated a way to display the object data using in the __str__ function like so:
def __str__(self):
if self.poisoned is True:
status = "[POISONED]"
else:
status = ""
self.status = status
return ('NAME: {name} {status}\n' \
'XP: {xp}\n' \
'HP: {hit_points}\n' \
'SP: {spell_points}\n' \
'STR: {strength}\n' \
'DEX: {dexterity}\n' \
'WEAPON: {weapon}\n' \
'SPELL: {spell}\n' \
'ITEM: {item}\n' \
'AURA: {aura}\n' \
).format(**self.__dict__)
The problem I want to solve has to do with the WEAPON, SPELL, ITEM and AURA variables. These items are defined in the Character object as single item lists: weapon=[] and so on. Using the above method returns the list object instead of the object it contains without the []. I'd rater see a blank " " string or the list's contained object if one exists and not [].
NAME: Bones
XP: 0
HP: 100
SP: 100
STR: 14
DEX: 19
WEAPON: []
SPELL: []
ITEM: []
AURA: []
I've tried a number of experiments including replacing the {weapon} reference with {current_weapon} after defining current_weapon = weapon[0] which won't work if the list object is empty. That just errors with IndexError: list index out of range. I could generate the items at object instantiation, but that won't work as self.item will at times be an empty list container.
I could propagate the lists with " " objects but would then have to juggle them out with replacement items and keep track of this which seems very inelegant and potentially cumbersome.
I just can't seem to wrap my head around an elegant way to print the list object in the above __str__ return as currently designed. I'm still learning Python and want to believe there is a simple addition I could append to this return string to do this.
Another option is to use the power of string formatting to check attributes of what it's passed in, and the fact that self is a local variable within the method:
def __str__(self):
status = '[POISONED]' if self.poisoned else ''
weapon = self.weapon[0] if self.weapon else ''
spell = self.spell[0] if self.spell else ''
item = self.item[0] if self.item else ''
aura = self.aura[0] if self.aura else ''
return ('NAME: {self.name} {status}\n'
'XP: {self.xp}\n'
'HP: {self.hit_points}\n'
'SP: {self.spell_points}\n'
'STR: {self.strength}\n'
'DEX: {self.dexterity}\n'
'WEAPON: {weapon}\n'
'SPELL: {spell}\n'
'ITEM: {item}\n'
'AURA: {aura}\n'
).format(**locals())
You could just create a local copy of your dict, and modify the values you want, before passing that on to the format:
def __str__(self):
local_data = self.__dict__.copy()
local_data['status'] = "[POISONED]" if self.poisoned else ""
local_data['weapon'] = " " if not self.weapon else ','.join(self.weapon)
return ('NAME: {name} {status}\n' \
'XP: {xp}\n' \
'HP: {hit_points}\n' \
'SP: {spell_points}\n' \
'STR: {strength}\n' \
'DEX: {dexterity}\n' \
'WEAPON: {weapon}\n' \
'SPELL: {spell}\n' \
'ITEM: {item}\n' \
'AURA: {aura}\n' \
).format(**local_data)
It is probably better to do that, than to modify your attributes simple for the formatting, like you were doing with your self.status. Now you are just modifying temp copies.
You can do it in a simple way, even if not so trivial. You can modify the string format to take the whole object and harness the power of the properties.This has the advantage of not creating a copy of your dictionary, that can be expensive for big object.
I'll give you an example that should be close to what you need:
class A(object):
def __init__(self):
# one full list and one empty one
self.c = [1,2,3]
self.d = []
#these two preperties create a string versione when requeste
c_str = property(lambda self: ", ".join(str(i) for i in self.c))
d_str = property(lambda self: ", ".join(str(i) for i in self.d))
def __str__(self):
#you have to use the dotted version because properties are not visibles
# from the dict attribute
string = "c = {0.c_str} \nd = {0.d_str}"
return string.format(self)
a = A()
print str(a)
# c = 1, 2, 3
# d =
If you are programming some kind of game properties can be a huge lifesavers, as you can use them to obtain complicated values as attribute instead of functions, creating a lot more cleaner code. They allow you to implement even check for the insertion of value, for examples that a value is positive.
EDIT:
Why I am using the 0.c_str instead of c_str? it is because the properties are special objects that will be called only if you access them with the dot notation (self.c_str). They do not exist in the objects __dict__ so you can't use it. If you try to print the __dict__ you will see only the values c and d.
That's why I passed to the format function the whole object and accessed its attributes instead of passing it the object dictionary.
If you don't like the 0.c_str notation you can escape it differently, for example keeping it close to the usual notation:
"{self.c_str}".format(self=self)
or
"{foo.c_str}".format(foo=self)

Special Python dict with object IDs

I want to create a special dictionary which uses object IDs as keys, like this:
class ObjectIdDict(dict):
def __setitem__(self, key, value):
super(ObjectIdDict, self).__setitem__(id(key), value)
def __getitem__(self, key):
super(ObjectIdDict, self).__getitem__(id(key))
But if I run the following test, I get an error:
class ObjectIdDictTest(unittest.TestCase):
def test_get_and_set(self):
dict_to_test = ObjectIdDict()
class Something:
def __init__(self):
self.x = 1
s = Something()
dict_to_test[s.x] = "message"
self.assertEqual(dict_to_test[s.x], "message")
Error message:
AssertionError: None != 'message'
What is wrong here?
Background:
The reason for creating such an exotic dict is that I want to store validation errors for each field of an object and want to avoid field names as strings: domain_object.errors[domain_object.field1] otherwise field names as strings (domain_object.errors["field1"]) would be bad for refactoring and code completion.
ΤΖΩΤΖΙΟΥ:
I'm certain you don't get anything by
using IDs. obj.field1= 1;
print(id(obj.field1)); obj.field1= 2;
print(id(obj.field1))
If I would not use IDs, the key would be the value of the variable, not its address. This would lead to errors if two fields had the same value:
def test_ordinary_dict(self):
dict_to_test = {}
class Something:
def __init__(self):
self.x = 1
self.y = 1 # same value as self.x!
s = Something()
dict_to_test[s.x] = "message for x"
dict_to_test[s.y] = "message for y"
self.assertEqual(dict_to_test[s.x], "message for x")
# fails because dict_to_test[s.x] == dict_to_test[1] what results in:
# "message for y"
It is not critical that changing a variables value lead to a new address since the validation result is no longer valid after that.
__getitem__ must return the result:
def __getitem__(self, key):
return super(ObjectIdDict, self).__getitem__(id(key))
#^^^^^
Without a return, the implicit return value is None, and therefore oiddict[key] is None for all keys.

Categories

Resources