try..except or type() or isinstance()?

Chris Angelico rosuav at gmail.com
Sat Aug 15 02:15:29 EDT 2020


On Sat, Aug 15, 2020 at 3:36 PM Manfred Lotz <ml_news at posteo.de> wrote:
>
> I have an object which I could initialize providind an int or a str.
>
> I am not sure which of the following is best to use
>  - try/except
>  - if type(int)...
>  - if isinstance(v, int)
>
> Here a minimal example
>
> def get_id(fromname):
>     # do something with `fromname`
>     return 0
>
> def get_name(fromid):
>     # do something with `fromid`
>     return "something"
>
> """ For O1, O2, O3: self.myid is int
>                                         self.name is str
> """
> class O1:
>     def __init__(self, val):
>         try:
>             self.myid = int(val)
>             self.name = get_name(self.myid)
>         except:
>             self.myid = get_id(val)
>             self.name = val

Don't use a bare "except" - use "except ValueError" instead. But
otherwise, this is a perfectly reasonable way to say "anything that
can be interpreted as an integer will be".

> class O2:
>     def __init__(self, val):
>         if type(val) == int:
>             self.myid = val
>             self.name = get_name(self.myid)
>         else:
>             self.myid = get_id(val)
>             self.name = val

Nope, don't do this. It's strictly worse than O3.

> class O3:
>     def __init__(self, val):
>         if isinstance(val, int):
>             self.myid = val
>             self.name = get_name(self.myid)
>         else:
>             self.myid = get_id(val)
>             self.name = val

This is a perfectly reasonable way to say "integers will be treated as
IDs". Note that O1 and O3 are very different semantically; O1 will
treat the string "7" as an ID, but O3 will treat it as a name.

Here's an even better way:

class O4:
    def __init__(self, id):
        self.myid = id
        self.name = get_name(id)
    @classmethod
    def from_name(cls, name):
        return cls(get_id(name))

This makes the ID the main way you'd do things, and a name lookup as
an alternate constructor. Very good pattern, reliable, easy to use.

ChrisA


More information about the Python-list mailing list