3

I have a class that I'll be instantiating a lot from lines of JSON. Something like:

class Something:
 def __init__(self, json):
 #load all self variables from simplejson.loads(json) here
 print self.some_variable_loaded_from_json

I'd like this to be as efficient as possible because this class is loaded hundreds of times a second. I know I can do a for loop with key/value pairs in the dictionary generated from simplejson, but if there's a way to have simplejson just load directly to class variables without that O(n) overhead, that would be awesome.

asked Sep 22, 2012 at 1:34
3
  • 1
    @DemianBrecht: just incorrect - check the example in my answer: Python allows you to override your instance variables with a simple attribute assigment to __dict__ Commented Sep 22, 2012 at 2:27
  • @jsbueno: I was mistaken. For some reason, I had assumed that __dict__ was read only. Commented Sep 22, 2012 at 6:17
  • @DemianBrecht - a class's __dict__ is indeed readonly. Maybe that is why you thought that. Commented Sep 24, 2012 at 2:19

2 Answers 2

11

If you will simply load your JSON data into a Python object, just pass your relevant dictionary to the __init__ method - there you can simply override your instance __dict__ with the passed in dictionary:

>>> import json
>>> json_data = '{"a": "my data"}'
>>> data = json.loads(json_data)
>>> class AutoVar(object):
... def __init__(self, data):
... self.__dict__ = data
... 
>>> test = AutoVar(data)
>>> test.a
u'my data'

update It is 2025, and nowadays, the most used pattern for this is to make use of dataclasses. With dataclasses, you have to explicitly define the fields you want in your class, and their expected type - also, any extra keys in the original JSON object will raise an error - so the pattern above can still be useful for some lose situations.

Dataclasses were introduced in Python's stdlib mid last decade to have a standard way to reduce the __init__ boilerplate of assigning arguments to instance fields of the same name, and also adds shortcuts for a nice REPR, and some operators

from dataclasses import dataclass
@dataclass
class MyClass:
 a: str
data = {"a": "my data"}
test = MyClass(**data)
answered Sep 22, 2012 at 2:25
Sign up to request clarification or add additional context in comments.

Comments

2

You're going to have to either load the data once and keep it cached, or loop over the entire JSON blob on every instantiation of Something. Unfortunately, SimpleJson doesn't maintain an "object cache" or anything like that (nor does any other JSON library in Python). To get the data again from the JSON blob, you'd have to re-parse the blob itself (or the file, whatever it is).

What I might recommend is you add these variables from the JSON to the class rather than each instance, and only when necessary. For instance:

class Something(object):
 @classmethod
 def _load_from_json(cls, blob):
 for k, v in blob.iteritems():
 setattr(cls, k, v)

The call to _load_from_json will be relatively expensive, but you should only have to do it whenever the JSON itself changes, and then all instances of Something will have attribute-like access to the data.

On a similar note, if you are looking at a file here, I recently published a gist that allows for real-time object-like access of a YAML file (although you can really just swap out yaml for json in the code). It might do what you're looking for.

answered Sep 22, 2012 at 1:39

2 Comments

Not looking at a file, but would love to see the gist anyway. Link?
Oh, herp derp - my bad. Forgot to link. Here it is: gist.github.com/3298353

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.