Dynamically set dict elements with getattr - python

I already see the post Dynamically get dict elements via getattr?, but i can't solve my problem.
I want do something similar, but I'm a bit confused. I want set (not get) the data in the correspondent dictionary, but I get this error
AttributeError: type object 'Dictionary' has no attribute 'VERBS'.
My code is:
class Dictionary:
def __init__(self):
self.VERBS = dict()
self.REFERENCER = dict()
def setDictionary(self, fileDictionary, name):
methodCaller = Dictionary()
dictionary = "self."+name.upper()
dictionary = getattr(Dictionary, name.upper())
dictionary = fileDictionary.copy()
Can you see what I'm doing wrong? Because I don't understand completely that.

I think that this is what you are looking for:
class Dictionary:
def __init__(self):
self.VERBS = dict()
self.REFERENCER = dict()
def setDictionary(self, fileDictionary, name):
setattr(self, name.upper(), fileDictionary)
This uses setattr to assign fileDictionary to the member with the name name.upper() on self
The error that the code in the question has results from attempting to access the name on the class where it doesn't exist rather than on the instance where it exists.
It is also possible to write the method as:
def setDictionary(self, fileDictionary, name):
dictionary = getattr(self, name.upper())
dictionary.update(fileDictionary)
Which might be closer to what you were attempting.
Note that these two behave differently if the passed dictionary is mutated. The first binds the object to the name on the instance. The second updates the existing dictionary with the items from the passed dictionary.

Related

Returning the inner namespace of a class as dictionary

Imagine we have a class like as below:
class P1(object):
def __init__(self,value=0,src='admin'):
self.value=value
self.src=src
Is it possible to add a method that returns the name inner variables as a dictionary with name as the name and the value as the value like this:
def getDict(self):
return dictionary(variables)
which returns:
{
'value':0,
'src':'admin'
}
PS I know it can be down by hard coding it, I am asking if there is Pythonic way of doing it with one method call.
You can use __dict__:
A dictionary or other mapping object used to store an object’s (writable) attributes.
def getDict(self):
return self.__dict__
or vars() builtin, which simply returns the __dict__ attribute:
return vars(self)
Warning: Note that this returns a reference to the actual namespace, and any changes you make to the dictionary will be reflected to the instance.
You're looking for vars example:
return vars(self)
Output:
{'value': 0, 'src': 'admin'}
Yes, you can use magic methods. If not create your own method which returns the dict of value and src. Your code:
class P1(object):
def __init__(self,value=0,src='admin'):
self.value=value
self.src=src
def getdict(self):
return {"value":self.value,"src":self.src} #manual return of dict
x=P1(5,"user") #checking for non default values
print(x.getdict())
x=P1() #checking for default values
print(x.getdict())

How to make dictionary element an object in python?

How to make dictionary element an object in Python?
I made a class…
class Qs:
def __init__(self,list1,id,quest="",mark=1):
self.__list1=list1
self.__id=id
self.__quest=quest
self.__mark=mark
self.__list1.update({self.__id:{self.__quest:self.__mark}})
How can I store objects in a dictionary so I can call functions in this class like this?
dictionary[1].print()
what you probably want is another class that includes a dictionary in it:
class QuestionCollection:
def __init__(self):
self.listofquestions = dict()
def print(self,question_number):
print(dictionary[question_number])
Then you could do this:
classobject = MyClass()
classobject.listofquestions[1] = Qs(...)
classobject.print(1)
or,
classobject = MyClass()
print(classobject.dictionary[1])
Then, you could extend this class to include other functions that operate on your entire dictionary.

How to make classes in a loop have the same attribute

