Python refactoring question and create dynamic attributes

Cameron Simpson cs at cskk.id.au
Sun Jun 23 05:01:43 EDT 2019


On 23Jun2019 13:26, Arup Rakshit <ar at zeit.io> wrote:
>In the below code:
>
>    @classmethod
>    def find(self, id):
>        if isinstance(id, list):
>            rows = self.__table__().get_all(*id).run(self.__db__().conn)
>            result = []
>            for row in rows:
>                acategory = Category()
>                acategory.__dict__.update(row)
>                result.append(acategory)
>            return result
>        else:
>            adict = self.__table__().get(id).run(self.__db__().conn)
>            acategory = Category()
>            acategory.__dict__.update(adict)
>            return acategory
>
>I have 2 questions:
>
>1. Is there any better way to create attributes in an object without using __dict__().update() or this is a correct approach?

setattr() is the usual approach, but that sets a single attribute at a 
time. If you have many then __dict__.update may be reasonable.

You should bear in mind that not all objects have a __dict__. It is 
uncommon, but if a class is defined with a __slots__ attribute then its 
instances have fixed attribute names and there is no __dict__. Also some 
builtin types have not __dict__. However, you likely know that the 
objects you are using have a __dict__, so you're probably good.

Also, __dict__ bypasses properties and descriptors. That might be 
important.

>2. Can we get the same result what for row in rows: block is producing without killing the readability ?

Not obviously. It looks pretty direct to me.

Unless the Category class can be made to accept an attribute map in its 
__int__ method, then you might do some variable on:

  result = [ Category(row) for row in rows ]

which is pretty readable.

BTW, @classmethods receive the class as the first argument, not an 
instance. So you'd normally write:

  @classmethod
  def find(cls, id):
    ...

and you would not have a self to use. is __table__ a class atribute or 
an instance attribute?

>To see the context, here is my source code 
>https://gitlab.com/aruprakshit/flask_awesome_recipes/blob/master/app/models/category.py

Ah, so Category inherits from BaseModel. That means you can write your 
own __init__. If it accepted an optional mapping (i.e. a dict or row) 
you could put the .update inside __init__, supporting the list 
comprehension I suggest above.

It looks like you've marks almost all the methods as @classmethods. Are 
you sure about that? They all seem written to use self, and thus be 
instance methods.

Cheers,
Cameron Simpson <cs at cskk.id.au>



More information about the Python-list mailing list