Aditya Lal wrote: > On 10/29/07, *Kent Johnson* <[EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>> > wrote:
> - Common Python practice is to prefer the least restrictive type check > possible. > I completely agree that the check " type(n) == int " is very intuitive > and simple. Its just that there are many more types that the basic ones > and 'types' module provide a "consistent" way for checking for types. Yes, for some types it is easiest to import types and use its definitions. Whether to use types.IntegerType or int is a matter of preference, I suppose. > As > an example - consider a function : > > def execMyFun( f ) : > if type(f) == types.GeneratorType : > return f.next() > elif type(f) == types.FunctionType : > return f() > else : > raise Exception("Invalid type for f : " + type(f) ) > > Here types module came to the rescue which otherwise I would have > written using exception handling. /Well ! if you have a cleaner solution > do let me know./ You probably should write this using exception handling. The least restrictive type check is to check for the specific operations you need, rather that checking for a type that supports the operation. This can be done with preflight checks - known as Look Before You Leap - or by trying an operation and catching exceptions in case of failure, known as Easier to Ask Forgiveness than Permission. In this case, it seems that if f implements the iterator protocol then you want the next item and if f is callable then you want to just call it. In both cases checking for specific operations or trying the operation and catching any exception will allow a wider range of parameters. For example, next() is meaningful for generators, iterators on built-in types, user-defined iterators (defined with classes). In [129]: import types In [130]: i=iter([1]) In [131]: type(i) Out[131]: <type 'listiterator'> In [132]: type(i)==types.GeneratorType Out[132]: False In [133]: isinstance(i, types.GeneratorType) Out[133]: False In [134]: i.next Out[134]: <method-wrapper 'next' of listiterator object at 0x20d0050> Function call is valid for functions, bound methods, and instances of any class that defines a __call__() method. Here is a less restrictive LBYL implementation of your function: def execMyFun( f ) : if hasattr(f, 'next') and callable(f.next): return f.next() elif callable(f): return f() else : raise Exception("Invalid type for f : " + type(f) ) Here in an EAFP implementation: def execMyFun( f ) : try: return f.next() except AttributeError: pass try: return f() except TypeError: pass raise Exception("Invalid type for f : " + type(f) ) I think I prefer the LBYL version here, it allows the same values for f and it won't hide AttributeErrors and TypeErrors raised by calling f.next() or f(). Finally you should probably raise TypeError which is "raised when an operation or function is applied to an object of inappropriate type." Kent _______________________________________________ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor