python dictionary key Vs object attribute - python

suppose i have object has key 'dlist0' with attribute 'row_id' the i can access as
getattr(dlist0,'row_id')
then it return value
but if i have a dictionary
ddict0 = {'row_id':4, 'name':'account_balance'}
getattr(ddict0,'row_id')
it is not work
my question is how can i access ddict0 and dlist0 same way
any one can help me?

Dictionaries have items, and thus use whatever is defined as __getitem__() to retrieve the value of a key.
Objects have attributes, and thus use __getattr__() to retrieve the value of an attribute.
You can theoretically override one to point at the other, if you need to - but why do you need to? Why not just write a helper function instead:
Python 2.x:
def get_value(some_thing, some_key):
if type(some_thing) in ('dict','tuple','list'):
return some_thing[some_key]
else:
return getattr(some_thing, some_key)
Python 3.x:
def get_value(some_thing, some_key):
if type(some_thing) in (dict,tuple,list):
return some_thing[some_key]
else:
return getattr(some_thing, some_key)

Perhaps a namedtuple is more suitable for your purpose
>>> from collections import namedtuple
>>> AccountBalance=namedtuple('account_balance','row_id name')
>>> ddict0=AccountBalance(**{'row_id':4, 'name':'account_balance'})
>>> getattr(ddict0,'row_id')
4
>>> ddict0._asdict()
{'row_id': 4, 'name': 'account_balance'}

Related

Python - overriding a method based on specific access type

I have a situation where I need to create a dictionary that keeps track of global order of the values. I haven't been able to find a good way for the class itself to have an incrementing counter that's also tracked by the value.
Here's what I've written in the meanwhile to get around this:
from collections import defaultdict
class NotMyDict(object):
""" defaultdict(list) that tracks order globally across the dict.
Will function as a normal defaultdict(list) unless you modify the
'ordered' attribute and set it to a non-false evaluating value. This
"""
ordered = False
_data = defaultdict(NotMyDictList)
_next_index = 0
class NotMyDictList(list):
def append(self, value):
def __repr__(self):
if self.ordered:
return repr(self._data)
else:
temp = defaultdict(list)
for key in self._data:
for value in self._data[key]:
temp[key].append(value[0])
return repr(temp)
def __getitem__(self, key):
if self.ordered:
return self._data[key]
else:
return [val[0] for val in self._data[key]]
def add_value_to_key(self, key, value):
self._data[key].append((value, self._next_index))
self._next_index += 1
So I can use this like a normal dictionary for pulling values. I could have instantiated a list if the key didn't exist, but defaultdict was simple and easy.
Here's an example of the use:
test = NotMyDict()
test.add_value_to_key('test', 'hi')
test.add_value_to_key('test', 'there')
test.add_value_to_key('test', 'buddy')
test['test']
Result:
['hi', 'there', 'buddy']
test.ordered = True
test['test']
Result:
[('hi', 0), ('there', 1), ('buddy', 2)]
Now - the example of use isn't super important, but the functionality that I can't seem to figure out, is instead of using the .add_value_to_key(), I want to be able to use a normal defaultdict(list) convention of:
dict[key].append()
and still have it track the index. Do I need to pass global object locations with id() and reference those objects at a memory level, or is there a way I just don't understand to have a "class global" that's accessible by it's members?
I had also tried to use nested classes, but the nested class didn't have access to the parent class's globals, so I'd have to:
Make a list-like class that references the parent class attribute somehow (Maybe with id() and direct memory location reference?)
modify/make it's append() function so that it also updates the parent class global counter, and tracks the value with this counter as a metadata field.
I really just can't seem to wrap my head around how to create this object/class in a way that let's me use the same functionality of a defaultdict(list) where I can index/append directly AND have it track the global index order of that new value.
dict[key].append(value)
Help would be appreciated - I sunk three hours into trying different solutions before I scrapped it and went with the "just use this method to append" for now.

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

TypeError: first argument must be callable, defaultdict

The error comes from publishDB = defaultdict(defaultdict({})) I want to make a database like {subject1:{student_id:{assignemt1:marks, assignment2:marks,finals:marks}} , {student_id:{assignemt1:marks, assignment2:marks,finals:marks}}, subject2:{student_id:{assignemt1:marks, assignment2:marks,finals:marks}} , {student_id:{assignemt1:marks, assignment2:marks,finals:marks}}}. I was trying to populate it as DB[math][10001] = a dict and later read out as d = DB[math][10001]. Since, I am on my office computer I can not try different module.
Am I on right track to do so?
Such a nested dict structure can be achieved using a recursive defaultdict "tree":
def tree():
return defaultdict(tree)
publishDB = tree()
At each level, the defaultdicts are instantiated with tree which is a zero-argument callable, as required.
Then you can simply assign marks:
publishDB[subject][student][assignment] = mark
defaultdict() requires that its first argument be callable: it must be a class that you want an instance of, or a function that returns an instance.
defaultdict({}) has an empty dictionary, which is not callable.
You likely want defaultdict(dict), as dict is a class that returns a dictionary when instantiated (called).
But that still doesn't solve the problem... just moves it to a different level. The outer defaultdict(...) in defaultdict(defaultdict(dict)) has the exact same issue because defaultdict(dict) isn't callable.
You can use a lambda expression to solve this, creating a one-line function that, when called, creates a defaultdict(dict):
defaultdict(lambda: defaultdict(dict))
You could also use the lambda at the lower level if you wanted:
defaultdict(lambda: defaultdict(lambda: {}))

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