2016-07-04 23 views
0

所以,我有这段代码片段。为什么在Python中使用self时,该类传递给在类函数中被调用的函数?

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

展望调试器和错误信息,以及,我注意到,变量level包含LogObserver而不是整数。我期待一个整数。

然而,当我从self.logger.log()除去self像:

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

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

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

+2

我不明白你在问什么。 “自我”就是实例;如果您将其包含在该调用中,则该实例将被传递;如果你删除它,它不会。你的问题是什么? –

+0

'.log'里面的'self'应该指向'LogObserver'中的名为'self.log'的对象,而不是观察者本身。你为什么认为你需要传递外部'self'(或任何显式实例)?你写了那个片段吗?你可以给[mcve]? – jonrsharpe

+1

在第一种情况下,您传入LogObserver。在第二个你不。你期望发生什么? –

回答

3

如果你调用一个实例方法(静态方法或类方法),该实例作为隐含的第一个参数传递。这就是为什么方法定义以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) - 这是如果bar只在类/类型定义只能这样了。但是,self的传递并未因此而改变。

+0

从我的理解来看,这就像'LogObserver'.logger.log(self = self.logger,LogObserver,...)'。但是因为我使用'self',所以'self = self.logger'是隐式定义的。我对吗? –

+1

@ SeanFrancisN.Ballais对于'self = self.logger'的传递,你已经发现了。 *属性*'self.logger'如何解决取决于'logger'是在实例还是类上定义的。它接近'instance .__ dict __('logger',type(instance).__ dict __。get('logger'))',即将首先尝试实例,然后是它的类(包含基类)。 – MisterMiyagi

+0

现在我明白了。感谢您的洞察力。 –

相关问题