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

Manfred Lotz ml_news at posteo.de
Sat Aug 15 04:16:32 EDT 2020


On Sat, 15 Aug 2020 08:33:58 +0200
Peter Otten <__peter__ at web.de> wrote:

> Chris Angelico wrote:
> 
> > 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.
> >  
> 
> Yet another way: keyword arguments:
> 
> class O5:
>     def __init__(self, *, id=None, name=None):
>         if name is None:
>             assert id is not None
>             name = get_name(id)
>         else:
>             assert id is None
>             id = get_id(name)
>         self.id = id
>         self.name = name
> 

Thanks. Also a nice method. As said in my other reply it doesn't fit to
my use case.

-- 
Manfred



More information about the Python-list mailing list