为什么在Python中使用self时,类传递给在类函数内调用的函数?

时间:2016-07-04 14:20:46

标签: python python-3.x

所以,我有这个代码片段。

class LogObserver(object): 
    def write_log(...):
        self.logger.log(self, level, message, *args, **kwargs)
...

同时查看调试器和错误消息,我注意到变量level包含LogObserver而不是整数。我期待一个整数。

但是,当我从self中移除self.logger.log()时:

self.logger.log(level, message, *args, **kwargs)

level包含整数而不是LogObserver个对象。错误消息也会消失。

这种行为背后的解释是什么?

1 个答案:

答案 0 :(得分:3)

如果调用实例方法( staticmethod或classmethod),则实例将作为第一个参数隐式传递。这就是方法定义将self作为第一个参数的原因;顺便提一下,名称self只是一种惯例。例如,foo.bar()将被翻译为type(foo).bar(foo)

如果显式地将实例作为参数传递,它将像任何其他参数一样传递 - 在隐式传递实例之后。例如,foo.bar(foo)将被翻译为type(foo).bar(foo, foo)

现在,在方法中,self通常是第一个参数。我们假设你已经定义了

class Foo(object):
  def bar(self, other=None):
    pass
foo = Foo()

致电foo.bar()已转换为type(foo).bar(self=foo, other=None)。 同样,foo.bar(foo)已翻译为type(foo).bar(self=foo, other=foo)

因此,当您致电self.logger.log(self, level, message, *args, **kwargs)时,实际上会转换为type(self).logger.log(self=self, level=self, message=level, args=(message,), kwargs={})。因此,level获取对象的实例,即self

请注意,foo.bar()并不总是解析为type(foo).bar(foo) - 只有在{/ 1}}仅在类/类型上定义时才会出现这种情况。但是,bar的传递不会因此而改变。