ArtsAutosBooksBusinessEducationEntertainmentFamilyFashionFoodGamesGenderHealthHolidaysHomeHubPagesPersonal FinancePetsPoliticsReligionSportsTechnologyTravel
  • »
  • Technology»
  • Computers & Software»
  • Computer Science & Programming»
  • Programming Languages

Starting with Python Introspection and reflection

Updated on October 9, 2012

Introspection, called Reflection in Java is the ability to inspect an object and determine its properties. It can be used to eliminate multiple “if.... then” statements thus making code cleaner, can be used to implement dependency injection (that is deciding the class to use at run or load time) and can eliminate the need to look at source code, saving headaches as some people write source code as compactly and obscurely as possible (I cannot claim to have been free of that fault in the past but nowadays I try to avoid it).

The code here, intended to allow Python programming beginners to get started with introspection, was developed using the Eclipse PyDev plugin for OS X and python 2.6 as supplied by OS X. A basic knowledge of Object orientation and Java Reflection is assumed.

Please note this is not production code and you use it at your own risk


Simple Sample Class

# the module was called refletionexperiments

class reflector(object):
    '''
    classdocs
    '''
    params = list();

    def __init__(self,params):
        '''
        Constructor
        '''
 
    def greet(self,greeting):
        print greeting;
        return "greeting done";
    
    def times2(self,x):
        return x+x;

Code sample using introspection

'''
Created on Jun 27, 2012

@author: alex
'''
from experiments import reflectionexperiments
from inspect import *

# given a full classname returns an object that can be used as the class
# Taken from 
# http://stackoverflow.com/questions/452969/does-python-have-an-equivalent-to-java-class-forname
# Some comments added 
#
# Note this returns a class and you have to instantiate it
def get_class( kls ):
    parts = kls.split('.')
# the class name - to the left of the first dot
    module = ".".join(parts[:-1])
# import the module just discovered. 
    m = __import__( module )
# recursively create the object. 
    for comp in parts[1:]:
        m = getattr(m, comp)           
    return m

if __name__ == '__main__':
    
    print "Creating test object";
    paramlist = {"test":"a"};
    testval= reflectionexperiments.reflector(paramlist); 
    print ;
    print "listing object attributes"   
    print "\t"  + str(dir(testval));


    print "\nFinding the greet method the hard way";
# NB  methods are first class objects in Python  
    for name in dir(testval) :       
#        print name;
        if(name == "greet"):
            print  "\t\t" + getattr(testval,name)("\tthis is the greeting string followed by return value of greet");

    print "\nFinding the greet method the easy way";
    result = getattr(testval,"greet")("printed in greet method");

    print "\t  value returned from greet is:  " + str(result);
# this is a compact but inscrutable  and inflexible way of doing this
    print "\nprinting list of methods";
    methodList = [method for method in dir(testval) if callable(getattr(testval, method))]
    print "\t" + str(methodList);
    
# lets do it a sensible way

#    methods =list();
    print "\nprinting methods as found";   
    for thing in dir(testval):
        temp = getattr(testval, thing);
        if callable(temp):
            print "\t" + thing + ":-" + str(dir(temp));
            
    print "\nFinding the first meaningful parameter of the greet  method";

# get the name of the first parameter of the greet method other than "self"    
    result = getattr(testval, "greet");
    print    "\t" + result.func_code.co_varnames[1];
    
    print "\nFinding the first meaningful parameter of the greet  method using inspect";
# another way to do it but less flexible and with unwanted confusing brackets

    print  "\t" + (getargspec(result)[0])[1];
    
    
#    Now try to instantiate an object using strings
    print "\nInstantiating and calling method by name given package";
    test2 = getattr(reflectionexperiments,"reflector")("");
    test2.greet("\tInstantiating & calling method by name given package");
    
    print "\nInstantiating class by name and calling method  by name";
    test3 = get_class("reflectionexperiments.reflector")("");
    
    test3.greet("\tInstantiating class by name & calling method  by name");
  

Useful Keywords

The dir() keyword

This is where most people start. It returns a sorted list of attribute names for any object passed to it. If no object is specified, dir() returns the names in the current scope.

The programmer defined methods come after all the internal attributes which are surrounded by underscores.

It is worth experimenting with dir() on various objects including your own classes and methods

getattr

Where dir() simply lists all the attributes of an object, getattr returns an object that is an attribute of its argument.

A method is a callable object and, if retrieved by getattr() must be followed by a parameter list if you want to use it. The predicate for testing whether the code is a methods is callable(object)

These two keywords should get you through 90% of the cases where introspection helps. Sometimes however you want to know the parameters of a method and this can be done in more than one way

Finding the parameters of an object

The first method is to my mind the simplest, at least for beginners:

# get the name of the first parameter of the greet method other than "self"

result = getattr(testval, "greet");

print result.func_code.co_varnames[1];

func_code.co_varnames is a list of the method's parameter names. element zero is "self"

frominspect import *

print (getargspec(result)[0])[1];

prints out “greeting”

Here getargspec(result)[0] is the list of parameter names and as before the zeroth element is “self”. This has more parentheses than I like: any more and I may as well re-learn LISP, which for a contractor is almost useless, since almost no clients use it.

Dynamic instantiation

There is no built in method equivalent to Java's Class.forName() method and the method get_class in the sample code was taken from a stackOverflow post. The sample code shows how to use it with the class reflectionexperiments.reflector

The Wrap

I have presented a Python introspection starter kit which I think will cover most of the situations where the average developer will need it. The keyword dir(object) lets you find the attributes of an object, callable(object) tells you whether an attribute is a method, type(object) tells you the type of the object and object.func_code.co_varnames lists all a method's parameters.

