如何在Python中获取对象的父命名空间?
在Python中,我们可以用“.”来访问对象的字典项。比如说:
class test( object ) :
def __init__( self ) :
self.b = 1
def foo( self ) :
pass
obj = test()
a = obj.foo
根据上面的例子,假设我们有一个叫'a'的对象,能不能从这个对象中获取到'obj'的引用呢?'obj'是'foo'方法所在的父命名空间。比如说,我们想把obj.b的值改成2,这样可以吗?
3 个回答
8
从Python 2.6开始,im_self
和im_func
这两个词的同义词分别是__self__
和__func__
。在Python 3中,im*
这些属性完全不再使用了。所以你需要把它们改成:
>> a.__self__
<__main__.test object at 0xb7b7d9ac>
>> a.__self__.b = 2
>> obj.b
2
17
在绑定的方法中,你可以使用三个特殊的只读参数:
- im_func:这个参数返回的是未绑定的函数对象。
- im_self:这个参数返回的是这个函数绑定的对象,也就是类的实例。
- im_class:这个参数返回的是im_self所属于的类。
测试一下:
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 ...>
这里有个有趣的地方,能给你一些关于方法如何被调用的提示:
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')
基本上,绑定方法的im_self属性会发生变化,以便在调用im_func时可以把它作为第一个参数使用。
14
Python 2.6+(包括Python 3)
你可以使用__self__
属性来获取与某个方法绑定的实例。
>> a.__self__
<__main__.test object at 0x782d0>
>> a.__self__.b = 2
>> obj.b
2
Python 2.2+(仅限Python 2.x)
你也可以使用im_self
属性,但这个方法在Python 3中不兼容。
>> a.im_self
<__main__.test object at 0x782d0>