2

I am new to OOP with python. I have 3 classes with one being called from the other as a parameter instance:

class Characters:
    def __init__(self, b="", c = ""):
        self.b= b
        self.c= c           

class Words:
    def __init__(self, charss=Characters()):       
        self.charss= charss

class Sentences:
    def __init__(self, w=Words()):
        self.w = w

I am then creating a new instance of class Words form another Class and filling it with data i have from a json file.

s = Sentences()
s.__dict__ = json.loads(output.content)

When debugging i can see that s is populated correctly. I am then trying to print out the values of s like this:

print(s.w[0].charss[0])

an error occurs:AttributeError: 'dict' object has no attribute 'charss'

is it because I am populating from the JSON as __dict__ where charss instantiated as list. If that is so what would be the best solution changing the __dict__ from json input or instantiating the object as __dict__?

martineau
  • 119,623
  • 25
  • 170
  • 301
bcsta
  • 1,963
  • 3
  • 22
  • 61
  • 3
    Beware of using [mutable default arguments](https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument). – glibdud Mar 23 '18 at 12:15
  • @glibdud how is that the issue? – bcsta Mar 23 '18 at 12:18
  • 1
    It's not, that's just a public service announcement. – glibdud Mar 23 '18 at 12:18
  • @glibdud ok Thank you for that. Do you happen to know what my issue is though? – bcsta Mar 23 '18 at 12:22
  • What is the content of `output.content`? – glibdud Mar 23 '18 at 12:22
  • output is a requests.get(url) which contains a json formatted string – bcsta Mar 23 '18 at 12:23
  • Can you paste the actual contents into the question (redacted as necessary)? – glibdud Mar 23 '18 at 12:25
  • You wrote "`word` is populated correctly", but there's no symbol called `word` in any of your code. Do you mean `s`? – Personman Mar 23 '18 at 12:26
  • yes i will edit that i mean s – bcsta Mar 23 '18 at 12:26
  • @glibdud there is no need to post it here it is a long unuseful String that contains data in a json format. it is then being converted into python objects with json.loads function – bcsta Mar 23 '18 at 12:30
  • 2
    Well then we can't tell you what's wrong, because after you set `s.__dict__` to that, `s`'s attributes are entirely defined by what's in there. – glibdud Mar 23 '18 at 12:32
  • ... interesting question... I want to see this solved somehow. cheers for the service anouncement... > learned something very valuable today about something I thought was indeed a glitch in py2.7 and predecessors (might have solved in 3.5, which as I understand now shouldn't!) < (no need for down-voting Bruno Desthuilliers... it shows you are not able to see the beauty yet.. you will). – ZF007 Mar 23 '18 at 13:05
  • I wouldn't even worry about the error just yet, because it's not clear how you even intend to use the classes as designed. What is `Characters` supposed to represent--what are `b` and `c`? What is `Words` if not just a wrapper around a single `Characters` instance (and the same question applies to `Sentences`). – chepner Mar 23 '18 at 13:26

2 Answers2

1

The problem is the way the instance s is being accessed for printing. I am saving the json output as a dictionary but the instance of a class is by default a list. therefore instead of

print(s.w[0].charss[0])

that line should be

print(s.w[0]["charss"][0])
bcsta
  • 1,963
  • 3
  • 22
  • 61
0

When you say s.__dict__ = some_dictionary, you're entirely replacing all the instance variables of s with the ones in some_dictionary. This includes w, which is now defined entirely by whatever's in your JSON. JSON objects are never going to have charss attributes, so it's guaranteed to fail in the way you mention.

What are you trying to accomplish with s.__dict__ = json.loads(output.content)? Do you just want to store the dictionary in s? If so, s.my_cool_dict_name = json.loads(output.content) might be what you want.

Personman
  • 2,324
  • 1
  • 16
  • 27
  • with s.__dict__ = json.loads(output.content) i want to pupulate instance s and whatever sub instances is creates when called. this can be done because the json i am reading from has also the same structure of the class s and sub classes w and charss – bcsta Mar 23 '18 at 13:53
  • No, it can't – JSON objects will never be converted python objects with arbitrary attributes, only strings, ints, lists, and dicts, and thus will never have a `charss` attribute. If it is actually a dictionary, then you need ['charss'] instead of .chars. – Personman Mar 23 '18 at 20:42
  • Yes i realised that after sometime in fact that was the answer I was looking for but I managed to find the answer myself. thanks anyways. – bcsta Mar 24 '18 at 14:25