1

I have the following class:

class convert_to_obj(object):
    def __init__(self, d):
        for llist in d:
            for a, b in llist.items():
                if isinstance(b, (list, tuple)):
                    setattr(self, a, [obj(x) if isinstance(x, dict) else x for x in b])
                else:
                    setattr(self, a, obj(b) if isinstance(b, dict) else b)

    def is_authenticated(self):
        username = self.username
        password = self.password
        if username and password:
            return True

I am converting a dict to obj and then trying to access the is_authenticated method, when I do the following below:

new_array = [{'username': u'rr', 'password': u'something', }]
user = convert_to_obj(new_array)
user.is_authenticated()

it returns an error saying:

'convert_to_obj' object has no attribute 'is_authenticated'

I don't know why it's doing this. Hopefully, some other eyes might be able to point out what I am doing wrong. Thanks

1
  • BTW I've added a Q on meta about making tabs visible in rendered markdown Commented Mar 18, 2016 at 20:34

2 Answers 2

6

@user2357112 is right (and good catch, because I wouldn't have seen it):

DO NOT USE TABS IN PYTHON ­— EVER!

That said, I have a few comments about your code.

First:

class convert_to_obj(object):

is a very bad name for a class. It'd be a good name for a function, though. You should better call it, for example:

class DictObject(object):

That being said, I'd advice you to use existing tools for doing such a thing. There's a powerful one called namedtuple, in the collections module. To do your thing, you could do:

from collections import namedtuple

# Create a class that declares the interface for a given behaviour
# which will expect a set of members to be accessible
class AuthenticationMixin():
    def is_authenticated(self):
        username = self.username
        password = self.password
        # useless use of if, here you can simply do:
        # return username and password
        if username and password:
            return True
        # but if you don't, don't forget to return False below
        # to keep a proper boolean interface for the method
        return False

def convert_to_object(d): # here that'd be a good name:
    # there you create an object with all the needed members
    DictObjectBase = namedtuple('DictObjectBase', d.keys())
    # then you create a class where you mix the interface with the
    # freshly created class that will contain the members
    class DictObject(DictObjectBase, AuthenticationMixin):
        pass
    # finally you build an instance with the dict, and return it
    return DictObject(**d)

which would give:

>>> new_array = [{'username': u'rr', 'password': u'something', }]
>>> # yes here I access the first element of the array, because you want
>>> # to keep the convert_to_object() function simple. 
>>> o = convert_to_object(new_array[0])
>>> o
DictObject(password='something', username='rr')
>>> o.is_authenticated()
True

all that being more readable and easy to use.


N.B.: for a list of dicts to convert, just make:

>>> objdict_list = [convert_to_object(d) for d in new_array]
>>> objdict_list
[DictObject(password='something', username='rr')]

And if you're working with a list of pairs instead of a dict:

>>> tup_array = [('username', u'rr'), ('password', u'something')]
>>> {t[0]:t[1] for t in tup_array}
{'password': 'something', 'username': 'rr'}

So you don't need the extra leg work in the __init__().

HTH

Sign up to request clarification or add additional context in comments.

1 Comment

thanks a bunch. I have refactored my code to something similar. I am still getting the hang of python and some design principles so this comes in handy. Btw are you familiar with django? I just posted this question (stackoverflow.com/questions/36092348/…). Please check it out if you can.
5

You've mixed tabs and spaces, so the is_authenticated definition is erroneously nested inside the definition of __init__. Turn on "show whitespace" in your editor to see the problem, and run Python with the -tt flag to make it tell you when you do something like this. To fix the problem, convert the tabs to spaces; your editor most likely has a function to do this automatically.

3 Comments

Thanks! That was indeed the issue, almost drove me crazy.
How did you see that? By opening up the edit to see that it was a tab? I didn't even know that those were preserved in the actual code, because highlighting the snippet on the page doesn't make it clear (unless I'm missing something, hence why I'm asking).
yup, you need to edit, as on SO, when the code is shown, the tabs are converted to four spaces (just select the indentation), whereas the "raw" code in the edit box preserves tabs.

Your Answer

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.