Hi Chris, Thanks a lot for you advice. On Sat, 15 Aug 2020 16:15:29 +1000 Chris Angelico <ros...@gmail.com> wrote:
> On Sat, Aug 15, 2020 at 3:36 PM Manfred Lotz <ml_n...@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. Oops, yes. You are right, of course. > 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. > Aaa ok. I think in this particular case it would be ok but in general it might be bad if val would be a class object. So, I take your advice to avoid this in general as then I avoid errors in more complicated situations when using type(..). > > 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. > For my use case I don't like this solution as I get the value which could be an int or str from a file. Means I would have to check the type beforehand in order to know if I have to do O4(val) or O4.from_name(val). Otherwise, it is admittedly a very good pattern. -- Manfred -- https://mail.python.org/mailman/listinfo/python-list