Further reading

Comments

    0 of 8192 characters used
    Post Comment

    • AlexK2009 profile image
      Author

      AlexK2009 5 years ago from Edinburgh, Scotland

      Yes, I think I had to do something like that to get MongoDB to play nicely with Python in Eclipse. I have not heard of virtualenv.

    • derek gulbranson profile image

      derek gulbranson 5 years ago from San Francisco

      Yea, I'm not sure how well iPython plays with Eclipse. It is a setuptools install though, so you can always test things out using virtualenv and then just delete it if something screws up.

    • AlexK2009 profile image
      Author

      AlexK2009 5 years ago from Edinburgh, Scotland

      Thanks for that. I will have to look into it. I do not know how well the tools you mention work in Eclipse, and now I have pydev working with MongoDB I am reluctant to risk screwing up ... errr I mean changing the system.

    • derek gulbranson profile image

      derek gulbranson 5 years ago from San Francisco

      If you're really interested in getting into Python's introspection capabilities I'd suggest installing ipython and ipdb. Instead of having to type dir() around everything you can just press tab. Also you don't mention pdb.set_trace() which is my most frequently used introspection tool. I have "import ipdb; ipdb.set_trace()" as a tab trigger in TextMate so I can quickly throw a breakpoint in anywhere.

    working

    This website uses cookies

    As a user in the EEA, your approval is needed on a few things. To provide a better website experience, hubpages.com uses cookies (and other similar technologies) and may collect, process, and share personal data. Please choose which areas of our service you consent to our doing so.

    For more information on managing or withdrawing consents and how we handle data, visit our Privacy Policy at: "https://hubpages.com/privacy-policy#gdpr"

    Show Details
    Necessary
    HubPages Device IDThis is used to identify particular browsers or devices when the access the service, and is used for security reasons.
    LoginThis is necessary to sign in to the HubPages Service.
    Google RecaptchaThis is used to prevent bots and spam. (Privacy Policy)
    AkismetThis is used to detect comment spam. (Privacy Policy)
    HubPages Google AnalyticsThis is used to provide data on traffic to our website, all personally identifyable data is anonymized. (Privacy Policy)
    HubPages Traffic PixelThis is used to collect data on traffic to articles and other pages on our site. Unless you are signed in to a HubPages account, all personally identifiable information is anonymized.
    Amazon Web ServicesThis is a cloud services platform that we used to host our service. (Privacy Policy)
    CloudflareThis is a cloud CDN service that we use to efficiently deliver files required for our service to operate such as javascript, cascading style sheets, images, and videos. (Privacy Policy)
    Google Hosted LibrariesJavascript software libraries such as jQuery are loaded at endpoints on the googleapis.com or gstatic.com domains, for performance and efficiency reasons. (Privacy Policy)
    Features
    Google Custom SearchThis is feature allows you to search the site. (Privacy Policy)
    Google MapsSome articles have Google Maps embedded in them. (Privacy Policy)
    Google ChartsThis is used to display charts and graphs on articles and the author center. (Privacy Policy)
    Google AdSense Host APIThis service allows you to sign up for or associate a Google AdSense account with HubPages, so that you can earn money from ads on your articles. No data is shared unless you engage with this feature. (Privacy Policy)
    Google YouTubeSome articles have YouTube videos embedded in them. (Privacy Policy)
    VimeoSome articles have Vimeo videos embedded in them. (Privacy Policy)
    PaypalThis is used for a registered author who enrolls in the HubPages Earnings program and requests to be paid via PayPal. No data is shared with Paypal unless you engage with this feature. (Privacy Policy)
    Facebook LoginYou can use this to streamline signing up for, or signing in to your Hubpages account. No data is shared with Facebook unless you engage with this feature. (Privacy Policy)
    MavenThis supports the Maven widget and search functionality. (Privacy Policy)
    Marketing
    Google AdSenseThis is an ad network. (Privacy Policy)
    Google DoubleClickGoogle provides ad serving technology and runs an ad network. (Privacy Policy)
    Index ExchangeThis is an ad network. (Privacy Policy)
    SovrnThis is an ad network. (Privacy Policy)
    Facebook AdsThis is an ad network. (Privacy Policy)
    Amazon Unified Ad MarketplaceThis is an ad network. (Privacy Policy)
    AppNexusThis is an ad network. (Privacy Policy)
    OpenxThis is an ad network. (Privacy Policy)
    Rubicon ProjectThis is an ad network. (Privacy Policy)
    TripleLiftThis is an ad network. (Privacy Policy)
    Say MediaWe partner with Say Media to deliver ad campaigns on our sites. (Privacy Policy)
    Remarketing PixelsWe may use remarketing pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to advertise the HubPages Service to people that have visited our sites.
    Conversion Tracking PixelsWe may use conversion tracking pixels from advertising networks such as Google AdWords, Bing Ads, and Facebook in order to identify when an advertisement has successfully resulted in the desired action, such as signing up for the HubPages Service or publishing an article on the HubPages Service.
    Statistics
    Author Google AnalyticsThis is used to provide traffic data and reports to the authors of articles on the HubPages Service. (Privacy Policy)
    ComscoreComScore is a media measurement and analytics company providing marketing data and analytics to enterprises, media and advertising agencies, and publishers. Non-consent will result in ComScore only processing obfuscated personal data. (Privacy Policy)
    Amazon Tracking PixelSome articles display amazon products as part of the Amazon Affiliate program, this pixel provides traffic statistics for those products (Privacy Policy)