所以,我有这个代码片段。
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
个对象。错误消息也会消失。
这种行为背后的解释是什么?
答案 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
的传递不会因此而改变。