Question

Description:

I've read a lot opinions about checking value type in python and most said that you shouldn't check type, but instead use try and except. I want to make clear few things.

Questions:

When I have method like this:

def set_age(self, age):
    self._age = age

I can't let user pass any types other then int because later in code it can cause some harder to debug bugs. And according to Python methodology I can't check type. So how should I do it with try in the proper way?

def set_age(self, age):
    try:
        age = int(age)
    except TypeError:
        raise TypeError('First parameter must be of int type.')
    self._age = age

Or just

def set_age(self, age):
    self._age = int(age)

and let Python raise errors on it's own.

I know it might be silly questions, I just want to make sure.

Was it helpful?

Solution

Python will raise an appropriate error if it's not an integer, so there is no need to put your own over the top of it.

Let's step back a bit though, as there are other problems here. getters and setters are really unpythonic - either just use an attribute, or use properties.

In this case, I think you are still thinking in the wrong way. The reason we don't type check in Python is because we shouldn't care what type something is, just if it will work in the given situation. Making everything the type you think it should be as soon as you get it is essentially type checking.

You say it will make it harder to debug, but that's not really the experience most people have. Duck typing is designed to allow anything that can do the job do the job. Converting everything to an int limits your program. The problem isn't here, the problem is with your code that is passing something that doesn't make sense to your class. In my experience, this is actually a really rare thing to do - you don't tend to throw random stuff at classes and see what sticks.

So, my suggestion here is that you use an attribute - just do x.age = ... instead of using set_age() or anything like that. If you really need to have an int (as in, only whole numbers make sense), then use a property and call int() in the setter, leaving the error to propagate to the caller if it happens.

OTHER TIPS

One tenet of python is that "its better to ask forgiveness than permission". Many times the exceptions generated by the functions your function calls are sufficient to tell the caller of your function what went wrong.

That being said, in some cases I'll throw a more specific exception where the semantics to the caller don't entirely line up. one example I can think of is where I am examining a json response and I get a "key error" on one element of the dictionary. This typically means whatever request I sent out failed, and I therefore can't find the data I need. I'll in turn throw something more semantically in line with my function like "Query Failed".

Most times though exceptions thrown by called functions "type error" or "io error" should make perfect sense to the caller of my function so I don't bother catching and rethrowing.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top