Conseguir espacio de nombres de los padres del objeto en Python?
-
11-09-2019 - |
Pregunta
En Python es posible utilizar ''. con el fin de acceder a los elementos del diccionario de objetos. Por ejemplo:
class test( object ) :
def __init__( self ) :
self.b = 1
def foo( self ) :
pass
obj = test()
a = obj.foo
Desde arriba ejemplo, tener 'un' objeto, es posible obtener de ella la referencia a 'obj' que es un espacio de nombres para los padres 'foo' método asignado? Por ejemplo, para cambiar obj.b en 2?
Solución
Python 2.6+ (incluyendo Python 3)
Puede utilizar la propiedad __self__
de un salto método para acceder a la instancia que el método está destinado a.
>> a.__self__
<__main__.test object at 0x782d0>
>> a.__self__.b = 2
>> obj.b
2
Python 2.2 + (2.x Python solamente)
También puede utilizar la propiedad im_self
, pero esto no es compatible con versiones futuras Python 3.
>> a.im_self
<__main__.test object at 0x782d0>
Otros consejos
En métodos consolidados, se pueden utilizar tres parámetros especiales de sólo lectura:
- im_func que devuelve el (no unido) objeto de función
- im_self que devuelve el objeto de la función está obligado a (instancia de clase)
- im_class que devuelve la clase de im_self
Pruebas en torno a:
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 ...>
Hay una cosa interesante señalar aquí, que da una idea de cómo están siendo llamados los métodos:
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')
Básicamente, im_self atributo de un salto cambios de método, para permitir su uso como el primer parámetro al llamar im_func
desde sinónimos python2.6 para im_self
y im_func
son __self__
y __func__
, respectivamente. atributos im*
hayan desaparecido por completo en py3k. por lo que tendría que cambiarlo a:
>> a.__self__
<__main__.test object at 0xb7b7d9ac>
>> a.__self__.b = 2
>> obj.b
2