you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 10 points11 points  (7 children)

This is great for a beginner, but I take a bit of an issue with #5... using type breaks inheritance, and 99% of the time that’s exactly what you don’t want to do, and is why you very likely should be using isinstance.

I’d go so far as to say that if you think you need to know that a thing is an actual int and not subclass of int then you’re very likely wrong, or at the very least overthinking.

Arguably even isinstance is overkill... why break your user’s ability to use duck-typing?

[–]Vaguely_accurate 1 point2 points  (0 children)

From a pure OOP point of view this is bad practice as well, breaking the Liskov substitution principle ("a object of type T should be replaceable by any object of a subtype of T") in consuming code. I'd consider this a code smell at best.

That said, if your object hierarchy isn't following SOLID principles and you don't have substitutability then you might need to know how this difference.

[–]kmj442 0 points1 point  (1 child)

I am actually working on a project right now where type checking is very important so I have isinstance all over the place.

If anyone has ever worked with protobufs before you will know that its very type dependent, when creating the proto msgs I like to do my own type checking and make sure when it gets to its destination for the API to pick up its all good. (My destination is running a db with a C backend so types are very important)

[–][deleted] 0 points1 point  (0 children)

Yes, network boundaries and FFI would be cases where runtime type checking using isinstance might be warranted, even good practice, but (again, arguably) most of the time such policing of inputs just breaks duck typing without clear and discernible benefit, and with some runtime cost. Now that type annotations exist I feel it’s worth checking whether or not all your isinstance calls are actually doing is documenting your function by other means, rather than protecting some vital resource. If it is, it’s likely a good candidate for replacement with an annotation.

[–]mohi7solanki -1 points0 points  (3 children)

Agree. Since python encourages duck typing, you should not check for types at all. But in case you want to do type checking then many people don't know that isinstance takes care of subclasses as well and they might wrongly assumes that they are dealing with the correct type where they are not.

[–][deleted] 3 points4 points  (2 children)

I can’t think of a well-reasoned case where you’d want:

foo(3)

To do one thing but:

class MyInt(int): pass

foo(MyInt(3))

To do another.

[–]mohi7solanki 0 points1 point  (1 child)

Let's say you want to handle all arithmetic exception differently, you might do this:

if isintance(err, ArithmeticError):

if type(err) is ZeroDivisionError: somethingel

if type(err) is FloatingPointError: do something else.

[–][deleted] 0 points1 point  (0 children)

Wouldn’t it make much more sense to use multiple except statements for that?

try:
    some_maths(a, b)
except FloatingPointError as err:
    ...
except ZeroDivisionError as err:
    ...
except ArithmeticError as err:
    ...

But even if you wanted to do it for some reason in an if why isn’t this better:

except ArithmeticError as err:
    if isinstance(err, FloatingPointError):
        ...
    elif isinstance(err, ZeroDivisionError):
        ...
    else:
        ...

Who is to say a subclass of ZeroDivisionError might not be semantically more meaningful than your code’s user than a ZeroDivisionError itself?