I have a class which has an attribute and a method (amongst others such as init etc) like so:
Class Example(object):
default_outputs = ['a','b','c']
def add_outputs(self,list_of_outputs):
return default_outputs + list_of_outputs
and then I have a loop which does something like this:
list_of_outputs = []
for file in filelist:
object = Example(file)
object.add_outputs(['d','e'])
list_of_outputs.append(object.get_output_of_interest_which_depends_on_outputs_added)
so as you can see, I have this add_outputs(['d','e']) call on every object in the loop - ideally what I'd want is for each object created in this specific loop to have these outputs already specified. Obviously I could add these as parameters to the init function to get something like.
object = Example(file,['d','e'])
but that is effectively the same thing and it won't work in conjunction with the other methods I have.
So in a way I guess I want a class which takes some parameters and returns another class. A class that makes a class. How can I do that in Python?
Subclass is one of options for you, for example:
Class ExampleWithDE(Example):
def __init__(self, *args, **kwargs):
super(ExampleWithDE, self).__init__(*args, **kwargs)
self.add_outputs['d','e']
and then in loop use this new class:
for file in filelist:
object = ExampleWithDE(file)
...
Dynamically creating a class is nothing complicated:
def extends_example_with(outputs):
class ExtendedExample(Example):
default_outputs = Example.default_outputs + outputs
return ExtentedExample
cls = extend_example_with([d, e])
for file in filelist:
object = cls(file)
I'm going to focus on this part of your question:
So in a way I guess I want a class which takes some parameters and returns another class. A class that makes a class. How can I do that in Python?
What you're looking after is something called the MOP, the Meta-Object Protocol, also known as reflection (kind of, not entirely true I guess). This protocol is a set of functions and datastructures that describe the object system itself to the programmer (so you have things like a Class object and so on).
http://eli.thegreenplace.net/2011/08/14/python-metaclasses-by-example/
However you could also just inherit from a base class that does this kind of thing at initialization, like so:
Class ext(Example):
def __init__(self, *args, **kwargs):
super(ext, self).__init__(*args, **kwargs)
self.add_outputs["d", "e"]
EDIT: Fixed some stuff and saw that the second part of my answer is already provided by someone else, sorry about that.
Edit 1
Wouldn't the following be what you want ?
class Example(object):
default_outputs = ['a','b','c']
def __init__(self,x):
self.x = x
#classmethod
def add_outputs(cls,list_of_outputs):
cls.used_output = cls.default_outputs + list_of_outputs
def get_output_of_interest(self):
return ''.join(self.x*y for y in self.used_output)
list_of_outputs = []
filelist = (1,3,6)
Example.add_outputs(['e','hy'])
for file in filelist:
obj = Example(file)
list_of_outputs.append(obj.get_output_of_interest())
print list_of_outputs
print '================'
list_of_outputs = []
filelist = (5,2)
Example.add_outputs(['d','G'])
for file in filelist:
obj = Example(file)
list_of_outputs.append(obj.get_output_of_interest())
print list_of_outputs
result
['abcehy', 'aaabbbccceeehyhyhy', 'aaaaaabbbbbbcccccceeeeeehyhyhyhyhyhy']
================
['aaaaabbbbbcccccdddddGGGGG', 'aabbccddGG']
Quite evidently, the codes of the __init__ and get_output_of_interest methods are just defined in order to furnish me an executable code that shows that the class' attribute named used_output is set before each loop iteration.
Doing so, this attribute as well as the object filelist can be set before each loop iteration and the result obtained after the loop depends as well on the value of filelist as on this class attribute used_output without having to set it for each created object inside the loop.
You may be interested by this excerpt of the doc:
A class instance has a namespace implemented as a dictionary which is
the first place in which attribute references are searched. When an
attribute is not found there, and the instance’s class has an
attribute by that name, the search continues with the class
attributes.
http://docs.python.org/2/reference/datamodel.html#the-standard-type-hierarchy
Original answer
Your question is hazy because doing repeatedly an assignement to one unique identifier doesn't give you access to several objects but only to the last one created.
But first there are three problems with your code that make me doubting that you tried to execute it:
it is class , not Class in the definition of a class
Example(file) produces an error since there is no __init__ method to receive the argument
using object as an identifier overrides the access to the fundamental builtin object named object
Now to show what I said at beginning:
class Example(object):
default_outputs = ['a','b','c']
def add_outputs(self,list_of_outputs):
return default_outputs + list_of_outputs
filelist = (0,1,2,3,4,5)
for file in filelist:
obj = Example()
print 'id of obj :',id(obj)
result
id of obj : 18632816
id of obj : 18603984
id of obj : 18632816
id of obj : 18603984
id of obj : 18632816
id of obj : 18603984
If you then want to access to the first object created, how do you do ? , since the first object had identity 18632816 and using the identifier obj gives access to the object with identity 18603984 !
The fact that the identities are alternatevely 18632816 and 18603984 is due to the fact that when the identifier obj is reassigned, the former binding is destroyed and the former object is lost in the RAM, and the process then reuses the same portion of the RAM to create the new object reassigned to the same identifier.
The following code shows more clearly what really happens:
class Example(object):
default_outputs = ['a','b','c']
def add_outputs(self,list_of_outputs):
return default_outputs + list_of_outputs
filelist = (0,1,2,3,4,5,6,7)
li = []
for file in filelist:
obj = Example()
li.append(obj)
print 'id of obj :',id(obj)
result
id of obj : 18632816
id of obj : 18603984
id of obj : 18633680
id of obj : 18743632
id of obj : 18743504
id of obj : 18743664
id of obj : 18743696
id of obj : 18743728
<__main__.Example object at 0x011E01B0>
This time, access to each created object isn't lost because there's an access through the index of the list li .
But the object accessed with the identifier obj is the last created one, and only this one. 011E01B0 is the hexadecimal value of the adress==identity of the object accessed with obj , if you transform it in decimal value, you'll find 18743728
So what do you want to do exactly ?

