debuggingtestingand profiling here we have written the test code directly in the test method without the need for an inner functioninstead using unittest testcase assertraised(as context manager that expects the code to raise an attributeerror we have also used python ' unittest testcase assertlistequal(method at the end as we have seenpython' test modules are easy to use and are extremely usefulespecially if we use tdd they also have lot more functionality and features than have been shown here--for examplethe ability to skip tests which is useful to account for platform differences--and they are also well documented one feature that is missing--and which nose and py test provide--is test discoveryalthough this feature is expected to appear in later python version (perhaps as early as python profiling ||if program runs very slowly or consumes far more memory than we expectthe problem is most often due to our choice of algorithms or data structuresor due to our doing an inefficient implementation whatever the reason for the problemit is best to find out precisely where the problem lies rather than just inspecting our code and trying to optimize it randomly optimizing can cause us to introduce bugs or to speed up parts of our program that actually have no effect on the program' overall performance because the improvements are not in places where the interpreter spends most of its time before going further into profilingit is worth noting few python programming habits that are easy to learn and applyand that are good for performance none of the techniques is python-version-specificand all of them are perfectly sound python programming style firstprefer tuples to lists when read-only sequence is needed seconduse generators rather than creating large tuples or lists to iterate over thirduse python' built-in data structures--dictslistsand tuples--rather than custom data structures implemented in pythonsince the built-in ones are all very highly optimized fourthwhen creating large strings out of lots of small stringsinstead of concatenating the small stringsaccumulate them all in listand join the list of strings into single string at the end fifth and finallyif an object (including function or methodis accessed large number of times using attribute access ( when accessing function in module)or from data structureit may be better to create and use local variable that refers to the object to provide faster access python' standard library provides two modules that are particularly useful when we want to investigate the performance of our code one of these is the timeit module--this is useful for timing small pieces of python codeand can be usedfor exampleto compare the performance of two or more implementations of particular function or method the other is the cprofile module which can