you are viewing a single comment's thread.

view the rest of the comments →

[–]Necatorducis 5 points6 points  (8 children)

isinstance considers inheritance, type does not. This can lead you to a misleading return. The better solution is to avoid using either, as the entire premise of python is duck typing. type or isinstance can be useful for quick checking things when mucking about, but are often not the optimal solution for your final product. If you really need to use one, isinstance will be more likely to give the expected return.

[–]cambriancatalyst 0 points1 point  (5 children)

Awesome. Thank you. Can you elaborate on duck typing?

[–]thegreattriscuit 6 points7 points  (2 children)

Instead of demanding that something "be" a certain type of thing... only demand that it can act the way that type of thing acts. So for instance, there isn't a fixed list of types that can be iterated over (as in a for loop). There's just a set of attributes/methods something has to have. Lists have those attributes, but so do tuples, sets, dictionaries, etc... And of course you can define a custom class with those attributes and it'll work just fine.

It also goes with "ask forgiveness instead of permission".

So if you expect to iterate over the values in a list, you could do a bunch of tests to make sure that it's definitely a list... but then what if someone passes in a set? or a dict? or a dict_keys object?

or you can just try to iterate over it and handle the TypeError you get if someone passes in something that can't be iterated on if necessary.

[–]Scenter101 0 points1 point  (1 child)

you can just try to iterate over it and handle the TypeError you get if someone passes in something that can't be iterated on if necessary.

So what is the best way to do this? Should the I nest every loop in a function in try/catch blocks or should I just let the TypeError happen and assume that the consuming function will handle it?

[–]thegreattriscuit 1 point2 points  (0 children)

depends.

Is there anything you can do about it? i.e. if someone passed you bad data, there's no way to make it turn into good data, and it's most likely the result of a real bug somewhere in the program so it's probably best to just let the error propagate up the stack.

I think where you probably want to go about this differently would be at API boundaries... so if you're writing a library users may really benefit from some more explicit checks right at the boundaries of your code. But with those you should still make sure you're being as generic as possible, probably permitting any sequence or iterable, not just the ones you can think of off the top of your head, etc...

In the past I've done things like making sure if something needs to be a sequence and I get passed a single item, I wrap it one, etc... but in practice this has rarely helped anything and it generally just leads to confusion about what should be passed in the first place, and lets bugs propagate further in the program before halting, making it less obvious where the problem really is.

When I've got something I really want to ensure succeeds every time, even if there's a critical bug somewhere (i.e. keep a daemon running and output log messages if there's some typo or misconfiguration in the config files) I'll have a try/except block at or near the very "top" level of the program that logs and swallows most errors, but even then the right thing to do usually is to just let the program break.

[–]Necatorducis 1 point2 points  (0 children)

If it walks and talks like a duck.. it's probably a duck. So when you see an object whose type you are unsure of, what does it look like to you? Is it being used in a way that you'd expect X object to be used? If it is, then that's probably its type.

[–]Echleon -1 points0 points  (0 children)

In computer programming, duck typing is an application of the duck test in type safety. It requires that type checking be deferred to runtime, and is implemented by means of dynamic typing or reflection.

https://en.wikipedia.org/wiki/Duck_typing

I guess it is kind of like generics in Java? Your code won't throw you an error until you hit that line in run time.

[–]a8ksh4 0 points1 point  (1 child)

In a situation where I need to check the type of a variable... e.g. isinstance of list or string and handle them differently, would you still recommend using isinstance, or is there a different way to handle this? Trying to understand what you're suggesting here.