I find this design pattern comes up a lot:
try: year = int(request.GET['year'])
except: year = 0
The try
block can either fail because the key doesn't exist, or because it's not an int
, but I don't really care. I just need a sane value in the end.
Shouldn't there be a nicer way to do this? Or at least a way to do it on one line? Something like:
year = int(request.GET['year']) except 0
Or do you guys use this pattern too?
Before you answer, I already know about request.GET.get('year',0)
but you can still get a value error. Wrapping this in a try/catch block to catch the value error just means the default value appea开发者_开发知识库rs twice in my code. Even worse IMO.
You're probably better off to use get()
year = int(request.GET.get("year", 0))
This will set year to what ever request.GET['year'] is, or if the key doesn't exist, it will return 0. This gets rid of your KeyError, but you could still have a ValueError from request.GET['year'], if it is not convert'able to an int.
Regarding your question (the try/except), a common idiom in Python is EAFP.
EDIT:
If you're really concerned, why not write your own method to do this:
def myGet(obj, key, type, defaultval):
try:
return type(obj.get(key, defaultval))
except ValueError:
return defaultval
# In your code
year = myGet(request.GET, 'year', int, 0)
Shouldn't there be a nicer way to do this?
There is -- it's known as "a function"...:
def safeget(adict, key, type, default):
try: return type(adict.get(key, default))
except (ValueError, TypeError): return default
year = safeget(request.GET, 'year', int, 0)
FWIW, I don't think I've ever used this "pattern" -- the various error cases you're ignoring seem like they should be handled separately for UI reasons (a missing optional field defaulting is fine, but if somebody's mistakenly typed, say, 201o
(the 0
and o
keys being closed and, in some fonts, their results appearing similar), it generally doesn't seem nice to silently turn their input into 0
. So, I don't think it's so frequent, nor highly advisable, to warrant anything like a special syntax form in the language, or even a built-in function.
But the nice thing about helper functions like safeget
is that you and I can peacefully agree to disagree on the design issues involved (maybe we're just used to doing different kinds of software, for example!-) while letting each of us easily have exactly the helper functions each desires in their personal "utilities" modules!-)
I'd use a helper function:
def get_int(request, name, default=0):
try:
val = int(request.GET[name])
except (ValueError, KeyError):
val = default
return val
then:
year = get_int(request, 'year')
It keeps the complexity of the try/catch in one place, and makes for tidy functions, where you have one line per parameter in your view functions.
No way to do it in one line (that I can think of), but I'd do it like this, using get()
:
try:
year = int(request.GET.get("year", 0))
except ValueError:
year = 0
Also, it's generally better to catch a specific exception, not all exceptions.
精彩评论