dedalus_rex
dedalus_rex

Reputation: 469

Set an attribute to an class's attribute where the latter is returned from a class method

I have the following code that takes two lists a and b, and returns a Diff.diff attribute, which is a list with three dict() in there. I want to be able to access each dict by using an attribute of an attribute as Diff.diff.a, Diff.diff.b etc.

Now Diff.diff is a working attribute when I create a new instance of Diff class. However, I get the error that

AttributeError: 'list' object has no attribute 'a'

on the line in def __init__(... starting to define that sub-attributes

class Diff(object):   

    def __init__(self, a, b):
        self.a = dict(a)
        self.b = dict(b)

        Diff.diff = Diff.set_diff(self)
        Diff.diff.a = Diff.diff[0]
        Diff.diff.b = Diff.diff[1]
        Diff.diff.c = Diff.diff[2]

    def set_diff(self):
        # do something with self.a and self.b here
        return [{}, {}, {}] # returns a list with three items

I've tried searching for this issue and honestly I don't know what search terms to use... Hope this is not a repeated question.


EDIT:

My Solutions:

Note my code uses alpha beta gamaa instead of a b c.

class DiffList(object):

    def __init__(self, a):
        assert isinstance(a, list) and len(a) == 3
        self.alpha = DiffListItem(a[0])
        self.beta = DiffListItem(a[1])
        self.gamma = DiffListItem(a[2])


class Diff(object):

    def __init__(self, a, b):
        assert isinstance(a, list) and isinstance(b, list)
        self.a = dict(a)
        self.b = dict(b)
        self.diff = DiffList(self.set_diff())

    def set_diff(self):
        # return the list with 3 dicts
        return a

Now Diff.diff.alpha etc. returns a dict in the list as expected. Although this list is wrapped in a DiffListItem object that has a function that prints an ordered list.

class DiffListItem(object):

    def __init__(self, a):
        assert isinstance(a, dict)        
        self.a = a

    def ordered_list(self):
        # Take a dict and sort by its value, returns a ordered list with entries
        # as lists as [key, value]
        keys = sorted(self.a, key=self.a.get, reverse=1)
        res = [[key, self.a[key]] for key in keys]    
        return res

Hope this is helpful to others. I'm rather new to programming and haven't done much OOP yet. Python is giving me a great introduction to what's capable.

Upvotes: 1

Views: 74

Answers (3)

llrs
llrs

Reputation: 3397

I think that you want to create something like that:

class Diff(object):   
    a = None
    b = None
    c = None
    def __init__(self, a, b):
        self.a = dict(a)
        self.b = dict(b)

    #Do something here that modifies the diff.a, diff.b and diff.c 
    #attributes of the class like adding the dict to them

    def set_diff(self):
        # do something with self.a and self.b here
        return [{}, {}, {}] # returns a list with three items

This way by typing Diff.diff.a event without creating any object of class Diff ) you will have this attributes of attributes

Upvotes: -1

ely
ely

Reputation: 77454

The value returned by set_diff is a Python list object. list objects are a kind of data structure that allows for accessing entries positionally, based on their location in the data structure, much like the row of a matrix from math class (except that the "entries" can be any type of object).

Your code is asking for the list object that goes by the name Diff.diff to possess an attribute a that is a reference to the 0th entry, and so on. But this is not the type of data access supported by the list class.

Instead, you could use a particular data type called a namedtuple with named attributes a, b, and c. In that case, your code would look like this:

class Diff(object):   

    def __init__(self, a, b):
        self.a = dict(a)
        self.b = dict(b)
        self.diff = self.set_diff(self)

    def set_diff(self):
        # do something with self.a and self.b here
        from collections import namedtuple
        diff_tuple = namedtuple('diff_tuple', 'a b c')
        return diff_tuple({}, {}, {}) # returns a tuple with three named items

Upvotes: 2

jonrsharpe
jonrsharpe

Reputation: 122067

Diff.diff is a list, which you can't access by attribute. Instead, you could create a new object with those attributes. With the DiffList (or some better name; it isn't a list) defined as:

class DiffList(object):
    def __init__(self):
        self.a = {}
        self.b = {}
        self.c = {}

You should probably use this as an instance, rather than class, attribute:

def __init__(self, a, b):
    self.a = dict(a)
    self.b = dict(b)
    self.diff = DiffList() # no need for a separate method
    self.diff.a # ...

Then you can access it later:

diff = Diff(a, b)
diff.diff.a # ...

Upvotes: 1

Related Questions