def genflatten(lists)for in listsif isinstance( ,list)for item in genflatten( )yield item elseyield item care should also be taken when mixing recursive functions and decorators if decorator is applied to recursive functionall inner recursive calls now get routed through the decorated version for example@locked def factorial( )if < return elsereturn factorial( calls the wrapped version of factorial if the purpose of the decorator was related to some kind of system management such as synchronization or lockingrecursion is something probably best avoided documentation strings it is common practice for the first statement of function to be documentation string describing its usage for exampledef factorial( )"""computes factorial for examplefactorial( ""if < return elsereturn *factorial( - the documentation string is stored in the _doc_ attribute of the function that is commonly used by ides to provide interactive help if you are using decoratorsbe aware that wrapping function with decorator can break the help features associated with documentation strings for exampleconsider this codedef wrap(func)call(*args,**kwargs)return func(*args,**kwargsreturn call @wrap def factorial( )"""computes factorial ""if user requests help on this version of factorial()he will get rather cryptic explanationhelp(factorialhelp on function call in module _main_ _call(*args**kwargs(endf lib fl ff