0

In Python 2 code I had something like:

   ...
   elif type(value) == datetime.date:
       return transform_date(value)
   elif type(value) == datetime.datetime:
       return transform_datetime(value)
   ...

Now, if I follow advise of avoiding "antipattern", I should replace it with isinstance.

isinstance(value, datetime.date)

And there will be a problem, because then correctness will depend on which type I check first.

I am well aware of more than 10 years old How to compare type of an object in Python? and What's the canonical way to check for type in Python? , but this question differs in two important ways:

  1. It's about Python 3, idioms may be different
  2. I am interested in exact check, because the transformation depends on the exact type (otherwise it will be lossy)

Exact match: For example, obj.__class__ or type(obj) matches.

As in Python there is only one obvious way to do it, the answer to this question should not depend on opinion that much.

Roman Susi
  • 4,135
  • 2
  • 32
  • 47
  • What do you mean by exact match? Technically `isinstance` will match parents and children... What defines an exact match? – Error - Syntactical Remorse Aug 07 '19 at 14:03
  • If you write tests for the behaviour, they will ensure that you start with the most specific type in the implementation. Alternatively, they will pass if you continue to use the existing implementation, which works just fine in Python 3 too. Antipatterns depend on context - if you understand *why* `isinstance` is often preferred, you also know when that doesn't apply. – jonrsharpe Aug 07 '19 at 14:03
  • 1
    What correctness are you worried about? `isinstance(value, datetime.date)` will return `True` if `value` is an instance of a sublass of `date`, but that doesn't seem to be an issue here. – chepner Aug 07 '19 at 14:06
  • 2
    @chepner it will also return `True` if `value` is an instance of `datetime.datetime`, which subclasses `datetime.date`. – jonrsharpe Aug 07 '19 at 14:08
  • Ah, wasn't aware of that `datetime` inherited from `date`. – chepner Aug 07 '19 at 14:09
  • 1
    Something like https://pypi.org/project/singledispatch/ is probably more appropriate than manually checking types. – chepner Aug 07 '19 at 14:11
  • 1
    Anyway, I'm not aware of any additional ways to check types having been added in Python 3. – chepner Aug 07 '19 at 14:12
  • Exactly @jonrsharpe : Tests catched regression. – Roman Susi Aug 07 '19 at 14:14
  • Wow, wasn't even aware this existed xD (=> singledispatch) – bruno desthuilliers Aug 07 '19 at 14:14
  • @chepner Nice idea about singledispatch . I need to check if it matches exactly or in the same way as isinstance – Roman Susi Aug 07 '19 at 14:21
  • I *suspect* that it works like `isinstance`, but takes care to choose the most specific match, regardless of the order in which you define implementations. – chepner Aug 07 '19 at 14:25
  • @chepner Yes, it worked regardless of order at least in a simple case. – Roman Susi Aug 07 '19 at 14:28

1 Answers1

3

If you really want strict per-exact-class match, the pythonic solution hasn't changed since py2: use a dict

dispatch = {
    datetime.date: transform_date,
    datetime.datetime: transform_datetime,
    # etc
}

transform = dispatch.get(type(value), some_default_func)
transform(value)
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118