views:

121

answers:

4

Hello guys and gals,

Is it common in Python to keep testing for type values when working in a OOP fashion?

class Foo():
    def __init__(self,barObject):
        self.bar = setBarObject(barObject)

    def setBarObject(barObject);
        if (isInstance(barObject,Bar):
            self.bar = barObject
        else:
            # throw exception, log, etc.

class Bar():
    pass

Or I can use a more loose approach, like:

class Foo():
    def __init__(self,barObject):
        self.bar = barObject

class Bar():
    pass
+19  A: 

Nope, in fact it's overwhelmingly common not to test for type values, as in your second approach. The idea is that a client of your code (i.e. some other programmer who uses your class) should be able to pass any kind of object that has all the appropriate methods or properties. If it doesn't happen to be an instance of some particular class, that's fine; your code never needs to know the difference. This is called duck typing, because of the adage "If it quacks like a duck and flies like a duck, it might as well be a duck" (well, that's not the actual adage but I got the gist of it I think)

One place you'll see this a lot is in the standard library, with any functions that handle file input or output. Instead of requiring an actual file object, they'll take anything that implements the read() or readline() method (depending on the function), or write() for writing. In fact you'll often see this in the documentation, e.g. with tokenize.generate_tokens, which I just happened to be looking at earlier today:

The generate_tokens() generator requires one argument, readline, which must be a callable object which provides the same interface as the readline() method of built-in file objects (see section File Objects). Each call to the function should return one line of input as a string.

This allows you to use a StringIO object (like an in-memory file), or something wackier like a dialog box, in place of a real file.

In your own code, just access whatever properties of an object you need, and if it's the wrong kind of object, one of the properties you need won't be there and it'll throw an exception.

David Zaslavsky
Second that. Also see [EAFP](http://docs.python.org/glossary.html#term-eafp): Easier to Ask Forgiveness than Permission.
Muhammad Alkarouri
this is very interesting. After all, we should enjoy pythons features instead of defending from them.
George
+1  A: 

I think that it's good practice to check input for type. It's reasonable to assume that if you asked a user to give one data type they might give you another, so you should code to defend against this.

However, it seems like a waste of time (both writing and running the program) to check the type of input that the program generates independent of input. As in a strongly-typed language, checking type isn't important to defend against programmer error.

So basically, check input but nothing else so that code can run smoothly and users don't have to wonder why they got an exception rather than a result.

Rafe Kettler
This is probably good advice on other languages, but it is not the common practice in Python. See David's answer above.
Muhammad Alkarouri
very important comment. keep testing the INPUT. the difference between programmer error and user error is important. thanks.
George
I'm not sure; I learned python from MIT OCW and the professors at MIT always talked about "coding defensively", even in python
Rafe Kettler
@Rafe Kettler: generalizations are always wrong.
msw
@msw: what generalization? If it's assuming that users might give wrong input, I'd beg to differ
Rafe Kettler
@Rage: What you say is correct, but in a different context. Input that is coming from outside the program, usually strings, need to be checked for validity. Otherwise you risk all kinds of security problems: stack overflow, SQL injection, etc. However, in development the checking for type is generally superfluous. In Python, I mean.
Muhammad Alkarouri
@Rafe et al: Coding defensively with respect to user input isn't mutually exclusive with duck typing. I'd definitely agree that it's good practice to check your input for potential security issues, but pretty much all user input comes in as a string. You need to check the _content_, not the type. For things like integer conversions, `int()` raises a `ValueError` if it's given a non-numeric string, and that's enough of a check as far as the Python culture is concerned. You can always catch the error and handle it if you think it's necessary.
David Zaslavsky
@Rafe Kettler: *Users* should never see an exception. Exceptions should clearly indicate the problem, failing which *programmers* should investigate and/or read the fine manual, not wonder.
John Machin
The chance of a user that isn't a programmer passing an argument of the wrong type to an API/wrapper you're writing is somewhere between slim and none :)As a (programming) user of many APIs I'd rather be thrown back a meaningful exception with an explanation logged, so that the traceback is meaningful, rather than just the log and an unexplained, early exit, or, even worse, a silent error.I don't like dogmatic choices, and occasionally will type check inputs if I'm working on the surface close to my users, but that should be as rare as possible imo.
ThE_JacO
@Rafe: In the context of python, coding defensively would mean to either check that the method/attribute that you intend to access actually exists or (more pythonic) to assume that it does and catch the `AttributeError` if it doesn't. This is different from checking the type of the object.
aaronasterling
If you insist on testing the type of the input, How can I write a wrapper around the object and pass it to your code? There are dozens of good reasons why I might want to pass a wrapped object instead of the plain object.
gnibbler
A: 

If your alternative to the type check is an else containing exception handling, then you should really consider duck typing one tier up, supporting as many objects with the methods you require from the input, and working inside a try. You can then except (and except as specifically as possible) that. The final result wouldn't be unlike what you have there, but a lot more versatile and Pythonic.

Everything else that needed to be said about the actual question, whether it's common/good practice or not, I think has been answered excellently by David's.

ThE_JacO
A: 

I agree with some of the above answers, in that I generally never check for type from one function to another.

However, as someone else mentioned, anything accepted from a user should be checked, and for things like this I use regular expressions. The nice thing about using regular expressions to validate user input is that not only can you verify that the data is in the correct format, but you can parse the input into a more convenient form, like a string into a dictionary.

Colin Fox