如何在python中显式查看“ self”的作用?

时间:2019-03-12 04:17:10

标签: python python-3.x

我读过某个地方,在Python中使用“ 自我”会转换myobject.method (arg1, arg2) 进入MyClass.method(myobject, arg1, arg2)

有人知道我能证明这一点吗? 我只能使用dis.dis查看字节码吗?

2 个答案:

答案 0 :(得分:1)

自我不执行任何操作。 self 仅仅是Python类定义中方法的第一个参数的常规名称。该参数将传递给该类的实例。

本质上,要了解实际情况,您必须了解Python描述符。最好的地方是官方的docs 归根结底,描述符对象是实现__get____set____delete__的对象。这些方法拦截对象属性访问obj.x,对象属性分配obj.x = 42和对象属性删除del obj.x

另外,请查看HOWTO,其中他们展示了Python functions and methods are simply descriptors的方式,并显示了示例Python实现(当然,在CPython中,这是在C中实现的):

class Function(object):
    . . .
    def __get__(self, obj, objtype=None):
        "Simulate func_descr_get() in Objects/funcobject.c"
        if obj is None:
            return self
        return types.MethodType(self, obj)

我们可以“欺骗”并创建我们自己的对象,该对象仅包装一个函数对象,然后看到它起作用。

import types
class Function:
    def __init__(self, func):
        self._func = func
    def __call__(self, *args, **kwargs):
        return self._func(*args, **kwargs)
    def __get__(self, obj, objtype=None):
        "Simulate func_descr_get() in Objects/funcobject.c https://docs.python.org/3/howto/descriptor.html#functions-and-methods"
        if obj is None:
            return self
        else:
            return types.MethodType(self, obj)

class Foo:
   def __init__(self):
       self.foo = 42
   bar = Function(lambda self:
       self.foo ** 2

或者,或者在REPL中:

>>> import types
>>>
>>> class Function:
...     def __init__(self, func):
...         self._func = func
...     def __call__(self, *args, **kwargs):
...         return self._func(*args, **kwargs)
...     def __get__(self, obj, objtype=None):
...         "Simulate func_descr_get() in Objects/funcobject.c https://docs.python.org/3/howto/descriptor.html#functions-and-methods"
...         if obj is None:
...             return self
...         else:
...             return types.MethodType(self, obj)
...
>>> class Foo:
...    def __init__(self):
...        self.foo = 42
...    bar = Function(lambda self:
...        self.foo ** 2
...    )
...
>>> Foo().bar()
1764

这向您展示了“自我”背后的魔力仅仅是函数对象是描述符,它们实现了__get__方法,该方法可以在没有实例的情况下返回函数本身,或者返回绑定第一个参数的方法对象。

答案 1 :(得分:0)

在IDLE中亲自尝试可以帮助您解决此问题:

class MyObject(object):
  def method(self, arg1, arg2):
     print(self)

  @staticmethod
  def static_method(arg1, arg2):
     print(arg1)

my_object = MyObject()
my_object.method(1, 2)
>>> <MyObject at 0x1234>
my_object.static_method(1, 2)
>>> 1

Python不会进行任何转换,它只是将类实例作为第一个参数传递给类方法。在上方,您可以查看是否将方法设为静态(通过@staticmethod装饰器),可以避免使用该额外参数。