I encounter a strange dictionary. Let's call it cp_dict. When I type:
cp_dict['ZnS-Zn']
it returns:
{Element Zn: -1.159460605, Element S: -4.384479766249999}
The child key looks like a string but without quotation marks. How I can access the child keys (for example: Element Zn) and modify the values? I tried cp_dict['Zn3P2-Zn'][Element Zn], and the error is
SyntaxError: invalid syntax. Perhaps you forgot a comma?
The cp_dict['Zn3P2-Zn']['Element Zn'] leads to:
KeyError: 'Element Zn'
I checked type(cp_dict['ZnS-Zn']) . It returns <class 'dict'>.
It is quite easy to make a custom class which represents itself in that way ("looking like a string but without quotation marks"). The result returned by a __repr__ method is what gets used when representing instances inside collections such as dicts and lists:
>>> class Element:
... def __init__(self, symbol):
... self.symbol = symbol
... def __repr__(self):
... return f"Element {self.symbol}"
...
>>> d = {Element("Zn"): -1.159460605, Element("S"): -4.384479766249999}
>>> d
{Element Zn: -1.159460605, Element S: -4.384479766249999}
So, my guess is the keys of the dict are the strange items, not the dict itself. Check the type of a key, and look up it's __repr__ method. You can get the type of the first key with:
k = next(iter(cp_dict["ZnS-Zn"]))
Element = type(k)
To index the dict you will need an instance which compares equal with one of those keys. Again, look up type(k).__eq__ for that. If the __eq__ method is not customized, then you will need to use the identical key to index this dict, since the equality method will just be the default identity-based implementation which is inherited from object.
Related
I created a class Demo in which I added a constructor with an empty dictionary in it. With the method addSomething inside the class I add key value pairs to this dictionary. The key which gets added is of type str and the value of type int. In another method useKeys in the same class I wanna access the key which I added to the dictionary. With the keys() method I only get the key like dict_keys([<__main__.Demo object at 0x7f7cd00c75b0>]). How can I make the str who was added visible?
Code
class Demo:
def __init__(self, someString):
self.something = dict()
def addSomething(self, something):
if something not in self.something:
self.something[something] = 0
self.something[something] += 1
def useKeys(self):
#prints dict_keys([<__main__.Demo object at 0x7f7cd00c75b0>])
print(self.something.keys())
something1 = Demo("ABC")
something2 = Demo("DEF")
something1.addSomething(something2)
print(something1.useKeys())
Edit
One suggestion in the comments is to use __str__. I understand that this method gets called always if an object from this class gets printed. But how can I make the key from the dictionary readable? My current implementation does not make the key readable:
def __str__(self):
return "{self.something}".format(self=self)
With the method addSomething inside the class I add key value pairs to this dictionary. The key which gets added is of type str and the value of type int.
No, it is not. The key which gets added is of type Demo and the value is of type int. This is why printing the dictionary keys is printing the __repr__ of a Demo object.
How can I make the str who was added visible?
You did not add any str. The strings passed as arguments in your code are never used.
You can either write the __repr__ function (which will override the object object function of the same name, from which every python3 class inherits), or you can use the argument someString you're already providing and that it's not being used at all, it's only forcing you to provide a string when creating a new instance of a Demo object:
Solution 1
Actually using the attribute someString from the constructor in the addSomething function.
With this solution, the key is indeed of the type str.
class Demo:
def __init__(self, someString):
self.something = dict()
self.someString = someString # Actually using the string provided at instance time
def addSomething(self, something):
## This method will use the attribute someString from object something instead
if something.someString not in self.something:
self.something[something.someString] = 0
self.something[something.someString] += 1
def useKeys(self):
## keys are now strings
print(self.something.keys())
something1 = Demo("ABC")
something2 = Demo("DEF")
something1.addSomething(something2)
print(something1.useKeys())
Solution 2
Overriding __repr__, but you require a string anyway so using someString from the constructor too.
With this solution, the key is of type Demo, but when you print that key, it'll display a string.
class Demo:
def __init__(self, someString):
self.something = dict()
self.someString = someString # Actually using the string provided at instance time
def addSomething(self, something):
## This method will use the something object as in the original code
if something not in self.something:
self.something[something] = 0
self.something[something] += 1
def __repr__(self):
## When something1.__repr__ is called, it'll display the someString provided at instance time
return self.someString
def useKeys(self):
## keys are objects, but will appear as strings because of the __repr__ method from that object
print(self.something.keys())
something1 = Demo("ABC")
something2 = Demo("DEF")
something1.addSomething(something2)
print(something1.useKeys())
The __str__ function of an object is used in another circumstance, it's not needed in your requirement.
You can just convert it into a list for easy representation:
print(list(something1.useKeys()))
By the way, it does seem like the class you're implementing already exists as collections.Counter.
What does "CmdBtn['menu'] = CmdBtn.menu" in second last line mean.
def makeCommandMenu():
CmdBtn = Menubutton(mBar, text='Button Commands', underline=0)
CmdBtn.pack(side=LEFT, padx="2m")
CmdBtn.menu = Menu(CmdBtn)
...
...
CmdBtn['menu'] = CmdBtn.menu
return CmdBtn
When you use x[y] = z, it calls the __setitem__ method.
i.e.
x.__setitem__(y, z)
In your case, CmdBtn['menu'] = CmdBtn.menu means
CmdBtn.__setitem__('menu', CmdBtn.menu)
The Menubutton class does indeed provide a __setitem__ method. It looks like this is used to set a "resource value" (in this case CmdBtn.menu) for the given key ('menu').
This is not a "string inside an array".
The brackets operator is used for item access in some kind of sequence (usually a list, or a tuple), mapping (usually a dict, or dictionary), or some other kind of special object (such as this MenuButton object, which is not a sequence or a mapping). Unlike in some other languages, in python, ANY object is allowed to make use of this operator.
A list is similar to an "array" in other languages. It can contain a mixture of objects of any kind, and it maintains the order of the objects. A list object is very useful for when you want to maintain an ordered sequence of objects. You can access an object in a list using its index, like this (indexes start at zero):
x = [1,2,3] # this is a list
assert x[0] == 1 # access the first item in the list
x = list(range(1,4)) # another way to make the same list
A dict (dictionary) is useful for when you want to associate values with keys so you can look up the values later using the keys. Like this:
d = dict(a=1, b=2, c=3) # this is a dict
assert x['a'] == 1 # access the dict
d = {'a':1, 'b':2, 'c':3} # another way to make the same dict
Finally, you may also encounter custom made objects that also use the same item-access interface. In the Menubutton case, ['menu'] simply accesses some item (defined by the tkinter API) that responds to the key, 'menu'. You can make your own object type with item-access, too (python 3 code below):
class MyObject:
def __getitem__(self, x):
return "Here I am!"
This object doesn't do much except return the same string for key or index value you give it:
obj = MyObject()
print(obj [100]) # Here I am!
print(obj [101]) # Here I am!
print(obj ['Anything']) # Here I am!
print(obj ['foo bar baz']) # Here I am!
First of all, in Python everything is an object and square brackets means that this object is subscriptable (for e.g. tuple, list, dict, string and many more). Subscriptable means that this object at least implements the __getitem__() method (and __setitem__() in your case).
With those methods it's easy to interact with class members, so don't afraid to build your own example, to understand someone else's code.
Try this snippet:
class FooBar:
def __init__(self):
# just two simple members
self.foo = 'foo'
self.bar = 'bar'
def __getitem__(self, item):
# example getitem function
return self.__dict__[item]
def __setitem__(self, key, value):
# example setitem function
self.__dict__[key] = value
# create an instance of FooBar
fb = FooBar()
# lets print members of instance
# also try to comment out get and set functions to see the difference
print(fb['foo'], fb['bar'])
# lets try to change member via __setitem__
fb['foo'] = 'baz'
# lets print members of instance again to see the difference
print(fb['foo'], fb['bar'])
It is shorthand for CmdBtn.configure(menu=CmdBtn.menu)
The way to set widget options is typically at creation time (eg: Menubutton(..., menu=...)) or using the configure method (eg: CmdBtn.configure(menu=...). Tkinter provides a third method, which is to treat the widget like a dictionary where the configuration values are keys to the dictionary (eg: CMdBtn['menu']=...)
This is covered in the Setting Options section of the official python tkinter documentation
I am making a derived variant of the dict class such that a dictionary value can be accessed through attribute access syntax (so instead of doing dictionary['foo'] you could do dictionary.foo.) This is what I have so far:
class dict(dict):
__getattr__ = dict.__getitem__
However, this snippet of my code gives it problems:
eventD = {'rrule_end':None}
. . .
. . .
#(some time later)
print event.rrule_end
This is because the { } operators for dictionary creation have not been overloaded. Is it possible to make the dictName = { } syntax create an instance of my derived class instead of an ordinary dictionary?
No. You cannot override dict literal syntax. (You also can't override list literal syntax, or string literal syntax, or number literal syntax, or any literal syntax.)
You have to create the instance of your class explicitly. Give your class a name like MyDict and then do
eventD = MyDict({'rrule_end':None})
no, you can't overload that syntax, but their are alternative things you can do.
convert a normal dictionary into your dictionary
my_dict( {'foo':bar, 'foo2':bar2} )
make your function accept key-args
my_dict( foo='bar', foo2='bar2' )
make up your own syntax for this dictionary.
this is abusing python's overloadable operators and is a little complex to do.
its a chain reaction, starting with my_dict<'foo'.
overload the operator so it outputs another my_dict object and repeat the process,
each time keeping a record of each value until if finally reaches the end object.
then it calculates and spits out you own object object.
my_dict<'foo'|bar,'foo2'|'bar2'>end
EDIT:
I'm not sure the reason you want to do this, but this could be an alternative answer to your problem. you may also want to have a look at the vars built in function. this lets you get a dictionary of every attribute an object has. if the object changes, the dictionary changes automatically.
class dict_obj(object):
def __init__(self, obj):
self.obj = obj
self.dict = vars(obj)
def __getattr__(self, value):
return self.dict[value]
__getitem__ = __getattr__
you can use it like this
>>> class test:
def __init__(self):
self.value = 5
>>> obj = dict_obj(test())
>>> obj.value
5
>>> obj['value']
5
I have a class, and I would like to be able to create multiple objects of that class and place them in an array. I did it like so:
rooms = []
rooms.append(Object1())
...
rooms.append(Object4())
I then have a dict of functions, and I would like to pass the object to the function. However, I'm encountering some problems..For example, I have a dict:
dict = {'look': CallLook(rooms[i])}
I'm able to pass it into the function, however; in the function if I try to call an objects method it gives me problems
def CallLook(current_room)
current_room.examine()
I'm sure that there has to be a better way to do what I'm trying to do, but I'm new to Python and I haven't seen a clean example on how to do this. Anyone have a good way to implement a list of objects to be passed into functions? All of the objects contain the examine method, but they are objects of different classes. (I'm sorry I didn't say so earlier)
The specific error states: TypeError: 'NoneType' object is not callable
Anyone have a good way to implement a list of objects to be passed into functions? All of the objects contain the examine method, but they are objects of different classes. (I'm sorry I didn't say so earlier)
This is Python's plain duck-typing.
class Room:
def __init__(self, name):
self.name = name
def examine(self):
return "This %s looks clean!" % self.name
class Furniture:
def __init__(self, name):
self.name = name
def examine(self):
return "This %s looks comfortable..." % self.name
def examination(l):
for item in l:
print item.examine()
list_of_objects = [ Room("Living Room"), Furniture("Couch"),
Room("Restrooms"), Furniture("Bed") ]
examination(list_of_objects)
Prints:
This Living Room looks clean!
This Couch looks comfortable...
This Restrooms looks clean!
This Bed looks comfortable...
As for your specific problem: probably you have forgotten to return a value from examine()? (Please post the full error message (including full backtrace).)
I then have a dict of functions, and I would like to pass the object to the function. However, I'm encountering some problems..For example, I have a dict:
my_dict = {'look': CallLook(rooms[i])} # this is no dict of functions
The dict you have created may evaluate to {'look': None} (assuming your examine() doesn't return a value.) Which could explain the error you've observed.
If you wanted a dict of functions you needed to put in a callable, not an actual function call, e.g. like this:
my_dict = {'look': CallLook} # this is a dict of functions
if you want to bind the 'look' to a specific room you could redefine CallLook:
def CallLook(current_room)
return current_room.examine # return the bound examine
my_dict = {'look': CallLook(room[i])} # this is also a dict of functions
Another issue with your code is that you are shadowing the built-in dict() method by naming your local dictionary dict. You shouldn't do this. This yields nasty errors.
Assuming you don't have basic problems (like syntax errors because the code you have pasted is not valid Python), this example shows you how to do what you want:
>>> class Foo():
... def hello(self):
... return 'hello'
...
>>> r = [Foo(),Foo(),Foo()]
>>> def call_method(obj):
... return obj.hello()
...
>>> call_method(r[1])
'hello'
Assuming you have a class Room the usual way to create a list of instances would be using a list comprehension like this
rooms = [Room() for i in range(num_rooms)]
I think there are some things you may not be getting about this:
dict = {'look': CallLook(rooms[i])}
This creates a dict with just one entry: a key 'look', and a value which is the result of evaluating CallLook(rooms[i]) right at the point of that statement. It also then uses the name dict to store this object, so you can no longer use dict as a constructor in that context.
Now, the error you are getting tells us that rooms[i] is None at that point in the programme.
You don't need CallLook (which is also named non-standardly) - you can just use the expression rooms[i].examine(), or if you want to evaluate the call later rooms[i].examine.
You probably don't need the dict at all.
That is not a must, but in some cases, using hasattr() is good... getattr() is another way to get an attribute off an object...
So:
rooms = [Obj1(),Obj2(),Obj3()]
if hasattr(rooms[i], 'examine'):#First check if our object has selected function or attribute...
getattr(rooms[i], 'examine') #that will just evaluate the function do not call it, and equals to Obj1().examine
getattr(rooms[i], 'examine')() # By adding () to the end of getattr function, we evalute and then call the function...
You may also pass parameters to examine function like:
getattr(rooms[i], 'examine')(param1, param2)
I'm not sure of your requirement, but you can use dict to store multiple object of a class.
May be this will help,
>>> class c1():
... print "hi"
...
hi
>>> c = c1()
>>> c
<__main__.c1 instance at 0x032165F8>
>>> d ={}
>>> for i in range (10):
... d[i] = c1()
...
>>> d[0]
<__main__.c1 instance at 0x032166E8>
>>> d[1]
<__main__.c1 instance at 0x032164B8>
>>>
It will create a object of c1 class and store it in dict. Obviously, in this case you can use list instead of dict.
Long story short, I want to call format with arbitrarily named arguments, which will preform a lookup.
'{Thing1} and {other_thing}'.format(**my_mapping)
I've tried implementing my_mapping like this:
class Mapping(object):
def __getitem__(self, key):
return 'Proxied: %s' % key
my_mapping = Mapping()
Which works as expected when calling my_mapping['anything']. But when passed to format() as shown above I get:
TypeError: format() argument after ** must be a mapping, not Mapping
I tried subclassing dict instead of object, but now calling format() as shown raises KeyError. I even implemented __contains__ as return True, but still KeyError.
So it seems that ** is not just calling __getitem__ on the object passed in. Does anyone know how to get around this?
In Python 2 you can do this using string.Formatter class.
>>> class Mapping(object):
... def __getitem__(self, key):
... return 'Proxied: %s' % key
...
>>> my_mapping = Mapping()
>>> from string import Formatter
>>> Formatter().vformat('{Thing1} and {other_thing}', (), my_mapping)
'Proxied: Thing1 and Proxied: other_thing'
>>>
vformat takes 3 args: the format string, sequence of positional fields and mapping of keyword fields. Since positional fields weren't needed, I used an empty tuple ().
Python 3.2+:
'{Thing1} and {other_thing}'.format_map(my_mapping)
This may be a bit of necromancy, but I recently came across this problem, and this SO question was the first result. I wasn't happy with using string.Formatter, and wanted it to Just Work (TM).
If you implement a keys() function for your class as well as __getitem__(), then **my_mapping will work.
I.e:
class Mapping(object):
def __getitem__(self, key):
return 'Proxied: %s' % key
def keys(self):
return proxy.keys()
where
>>> my_mapping = Mapping()
>>> my_mapping.keys()
['Thing1','other_thing',...,'Thing2']
will result in a successful mapping that will work with .format.
Apparently (though I haven't actually looked at the source for str.format), it appears to use keys() to get a list of keys, then map the identifiers given in the string to those keys, then use __getitem__() to retrieve the specified values.
Hope this helps.
EDIT:
If you are in #aaron-mcmillin's position, and the key set is large, then a possible approach is to not generate a full set of keys, but generate a smaller subset. This only works of course if you know you will only need to format a small subset.
I.e:
class Mapping(object):
...
def keys(self):
return ['Thing1','other_thing', 'Thing2']
This is the best I could come up with:
If you have a custom mapping object that you want to pass to a func taking key-word arguments, then it must have a set of keys (which may be dynamically generated, but it must be a finite set), and it must be able to map those keys somehow. So, if you can assume that it will have an __iter__ to get the keys, and a __getitem__ that will succeed for each of those keys, e.g.:
class Me(object):
def __init__(self):
pass
def __iter__(self):
return iter(['a', 'b', 'c'])
def __getitem__(self, key):
return 12
Say the function is:
def myfunc(**kwargs):
print kwargs, type(kwargs)
Then we can pass it along by making a dict:
m = Me()
myfunc(**dict((k, m[k]) for k in m))
Resulting in:
{'a': 12, 'c': 12, 'b': 12} <type 'dict'>
Apparently this must be the way it's done... even if you pass in an object derived from dict, the function will still have a dict for the kwargs:
class Me(dict): pass
m = Me()
print type(m) #prints <class '__Main__.Me'>
def myfunc(**kwargs):
print type(kwargs)
myfunc(**m) #prints <type 'dict'>
Since it sounds like you wanted to do something like return a value based on what the key was, without having a particular set of keys in mind, it seems like you can't use the format function.