1
\$\begingroup\$

I am building a list of Python objects that I use fairly regularly that have a length property, (len, 'len') and I was trying to determine the best way to simplify the type/class formatter that the object uses. For example: type([]), returns "< type 'list'>" and type(collections.Counter()) returns "< class 'collections.Counter'> "

I had assumed that the formatter that was used could be accessed simply and the extraneous information removed to facility a particular documentation format that I prefer. In this situation, I had hoped to be able to remove '< type ... >' or '< class ... >' from the resultant output. The kludge that I have come up with entails parsing the string into its components and returning the portion I want. To ensure generality, for objects that I may not currently use, I had hoped for a better solution.

Insights regarding options to this issue, or more general comments would be appreciated. The line in question is flagged with a comment. Apologies, if I am not supposed to included doc information with posted scripts.

"""
Script:   empty_tests.py
Modified: 2015-05-25
Purpose:
  checks on objects that I use, that have a __len__ property
Notes:
- collections.OrderedDictionary and other classes in collections behave
  in a similar fashion
- for NumPy arrays, use size property rather than __len__
"""
import numpy as np
import collections
c0 = collections.Counter()
c1 = collections.Counter([0])
objs = [ [],[1],(),(1),{},{1:"one"},"","1",None,True,1,False,0,c0,c1 ]
is_empty = [ True  if not i else False for i in objs ]
t = [ type(i).__name__ for i in objs ]            # correct based on comment
#t = [str(type(i)).split("\'")[1] for i in objs ] # line in question
print("\n{:<15} {:<6} {:<10}".format("Object","Empty","Type"))
for i in range(len(objs)):
    print("{:<15} {:<6} {:<10s}".format(objs[i],str(is_empty[i]),t[i]))

Output with the above...the commented out line worked

Object          Empty  Type      
[]              True   list      
[1]             False  list      
()              True   tuple     
1               False  int       
{}              True   dict      
{1: 'one'}      False  dict      
                True   str   
.... etc   

I have tried ....

>>> type([])
<type 'type'>
>>> repr(type([]))
<type 'list'>"
>>> str(type([]))
<type 'list'>"
>>> print str(type([])), repr(type([]))
<type 'list'> <type 'list'>
>>>

EDIT the "name" property wasn't listed where I thought it would be, so if the object has a "format" property, check there.

>>> help(type(object).__format__)
Help on method_descriptor:
__format__(...)
    default object formatter
>>> dir(type(object).__format__)
    ['__call__', '__class__', '__delattr__', '__doc__', '__format__',
     '__get__', '__getattribute__', '__hash__', '__init__', '__name__', 
     '__new__', '__objclass__', '__reduce__', '__reduce_ex__', '__repr__', 
     '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
    >>> 
\$\endgroup\$
  • 1
    \$\begingroup\$ I still don't understand what you are trying to do here. Are you trying to find the name of an object's type? What's wrong with type(obj).__name__? \$\endgroup\$ – Gareth Rees May 28 '15 at 11:03
  • \$\begingroup\$ @Gareth your edited comment has sent me in the right direction...it is buried in dir(object.__format__) I was looking in dir(object) for magic methods. I will edit the code to reflect this. Post this as an answer especially where this is documented, I looked for the obvious and didn't find it. Must have been looking in the wrong place \$\endgroup\$ – NaN May 28 '15 at 11:17
  • 1
    \$\begingroup\$ You shouldn't rely on dir to show you all the special methods ("The resulting list is not necessarily complete"). The right place to look is the Data model section of the Python Language Reference. \$\endgroup\$ – Gareth Rees May 28 '15 at 11:22
  • \$\begingroup\$ Excellent Gareth...I have edited the question so those that follow don't waste the time that I did finding the now obvious. \$\endgroup\$ – NaN May 28 '15 at 11:28
1
\$\begingroup\$

This was answered in comments, but for completeness:

  1. The name of a class is given by its __name__ attribute.

  2. It's not a good idea to rely on dir to show you all the special methods and attributes. If you read the documentation you'll see that it says:

    The resulting list is not necessarily complete.

    The place to look for documentation on special methods is the Data model section of the Python Language Reference.

  3. Python 3.3 added __qualname__, which gives the qualified name, which is more informative than __name__ for nested class definitions.

  4. __name__ doesn't include the module name, so collections.Counter.__name__ is just "Counter". If you want to prepend the module name, find it using the __module__ attribute.

  5. True if not i else False is a long-winded way to write not i.

  6. If possible, iterate over objects, not over indexes. Instead of:

    is_empty = [ True  if not i else False for i in objs ]
    t = [ type(i).__name__ for i in objs ]
    for i in range(len(objs)):
        print("{:<15} {:<6} {:<10s}".format(objs[i],str(is_empty[i]),t[i]))
    

    write:

    for obj in objs:
        print("{!r:15} {!r:6} {:10}".format(obj, not obj, type(obj).__name__))
    
\$\endgroup\$
  • \$\begingroup\$ Many thanks for the additional tips. I will have to keep an eye on # 4 in particular. \$\endgroup\$ – NaN May 28 '15 at 13:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.