Chris Angelico 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. 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 -- https://mail.python.org/mailman/listinfo/python-list