Beyond the Basic Stuff With Python by Al Sweigart

Beyond the Basic Stuff With Python by Al Sweigart

Author:Al Sweigart [Sweigart, Al]
Language: eng
Format: epub
ISBN: 9781593279677
Google: BG_cDwAAQBAJ
Publisher: No Starch Press
Published: 2020-12-22T00:00:00+00:00


Python is a dynamically typed language, which means that Python functions and methods are free to return values of any data type. But to make your functions more predictable, you should strive to have them return values of only a single data type.

For example, here’s a function that, depending on a random number, returns either an integer value or a string value:

>>> import random >>> def returnsTwoTypes(): ... if random.randint(1, 2) == 1: ... return 42 ... else: ... return 'forty two'

When you’re writing code that calls this function, it can be easy to forget that you must handle several possible data types. To continue this example, say we call returnsTwoTypes() and want to convert the number that it returns to hexadecimal:

>>> hexNum = hex(returnsTwoTypes()) >>> hexNum '0x2a'

Python’s built-in hex() function returns a string of a hexadecimal number of the integer value it was passed. This code works fine as long as returnsTwoTypes() returns an integer, giving us the impression that this code is bug free. But when returnsTwoTypes() returns a string, it raises an exception:

>>> hexNum = hex(returnsTwoTypes()) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'str' object cannot be interpreted as an integer

Of course, we should always remember to handle every possible data type that the return value could have. But in the real world, it’s easy to forget this. To prevent these bugs, we should always attempt to make functions return values of a single data type. This isn’t a strict requirement, and sometimes there’s no way around having your function return values of different data types. But the closer you get to returning only one type, the simpler and less bug prone your functions will be.

There is one case in particular to be aware of: don’t return None from your function unless your function always returns None. The None value is the only value in the NoneType data type. It’s tempting to have a function return None to signify that an error occurred (I discuss this practice in the next section, “Raising Exceptions vs. Returning Error Codes”), but you should reserve returning None for functions that have no meaningful return value.

The reason is that returning None to indicate an error is a common source of uncaught 'NoneType' object has no attribute exceptions:

>>> import random >>> def sometimesReturnsNone(): ... if random.randint(1, 2) == 1: ... return 'Hello!' ... else: ... return None ... >>> returnVal = sometimesReturnsNone() >>> returnVal.upper() 'HELLO!' >>> returnVal = sometimesReturnsNone() >>> returnVal.upper() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'NoneType' object has no attribute 'upper'

This error message is rather vague, and it could take some effort to trace its cause back to a function that normally returns an expected result but could also return None when an error happens. The problem occurred because sometimesReturnsNone() returned None, which we then assigned to the returnVal variable. But the error message would lead you to think the problem occurred in the call to the upper() method.

In a



Download



Copyright Disclaimer:
This site does not store any files on its server. We only index and link to content provided by other sites. Please contact the content providers to delete copyright contents if any and email us, we'll remove relevant links or contents immediately.