views:

1159

answers:

3

Hello.

In python it's possible to use '.' in order to access object's dictionary items. For example:

class test( object ) :
  def __init__( self ) :
    self.b = 1
  def foo( self ) :
    pass
obj = test()
a = obj.foo

From above example, having 'a' object, is it possible to get from it reference to 'obj' that is a parent namespace for 'foo' method assigned? For example, to change obj.b into 2?

+6  A: 
Miles
Wow, never heard about im_self O_O. Thanks a lot!
Eye of Hell
Using dir() is a good way to discover things like that: dir(obj.foo)
Miles
But i need to do exactly reverse operation: obj from a :)
Eye of Hell
I mean at the interactive prompt, for learning purposes. You can look at what methods and attributes different kinds of objects have; so if you have an instance method, you can use dir() on it and see if any of the attributes lead you back to the object. And besides, dir(obj.foo) is identical to dir(a).
Miles
+4  A: 

On bound methods, you can use three special read-only parameters:

  • im_func which returns the (unbound) function object
  • im_self which returns the object the function is bound to (class instance)
  • im_class which returns the class of im_self

Testing around:

class Test(object):
    def foo(self):
        pass

instance = Test()
instance.foo          # <bound method Test.foo of <__main__.Test object at 0x1>>
instance.foo.im_func  # <function foo at 0x2>
instance.foo.im_self  # <__main__.Test object at 0x1>
instance.foo.im_class # <__main__.Test class at 0x3>

# A few remarks
instance.foo.im_self.__class__ == instance.foo.im_class # True
instance.foo.__name__ == instance.foo.im_func.__name__  # True
instance.foo.__doc__ == instance.foo.im_func.__doc__    # True

# Now, note this:
Test.foo.im_func != Test.foo # unbound method vs function
Test.foo.im_self is None

# Let's play with classmethods
class Extend(Test):
    @classmethod
    def bar(cls): 
        pass

extended = Extend()

# Be careful! Because it's a class method, the class is returned, not the instance
extended.bar.im_self # <__main__.Extend class at ...>

There is an interesting thing to note here, that gives you a hint on how the methods are being called:

class Hint(object):
    def foo(self, *args, **kwargs):
        pass

    @classmethod
    def bar(cls, *args, **kwargs):
        pass

instance = Hint()

# this will work with both class methods and instance methods:
for name in ['foo', 'bar']:
    method = instance.__getattribute__(name)
    # call the method
    method.im_func(method.im_self, 1, 2, 3, fruit='banana')

Basically, im_self attribute of a bound method changes, to allow using it as the first parameter when calling im_func

NicDumZ
+2  A: 

since python2.6 synonyms for im_self and im_func are __self__ and __func__, respectively. im* attributes are completely gone in py3k. so you would need to change it to:

>> a.__self__
<__main__.test object at 0xb7b7d9ac>
>> a.__self__.b = 2
>> obj.b
2
SilentGhost