The goal is to build a class with an __init__ method that will allow to create objects which will be initialized with a specific dictionary.
Details:
A file mydicts.py is a collection of various dictionaries.
The object built from the class that I intent to create will be initialized to one of the dictionaries from mydicts.py.
mydicts.py example:
dict1 = {k1:v1, k2:v2,...,kn:vn}
dict2 = {k1:v1, k2:v2,...,km:vm}
etc.
My attempts:
class Example(dict):
def __init__(self, dictx):
self.dictx = getattr(__import__("mydicts", fromlist=['m']), dictx)
Results:
e = Example('dict1')
print e
{} # <- got empty dictionary. Want {k1:v1, k2:v2,...,kn:vn}
The goal is to create objects such that:
a = Example(dict1)
print a
# {k1:v1, k2:v2,...,kn:vn}
b = Example(dict2)
print b
# {k1:v1, k2:v2,...,km:vm}
Since you did not define a custom __str__ method for your class, print is calling the __str__ method of the parent class dict. Moreover, this is causing Python to print the empty dictionary created by the parent class in dict.__new__ instead of the dictionary that you have stored in self.dictx.
Because your class inherits from dict, you should be passing the dictionary returned by getattr to the __init__ method of the parent class. You can use super for this:
class Example(dict):
def __init__(self, dictx):
dct = getattr(__import__("__main__", fromlist=['m']), dictx)
super(Example, self).__init__(dct)
This will initialize the parent class with data taken from dct. In other words, the empty dictionary has been replaced with the dictionary returned by getattr. So, when print calls the parent's __str__ method, the correct output will be given:
>>> dict1 = {'k1':'v1', 'k2':'v2', 'kn':'vn'}
>>> class Example(dict):
... def __init__(self, dictx):
... dct = getattr(__import__("__main__", fromlist=['m']), dictx)
... super(Example, self).__init__(dct)
...
>>> e = Example('dict1')
>>> print e
{'k2': 'v2', 'k1': 'v1', 'kn': 'vn'}
>>>
An alternate solution would be to define a custom __str__ method for your class that returns self.dictx as a string:
class Example(dict):
def __init__(self, dictx):
self.dictx = getattr(__import__("mydicts", fromlist=['m']), dictx)
def __str__(self):
return str(self.dictx)
Note however that if you use this approach, there isn't really a reason to inherit from dict since your class is not a new type of dictionary; it just has a dictionary stored as an attribute.
I think you are making this far more complicated than it need be. Noting the manual says:
Direct use of __import__() is rare, except in cases where you want to import a module whose name is only known at runtime.
But you do know the module name at loading time, your data definition just has too many variable names. Much clearer would be my_dicts.py:
my_dicts = [
{k1:v1, k2:v2,...,kn:vn},
{k1:v1, k2:v2,...,km:vm},
…
]
and example.py:
import my_dicts
class Example(dict):
def __init__(self, n):
"""Returns an Example instance loaded with the nth element
of my_dict."""
super(Example, self).__init__(my_dicts.my_dicts[n])
Related
I'm trying to understand some code which is using this class below:
class Base(object):
def __init__(self, **kwargs):
self.client = kwargs.get('client')
self.request = kwargs.get('request')
...
def to_dict(self):
data = dict()
for key in iter(self.__dict__): # <------------------------ this
if key in ('client', 'request'):
continue
value = self.__dict__[key]
if value is not None:
if hasattr(value, 'to_dict'):
data[key] = value.to_dict()
else:
data[key] = value
return data
I understand that it gets keyword arguments passed to the Base class like for example, Base(client="foo", request="bar").
My confusion is, why is it using self.__dict__ which turns variables inside __init__ to a dict (e.g {"client": "foo", "request": "bar"}) instead of just calling them by self.client & self.request inside other methods? When and why I should use self.__dict__ instead?
Almost all of the time, you shouldn't use self.__dict__.
If you're accessing an attribute like self.client, i.e. the attribute name is known and fixed, then the only difference between that and self.__dict__['client'] is that the latter won't look up the attribute on the class if it's missing on the instance. There is very rarely any reason to do this, but the difference is demonstrated below:
>>> class A:
... b = 3 # class attribute, not an instance attribute
...
>>> A.b # the class has this attribute
3
>>> a = A()
>>> a.b # the instance doesn't have this attribute, fallback to the class
3
>>> a.__dict__['b'] # the instance doesn't have this attribute, but no fallback
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'b'
The main use-case for self.__dict__ is when you don't want to access a fixed, known attribute name. In almost all code, you always know which attribute you want to access; and if you do need to look something up dynamically using an unknown string, you should create a dictionary yourself, and write self.that_dict[key] instead of self.__dict__[key].
So the only times you should really use __dict__ is when you are writing code which needs to work regardless of which attributes the instance might have; i.e. you specifically want code which will work even if you change the class's structure or its attribute names, or code which will work across multiple classes with different structures. I'll show one example below.
The __repr__ method
The __repr__ method is meant to return a string representing the instance, for the programmer's convenience when using a REPL. For debugging/testing purposes this string usually contains information about the object's state. Here's a common way to implement it:
class Foo:
def __init__(self, foo, bar, baz):
self.foo = foo
self.bar = bar
self.baz = baz
def __repr__(self):
return 'Foo({!r}, {!r}, {!r})'.format(self.foo, self.bar, self.baz)
This means if you write obj = Foo(1, 'y', True) to create an instance, then repr(obj) will be the string "Foo(1, 'y', True)", which is convenient because it shows the instance's entire state, and also the string itself is Python code which creates an instance with the same state.
But there are a few issues with the above implementation: we have to change it if the class's attributes change, it won't give useful results for instances of subclasses, and we have to write lots of similar code for different classes with different attributes. If we use __dict__ instead, we can solve all of those problems:
def __repr__(self):
return '{}({})'.format(
self.__class__.__name__,
', '.join('{}={!r}'.format(k, v) for k, v in self.__dict__.items())
)
Now repr(obj) will be Foo(foo=1, bar='y', baz=True), which also shows the instance's entire state, and is also executable Python code. This generalised __repr__ method will still work if the structure of Foo changes, it can be shared between multiple classes via inheritance, and it returns executable Python code for any class whose attributes are accepted as keyword arguments by __init__.
__dict__ holds all of the variables in the class. Take the following class:
class A():
def __init__(self, foo):
self.foo = foo
def new_var(self, bar):
self.bar = bar
Then in this case, notice:
a = A('var1')
print(a.__dict__) # {'foo': 'var1'}
b = A('var1')
b.new_var('var2')
b.foobar = 'var3'
print(b.__dict__) # {'foo': 'var1', 'bar': 'var2', 'foobar': 'var3'}
In your case you could do either or. __dict__ is a great way to grab all of the variables that are part of that class at the current instance in which it is called. You can check out the documentation on __dict__ here.
__dict__ is used when checking what instance variables(data attributes) an object has.
So, if there is Person class below:
class Person:
x1 = "Hello"
x2 = "World"
def __init__(self, name, age):
self.name = name
self.age = age
def test1(self):
print(self.__dict__) # Here
#classmethod
def test2(cls):
pass
#staticmethod
def test3():
pass
obj = Person("John", 27)
obj.test1() # Here
__dict__ gets name and age with their values in a dictionary as shown below:
{'name': 'John', 'age': 27} # Here
And, if the new instance variable gender is added after instanciation as shown below:
# ...
obj= Person("John", 27)
obj.test1()
obj.gender = "Male" # Here
obj.test1()
__dict__ gets name, age and gender with their values in a dictionary as shown below:
{'name': 'John', 'age': 27}
{'name': 'John', 'age': 27, 'gender': 'Male'} # Here
class Device(object):
data = None
def __init__(self, properties):
self.data = json.loads(properties)
pass
This is my device class and I want to assign properties to my object created by Json results using loops in python. my device properties are 'description' 'device_type','facility','id','latitude','longitude','sequence','source','update_date','web_url'
There are a number of ways to accomplish this. First would be to use the setattr method:
other_properties = {'device_type': "usb", 'id', '12345'} # and on and on
d = Device(properties=some_properties)
for k, v in other_properties.items():
setattr(d, k, v) # this will set d.<key> = value
This is relatively simple and easy to read, however some might complain about setting self attributes outside of __init__.
Next, you can pass in the properties as a dict like before and unpack them in __init__:
class Device:
def __init__(self, **properties):
for k, v in properties.items():
setattr(self, k, v) # again using setattr
Or if you already know what that dictionary of items is, you can set your keyword args on __init__ ahead of time and unpack them that way
class Device:
def __init__(self, id=None, device_type=None, latitude=None): # ad nauseum
self.id = id
self.device_type = device_type
...
d = Device(**properties) # This syntax will unpack properties into the correct keyword args
Another approach could be to call update on Device.__dict__, though there are definitely valid arguments on why not to do this
class Device:
def __init__(self, properties):
self.__dict__.update(properties)
Finally, the question could be raised "do you even need a class here?" If you want to just store key-value pairs you could use a dict and just use dict-style access paradigms:
d = {**properties}
d.get('id') # 12345
Or if you want class style access, you could use a namedtuple:
from collections import namedtuple
Device = namedtuple("Device", ['id', 'device_type', ...]) # Your other kwargs go here
d = Device(**properties)
d.id # 12345
To create many instances of the classes/namedtuples, you can do that with a list comprehension or for loop
For loop:
devices = []
for properties in records: # Where records is a list of json properties
devices.append(Device(**properties))
List comprehension
devices = [Device(**properties) for properties in records
Edit: Using json
The code above assumes that properties behaves like a dictionary, ** unpacking will take a dictionary and unpack it into the correct keyword arguments on a function definition. If you are passing a string, this won't work, which is why you are using the json module.
json.loads parses a string object into a python object type. For example:
import json
r = json.loads('["a", "b", "c"]')
# listType ['a', 'b', 'c']
# r is a list object containing the strings 'a', 'b', 'c'
It is most commonly used with returning dictionaries from json-formatted strings
mystr = '''
{ "id": 12345,
"device_type": "usb",
"loc": "abc12345"}'''
my_obj = json.loads(mystr)
# my_obj is a dict now
To put this in context with what you have defined in your problem, let's say you have a json_string property and you want to load that into a class like I have done above. First using your method:
class Device:
def __init__(self, property_string):
properties = json.loads(property_string)
for k, v in properties.items():
setattr(self, k, v)
To use the methods I have outlined above, you will just take that json.loads call and do it outside the class:
class Device:
def __init__(self, id=None, device_type=None, ...): # all of your attrs go there
self.id = id
self.device_type = device_type
... # more of the same here
properties = json.loads(property_string)
d = Device(**properties)
I am creating a dictionary of objects that I'd like to save and re-load at a different time (I want to do this with the "json" module, not "pickle").
I have one class created (let's call it "Ball"), and the dictionary just contains many different instances of that class. The way it looks is:
my_dict = {
"ball1": {"size": "big", "baseball": False, etc...},
"ball2": {"size": "small", "baseball": True, etc...},
etc...
}
As I create new instances of the "Ball" class, I just APPEND them to "my_dict".
My "Ball" class has methods that allow me to change the value of certain fields...ie:
changeSize(self, size)
PROBLEM:
In order for me to get the save ability to work properly with the json module I have had to do the following to each new instance of the "Ball" class:
newBall = Ball(name)
my_dict[name] = newBall.__dict__
Adding the
.__dict__
and then appending that to the dictionary makes it JSON serializable, BUT it makes it so that when I go in to "Edit Mode" I can't call the method (ie changeSize(name) ) because it is just a dictionary and no longer a "Ball" object.
How do I make it so that I can save (using json module) and also use the methods that I have in place to edit?
Also, the way I am saving/loading is as follows:
out_file = open("testSave.json"), "w")
json.dump(my_dict, out_file, indent=4)
out_file.close()
in_file = open("testSave.json", "r")
my_dict = json.load(in_file)
in_file.close()
Thanks!
Ultimately, json doesn't support serializing arbitrary python objects. If you want to do that, you can have a look at pickle.
Alternatively, you can create an alternate constructor on your Ball that will initialize it with values from the dict:
class Ball(object):
#classmethod
def from_json(self, dictionary):
b = cls()
b.__dict__.update(dictionary)
return b
...
I've written this assuming that the Ball constructor can be called with 0 arguments -- you may need to modify the code if that isn't the case, or if __init__ does anything "fancy" (beyond setting json serializable attributes). One way around the requirement of the arguments of __init__ is to use __new__ to create the instance and then just populate the members by updating the class dictionary:
class Ball(object):
def __init__(self, name, foo, bar):
self.name = name
self.foo = foo
self.bar = bar
def to_dict(self):
return self.__dict__
#classmethod
def from_dict(cls, dictionary):
self = cls.__new__(cls)
self.__dict__.update(dictionary)
return self
def __str__(self):
return 'Ball(%r, %r, %r)' % (self.name, self.foo, self.bar)
b = Ball('HockyPuck', 'flat', 'NotABall')
d = b.to_dict()
bb = Ball.from_dict(d)
print(bb)
This works in both python2.x and 3.x.
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.
For example I have a base class as follows:
class BaseClass(object):
def __init__(self, classtype):
self._type = classtype
From this class I derive several other classes, e.g.
class TestClass(BaseClass):
def __init__(self):
super(TestClass, self).__init__('Test')
class SpecialClass(BaseClass):
def __init__(self):
super(TestClass, self).__init__('Special')
Is there a nice, pythonic way to create those classes dynamically by a function call that puts the new class into my current scope, like:
foo(BaseClass, "My")
a = MyClass()
...
As there will be comments and questions why I need this: The derived classes all have the exact same internal structure with the difference, that the constructor takes a number of previously undefined arguments. So, for example, MyClass takes the keywords a while the constructor of class TestClass takes b and c.
inst1 = MyClass(a=4)
inst2 = MyClass(a=5)
inst3 = TestClass(b=False, c = "test")
But they should NEVER use the type of the class as input argument like
inst1 = BaseClass(classtype = "My", a=4)
I got this to work but would prefer the other way, i.e. dynamically created class objects.
This bit of code allows you to create new classes with dynamic
names and parameter names.
The parameter verification in __init__ just does not allow
unknown parameters, if you need other verifications, like
type, or that they are mandatory, just add the logic
there:
class BaseClass(object):
def __init__(self, classtype):
self._type = classtype
def ClassFactory(name, argnames, BaseClass=BaseClass):
def __init__(self, **kwargs):
for key, value in kwargs.items():
# here, the argnames variable is the one passed to the
# ClassFactory call
if key not in argnames:
raise TypeError("Argument %s not valid for %s"
% (key, self.__class__.__name__))
setattr(self, key, value)
BaseClass.__init__(self, name[:-len("Class")])
newclass = type(name, (BaseClass,),{"__init__": __init__})
return newclass
And this works like this, for example:
>>> SpecialClass = ClassFactory("SpecialClass", "a b c".split())
>>> s = SpecialClass(a=2)
>>> s.a
2
>>> s2 = SpecialClass(d=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in __init__
TypeError: Argument d not valid for SpecialClass
I see you are asking for inserting the dynamic names in the naming scope --
now, that is not considered a good practice in Python - you either have
variable names, known at coding time, or data - and names learned in runtime
are more "data" than "variables" -
So, you could just add your classes to a dictionary and use them from there:
name = "SpecialClass"
classes = {}
classes[name] = ClassFactory(name, params)
instance = classes[name](...)
And if your design absolutely needs the names to come in scope,
just do the same, but use the dictionary returned by the globals()
call instead of an arbitrary dictionary:
name = "SpecialClass"
globals()[name] = ClassFactory(name, params)
instance = SpecialClass(...)
(It indeed would be possible for the class factory function to insert the name dynamically on the global scope of the caller - but that is even worse practice, and is not compatible across Python implementations. The way to do that would be to get the caller's execution frame, through sys._getframe(1) and setting the class name in the frame's global dictionary in its f_globals attribute).
update, tl;dr: This answer had become popular, still its very specific to the question body. The general answer on how to
"dynamically create derived classes from a base class"
in Python is a simple call to type passing the new class name, a tuple with the baseclass(es) and the __dict__ body for the new class -like this:
>>> new_class = type("NewClassName", (BaseClass,), {"new_method": lambda self: ...})
update
Anyone needing this should also check the dill project - it claims to be able to pickle and unpickle classes just like pickle does to ordinary objects, and had lived to it in some of my tests.
type() is the function that creates classes and in particular sub-classes, like in the question:
def set_x(self, value):
self.x = value
# type() takes as argument the new class name, its base
# classes, and its attributes:
SubClass = type('SubClass', (BaseClass,), {'set_x': set_x})
# (More methods can be put in SubClass, including __init__().)
obj = SubClass()
obj.set_x(42)
print obj.x # Prints 42
print isinstance(obj, BaseClass) # True
In my case :
inst3 = globals()["SpecialClass"](b=False, c = "test")
To create a class with a dynamic attribute value, checkout the code below.
NB. This are code snippets in python programming language
def create_class(attribute_data, **more_data): # define a function with required attributes
class ClassCreated(optional extensions): # define class with optional inheritance
attribute1 = adattribute_data # set class attributes with function parameter
attribute2 = more_data.get("attribute2")
return ClassCreated # return the created class
# use class
myclass1 = create_class("hello") # *generates a class*