views:

92

answers:

4

I have a list of variables.. inside the list are strings, numbers, and class objects. I need to perform logic based on each different type of data. I am having trouble detecting class objects and branching my logic at that point.

if(type(lists[listname][0]).__name__ == 'str'): # <--- this works for strings
elif(type(lists[listname][0]).__name__ == 'object'): <--- this does not work for classes

in the second line of code above, the name variable contains "Address" as the class name. I was hoping it would contain "class" or "object" so I could branch my program. I will have many different types of objects in the future, so it's a bit impractical to perform logic on every different class name, "Address" "Person" etc

please let me know if my question needs clarification.

thanks!!

+1  A: 

I think you want the isinstance function.

if isinstance(o, ClassName):

However, you'll need to first verify that o is an object, you can use type for that.

Lars Wirzenius
thanks, I got a bit further in my app using this.
djmc
+3  A: 

FYI: it also makes a difference if its a new-style class or not:

# python
type(1).__name__
'int'
type('1').__name__
'str'
class foo(object):
  pass
type(foo()).__name__
'foo'
class bar:
  pass
type(bar()).__name__
'instance'

If you can make sure they're all new-style classes, your method will determine the real type. If you make them old-style, it'll show up as 'instance'. Not that I'm recommending making everything all old-style just for this.

However, you can take it one step further:

type(bar().__class__).__name__
'classobj'
type(foo().__class__).__name__
'type'

And always look for 'classobj' or 'type'. (Or the name of the metaclass, if it has one.)

eruciform
ok thanks, I think I understand all these examples. I'ld rather not look for the metaclass because I dont always know what it will be. I was hoping to find a way to detect the base object consistently
djmc
no problem, lemme know if you need anything else.
eruciform
A: 

If you are only interested in handling two types specifically, you could test for them explicitly using isinstance and then handle the leftovers:

import numbers

for item in list:
    if isinstance(item, basestring): # (str, unicode)
        do_string_thing(item)
    elif isinstance(item, numbers.Real): # (int, float, long)
        do_number_thing(item)
    else:
        do_object_thing(item)
AdmiralNemo
Can someone explain why this was down-voted? I feel like it would be useful for myself and other readers to understand what was wrong with my suggestion.
AdmiralNemo
Some people consider isinstance() a tool of last resort. See http://www.canonical.org/~kragen/isinstance/ for the rationale.
Russell Borogove
According to PEP 8, "object type comparisons should always use isinstance() instead of comparing types directly."
AdmiralNemo
Yes, isinstance() is better than comparing types, but it's worse than polymorphism.
Russell Borogove
+2  A: 

It's common in Python to use exception handling to decide which code path to take; inspecting the exact type of an object (with isinstance()) to decide what to do with it is discouraged.

For example, say that what you want to do is, if it's a string, print it in "title case", and if it's an object, you want to call a particular method on it. So:

try:
    # is it an object with a particular method?
    lists[listname][0].particularMethod()
except AttributeError:
    # no, it doesn't have particularMethod(), 
    # so we expect it to be a string; print it in title case
    print lists[listname][0].title()
Russell Borogove
+1 Good advice! Type inspecting should be avoided in python even more than in some other languages, so that any compatible object can be used. Python does not define interfaces, because any object should be usable in any place if it implements required methods.
zvonimir
ok I guess I can do this here. it's not really a concern for this app, but for future reference is there a performance concern with using exception handling in this way?
djmc
Not a major concern. If you were doing this kajillions of times, you could create a class that inherits from str and implements particularMethod(), and use instances of that class in your list instead of str; then you just call particularMethod() on everything.
Russell Borogove