Can I overload the {} operators for creating dictionaries? - python

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

Related

How to make object from dictionary readable

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.

Class method that alters the object

I've been learning about classes in python and I was trying to write a reverse method for an extended string class, which looks like:
class NewString(str):
def reverse(self):
self = self[::-1]
string = NewString('Python')
string.reverse()
print(string)
I expected it to print 'nohtyP' but it doesn't. It keeps the original value of the string and prints 'Python'. Can anyone explain to me why this doesn't work and how I could change the class to get it to do what I expected. There is no purpose for this other than learning more about how classes work.
self is just a local variable in the method. Reassigning it won't mutate the object it referred to before. Since strings are immutable, so are objects of your string subclass. All you can do is return new string objects from the methods:
class NewString(str):
def reverse(self):
return self.__class__(self[::-1]) # casts to the specific type of self
string = NewString('Python')
rev = string.reverse()
print(rev)
# nohtyP
type(rev)
# NewString

what is meaning of string inside array python

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

How to create a new unknown or dynamic/expando object in Python

In python how can we create a new object without having a predefined Class and later dynamically add properties to it ?
example:
dynamic_object = Dynamic()
dynamic_object.dynamic_property_a = "abc"
dynamic_object.dynamic_property_b = "abcdefg"
What is the best way to do it?
EDIT Because many people advised in comments that I might not need this.
The thing is that I have a function that serializes an object's properties. For that reason, I don't want to create an object of the expected class due to some constructor restrictions, but instead create a similar one, let's say like a mock, add any "custom" properties I need, then feed it back to the function.
Just define your own class to do it:
class Expando(object):
pass
ex = Expando()
ex.foo = 17
ex.bar = "Hello"
If you take metaclassing approach from #Martijn's answer, #Ned's answer can be rewritten shorter (though it's obviously less readable, but does the same thing).
obj = type('Expando', (object,), {})()
obj.foo = 71
obj.bar = 'World'
Or just, which does the same as above using dict argument:
obj = type('Expando', (object,), {'foo': 71, 'bar': 'World'})()
For Python 3, passing object to bases argument is not necessary (see type documentation).
But for simple cases instantiation doesn't have any benefit, so is okay to do:
ns = type('Expando', (object,), {'foo': 71, 'bar': 'World'})
At the same time, personally I prefer a plain class (i.e. without instantiation) for ad-hoc test configuration cases as simplest and readable:
class ns:
foo = 71
bar = 'World'
Update
In Python 3.3+ there is exactly what OP asks for, types.SimpleNamespace. It's just:
A simple object subclass that provides attribute access to its namespace, as well as a meaningful repr.
Unlike object, with SimpleNamespace you can add and remove attributes. If a SimpleNamespace object is initialized with keyword arguments, those are directly added to the underlying namespace.
import types
obj = types.SimpleNamespace()
obj.a = 123
print(obj.a) # 123
print(repr(obj)) # namespace(a=123)
However, in stdlib of both Python 2 and Python 3 there's argparse.Namespace, which has the same purpose:
Simple object for storing attributes.
Implements equality by attribute names and values, and provides a simple string representation.
import argparse
obj = argparse.Namespace()
obj.a = 123
print(obj.a) # 123
print(repr(obj)) # Namespace(a=123)
Note that both can be initialised with keyword arguments:
types.SimpleNamespace(a = 'foo',b = 123)
argparse.Namespace(a = 'foo',b = 123)
Using an object just to hold values isn't the most Pythonic style of programming. It's common in programming languages that don't have good associative containers, but in Python, you can use use a dictionary:
my_dict = {} # empty dict instance
my_dict["foo"] = "bar"
my_dict["num"] = 42
You can also use a "dictionary literal" to define the dictionary's contents all at once:
my_dict = {"foo":"bar", "num":42}
Or, if your keys are all legal identifiers (and they will be, if you were planning on them being attribute names), you can use the dict constructor with keyword arguments as key-value pairs:
my_dict = dict(foo="bar", num=42) # note, no quotation marks needed around keys
Filling out a dictionary is in fact what Python is doing behind the scenes when you do use an object, such as in Ned Batchelder's answer. The attributes of his ex object get stored in a dictionary, ex.__dict__, which should end up being equal to an equivalent dict created directly.
Unless attribute syntax (e.g. ex.foo) is absolutely necessary, you may as well skip the object entirely and use a dictionary directly.
Use the collections.namedtuple() class factory to create a custom class for your return value:
from collections import namedtuple
return namedtuple('Expando', ('dynamic_property_a', 'dynamic_property_b'))('abc', 'abcdefg')
The returned value can be used both as a tuple and by attribute access:
print retval[0] # prints 'abc'
print retval.dynamic_property_b # prints 'abcdefg'
One way that I found is also by creating a lambda. It can have sideeffects and comes with some properties that are not wanted. Just posting for the interest.
dynamic_object = lambda:expando
dynamic_object.dynamic_property_a = "abc"
dynamic_object.dynamic_property_b = "abcdefg"
I define a dictionary first because it's easy to define. Then I use namedtuple to convert it to an object:
from collections import namedtuple
def dict_to_obj(dict):
return namedtuple("ObjectName", dict.keys())(*dict.values())
my_dict = {
'name': 'The mighty object',
'description': 'Yep! Thats me',
'prop3': 1234
}
my_obj = dict_to_obj(my_dict)
Ned Batchelder's answer is the best. I just wanted to record a slightly different answer here, which avoids the use of the class keyword (in case that's useful for instructive reasons, demonstration of closure, etc.)
Just define your own class to do it:
def Expando():
def inst():
None
return inst
ex = Expando()
ex.foo = 17
ex.bar = "Hello"

Python - Call an object from a list of objects

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.

Categories