Issue
Here is part of code from mmcv (mmcv/runner/base_module.py).
I don't understand how does self(**data)
works.
class BaseDetector(BaseModule, metaclass=ABCMeta):
"""Base class for detectors."""
# ...
def train_step(self, data, optimizer):
losses = self(**data)
loss, log_vars = self._parse_losses(losses)
outputs = dict(
loss=loss, log_vars=log_vars, num_samples=len(data['img_metas']))
return outputs
class BaseModule(nn.Module, metaclass=ABCMeta):
def __init__(self, init_cfg: Optional[dict] = None):
# ...
Tried to find some function like __call__
in the parent class, but it seems not the right direction to go.
Could any one explain why self
could be used as a function?
Solution
This is nothing specific to PyTorch but rather to how Python works.
"Calling" an object is equivalent to calling a special Python function named __call__
. Essentially, this is the function which implements the call behaviour. In your case self(**data)
will call BaseDetector
's __call__
function which has most probably been implemented by one of the parent classes.
Here is a minimal example to understand this behaviour:
class A():
def __call__(self):
return 'hello'
class B(A):
def foo(self):
return self() + ' world'
Initialize a new object from B
:
b = B()
Then let us call the foo
method on b
:
>>> b.foo()
'hello world'
This function has been calling b()
i.e. b.__call__()
:
>>> b() # same as b.__call__()
'hello'
As an additional note, you can explicitly call the implementation of the parent class. This is useful when you need to overload the original implementation in your child's class.
It is done by calling super
:
class A():
def __call__(self):
return 'hello'
class B(A):
def __call__(self):
# calling self() here would create an infinite recursion loop
return super().__call__() + ' world'
Then you can call an instance of B
the same way:
>>> b = B()
>>> b()
'hello world'
Answered By - Ivan
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.