Получение родительского пространства имен объекта в python? - PullRequest
9 голосов
/ 05 июня 2009

В питоне можно использовать '.' для доступа к элементам словаря объекта. Например:

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

Из приведенного выше примера, имея объект 'a', можно ли получить из него ссылку на 'obj', который является родительским пространством имен для назначенного метода 'foo'? Например, чтобы изменить obj.b на 2?

Ответы [ 3 ]

17 голосов
/ 05 июня 2009

В связанных методах вы можете использовать три специальных параметра только для чтения:

  • 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 голосов
/ 05 июня 2009

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>
7 голосов
/ 05 июня 2009

, поскольку синонимами python2.6 для im_self и im_func являются __self__ и __func__ соответственно. im* атрибуты полностью исчезли в py3k. поэтому вам нужно изменить его на:

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