Prev: A link to a collection of tutorials on LISP.
Next: problems getting os.system and wxmenu to read options from afile and then execute
From: Steven W. Orr on 27 Jun 2010 22:09 I need to test an argument for a few different types. I'm calling my function like this arf = MyFunc(list) What I want to do is to test for whether something is a string, tuple, list or function. It's that last one that's causing me a problem. if isinstance(arg, (str, tuple, list)): No problem, but there are a lot of types that the type function returns. If I have a simple function def foo(): pass type(foo) prints out <type 'function'> So, my question is, what value can I use as the 2nd arg to isinstance to see if foo is a function? And while I'm on the subject, what types does isinstance not support? And last, what is the correct way to do it if this is not the right way? TIA (and hoping I'm clear) -- Time flies like the wind. Fruit flies like a banana. Stranger things have .0. happened but none stranger than this. Does your driver's license say Organ ..0 Donor?Black holes are where God divided by zero. Listen to me! We are all- 000 individuals! What if this weren't a hypothetical question? steveo at syslang.net
From: Stephen Hansen on 27 Jun 2010 22:25 On 6/27/10 7:09 PM, Steven W. Orr wrote: > So, my question is, what value can I use as the 2nd arg to isinstance to see if > foo is a function? And while I'm on the subject, what types does isinstance not > support? Does it have to be a function? -- There's quite a few things which are function-y enough that you really should accept them even if they may not be technically a /function/. Like a class instance with the __call__ method defined wrapping a function as a decorator. Or a bound method, really. In Python 2.x, you can use callable(fun) -- that goes away in Py3 though. But personally, I think this is the wrong approach. I'm assuming you need to do some different sort of behavior based on if its a str, tuple or list-- okay. But, personally-- at that point, I would just *assume* the argument is a function. And call it. If it can't be called, its not a functiony-thing. You can either let that traceback propagate, or just raise a TypeError "expected arg to be a string, tuple, list or callable". Then again, similarly I almost never want to test for if somethings a tuple or list. I'd rather use it as a sequence type and see if it works: while there's not as many 'sequency-like-things' out there as there are function-like-things, there's still quite a few. So personally, I'd check if its a string (can it be unicode or regular? If so isinstance(x,basestring)). Then I'd try to use it as a sequence, doing whatever I woulda done with it sequence-like. If that works, great. If not, I'd try to call it. Etc. Then again it does depend on just what you're *doing* with the arg being passed in. -- ... Stephen Hansen ... Also: Ixokai ... Mail: me+list/python (AT) ixokai (DOT) io ... Blog: http://meh.ixokai.io/
From: MRAB on 27 Jun 2010 22:30 Steven W. Orr wrote: > I need to test an argument for a few different types. > > I'm calling my function like this > > arf = MyFunc(list) > > What I want to do is to test for whether something is a string, tuple, list or > function. It's that last one that's causing me a problem. > > if isinstance(arg, (str, tuple, list)): > > No problem, but there are a lot of types that the type function returns. If I > have a simple function > > def foo(): > pass > type(foo) > prints out > <type 'function'> > > So, my question is, what value can I use as the 2nd arg to isinstance to see if > foo is a function? And while I'm on the subject, what types does isinstance not > support? > >>> def foo(): .... pass .... >>> import types >>> dir(types) ['BooleanType', 'BufferType', 'BuiltinFunctionType', 'BuiltinMethodType', 'ClassType', 'CodeType', 'ComplexType', 'DictProxyType', 'DictType', 'DictionaryType', 'EllipsisType', 'FileType', 'FloatType', 'FrameType', 'FunctionType', 'GeneratorType', 'GetSetDescriptorType', 'InstanceType', 'IntType', 'LambdaType', 'ListType', 'LongType', 'MemberDescriptorType', 'MethodType', 'ModuleType', 'NoneType', 'NotImplementedType', 'ObjectType', 'SliceType', 'StringType', 'StringTypes', 'TracebackType', 'TupleType', 'TypeType', 'UnboundMethodType', 'UnicodeType', 'XRangeType', '__builtins__', '__doc__', '__file__', '__name__', '__package__'] >>> isinstance(f, types.FunctionType) True >>> > And last, what is the correct way to do it if this is not the right way? > Why do you want to know what type it is? Do you want to do different things depending on the type? If the same function can return instances of any number of unrelated types/classes, then there's something wrong in your design! (You should also learn what "duck typing" is!) :-)
From: Steven W. Orr on 27 Jun 2010 23:04 On 6/27/2010 10:25 PM, Stephen Hansen wrote: > On 6/27/10 7:09 PM, Steven W. Orr wrote: >> So, my question is, what value can I use as the 2nd arg to isinstance >> to see if >> foo is a function? And while I'm on the subject, what types does >> isinstance not >> support? > > Does it have to be a function? -- There's quite a few things which are > function-y enough that you really should accept them even if they may > not be technically a /function/. Like a class instance with the __call__ > method defined wrapping a function as a decorator. Or a bound method, > really. > > In Python 2.x, you can use callable(fun) -- that goes away in Py3 > though. But personally, I think this is the wrong approach. Ok, you just asked great questions, and your questions were based on what I didn't tell you. I'm trying to teach myself about how __metaclass__ can be used as a substitute for LSD. ;-) So, instead of writing a class that does typechecking on its arguments at instantiation time, I'm writing a metaclass that allows the class to announce what sort of values it specifically will be expecting after instantiation. The model I'm using is something I've found that http://cleverdevil.org/computing/78/ So, the basic idea is >>> class Person(Enforcer): ... name = Field(str) ... age = Field(int) ... ff = Field(function) but there's no factory function called function. Does this help? > > I'm assuming you need to do some different sort of behavior based on if > its a str, tuple or list-- okay. > > But, personally-- at that point, I would just *assume* the argument is a > function. And call it. > > If it can't be called, its not a functiony-thing. You can either let > that traceback propagate, or just raise a TypeError "expected arg to be > a string, tuple, list or callable". > > Then again, similarly I almost never want to test for if somethings a > tuple or list. I'd rather use it as a sequence type and see if it works: > while there's not as many 'sequency-like-things' out there as there are > function-like-things, there's still quite a few. > > So personally, I'd check if its a string (can it be unicode or regular? > If so isinstance(x,basestring)). > > Then I'd try to use it as a sequence, doing whatever I woulda done with > it sequence-like. If that works, great. If not, I'd try to call it. > > Etc. > > Then again it does depend on just what you're *doing* with the arg being > passed in. > -- Time flies like the wind. Fruit flies like a banana. Stranger things have .0. happened but none stranger than this. Does your driver's license say Organ ..0 Donor?Black holes are where God divided by zero. Listen to me! We are all- 000 individuals! What if this weren't a hypothetical question? steveo at syslang.net
From: Stephen Hansen on 27 Jun 2010 23:25
On 6/27/10 8:04 PM, Steven W. Orr wrote: > On 6/27/2010 10:25 PM, Stephen Hansen wrote: >> On 6/27/10 7:09 PM, Steven W. Orr wrote: >>> So, my question is, what value can I use as the 2nd arg to isinstance >>> to see if >>> foo is a function? And while I'm on the subject, what types does >>> isinstance not >>> support? >> >> Does it have to be a function? -- There's quite a few things which are >> function-y enough that you really should accept them even if they may >> not be technically a /function/. Like a class instance with the __call__ >> method defined wrapping a function as a decorator. Or a bound method, >> really. >> >> In Python 2.x, you can use callable(fun) -- that goes away in Py3 >> though. But personally, I think this is the wrong approach. > > Ok, you just asked great questions, and your questions were based on what I > didn't tell you. > > I'm trying to teach myself about how __metaclass__ can be used as a substitute > for LSD. ;-) [snip] Ah. In that case, bearing in mind this won't work for Python 3, I would use callable(). So, isinstance(x, (int, str, tuple)); but don't rely on isinstance for function. Its just not appropriate, almost universally, to really be that specific. When someone esays they want to accept a function, what they *really* mean in my experience is they want some sort of object that you can put ()'s on after, and usually with some sort of agreement: it'll accept X args, and return Y things. You can't readily test for those agreements, but you can test to see if it'll accept ()'s after and be all function-y. Doing callable(ff) will do that for you. -- ... Stephen Hansen ... Also: Ixokai ... Mail: me+list/python (AT) ixokai (DOT) io ... Blog: http://meh.ixokai.io/ P.S. The removal of callable is something I don't understand in Python 3: while generally speaking I do really believe and use duck typing, I too have on occassion wanted to dispatch based on 'is callable? do x'. Sometimes its not convenient to do so via duck typing. Its rare. But it is there. That isinstance()/issubclass got a boost in power with the ABC's and registering, while at the same time the ability to introspect about the function-y callable-y ness of a function was removed? Makes no sense to me. But alas! |