Python : Behavior of class and instance variables

I have following two code samples
Example 1:
class MyClass(object):
def __init__(self, key, value):
self._dict = self._dict.update({key:value})
m = MyClass('ten',10)
print m._dict
Output:
AttributeError: 'MyClass' object has no attribute '_dict'
Example2:
class MyClass(object):
_dict = {}
def __init__(self, key, value):
self._dict = self._dict.update({key:value})
m = MyClass('ten',10)
print m._dict
Output:
None
I am quite surprised with above behavior
Why the example2 compiled successfully by just addition of _dict = {}
line, and line present at class scope.
also why None output?
I believed class scope variables has no relation with instance variable
(special with self)
Any Explaination?
Your 'example 2' defines a single dictionary at the class level. All instances of the class will share that same dictionary, at least unless you reassign _dict on the instance.
See this question for a detailed explanation:
Why do attribute references act like this with Python inheritance?
As for why you're getting None - the update method changes its dict in place, and returns None.
The None output is because dict.update returns None. It modifies the dictionary itself, but does not return anything. So you probably wanted self._dict.update({key:value}). However, self._dict doesn't exist at initialization. So it would make more sense to do self._dict = {key: value}. If you're trying to modify the object's internal dictionary, then you should do self.__dict__.update({key:value}). However, this is bad practice. A better idea would be to write setattr(self, key, value). The reason Example2 is working successfully is because if you try to do getattr(instance, thing) (which is what instance.thing does), and thing is not in instance.__dict__, then instance.__class__.__dict__ will be checked instead.
Because the _dict in Example 2 is a class variable so it's an attribute of MyClass where as the _dict in Example 1 is an instance variable so it's a instance attribute.
Example 1: you are trying to update an object that is yet to be created. therefore error.
Example 2: When working in the inner scope of the function, if you modify the variable it makes changes to the previously defined _dict. But if you assign the value, it makes a new variable with the same name in the inner scope.
This will work.
class MyClass(object):
_dict = {}
def __init__(self, key, value):
self._dict.update({key:value})
This will not.
class MyClass(object):
_dict = {}
def __init__(self, key, value):
self._dict = self._dict.update({key:value})
because you are doing an assigning operation. It makes a new variable. So no changes are made to the _dict in the outer scope. Your _dict in the outer scope is still empty and returns None.
self._dict does not yet exist, so the first version raises that exception. The second one actually falls through looking _dict up on the instance and instead updates the class attribute, then assigns the class-level dictionary to the instance-scope _dict attribute.

returning a list from an objects elements?

I have a defined an object ( simplified below) and want to return an element as a list.
Is there an easier way than doing the below ?
class objectRecord(object):
def __init__(self,fields):
self.time=fields[0]
self.definition=fields[1]
self.name=fields[2]
self.source=fields[3]
self.size=fields[4]
self.value=fields[5]
self.increasedsize=fields[6]
self.count=fields[7]
rest of __init__ omitted
def getList(self):
return [self.name,self.definition,self.name,self.source,self.size,self.value,self.increasedsize,self.count]
rest of class omitted
You can get a dictionary containing all object attributes:
def get_attrs_dict(self):
return self.__dict__
If you just want the list of values:
def get_attrs_list(self):
return self.__dict__.values()
Here is one way to do it, via getattr():
def getList(self):
attributes = 'time definition name source'.split()
return [getattr(self, attribute) for attribute in attributes]
You can add more attributes to the list if needed.
As sort of a follow-up to Mark's comment: it looks an awful lot like what you actually want is to write your __init__ like this:
def __init__(self, fields):
self.fields = fields # or maybe fields[:] if you need to make a copy
self.definition, self.name, ... , self.count = self.fields
This is both a more convenient way to define your variables, and provides a very clear way to access all the values (through self.fields).

Categories

Resources