Description
It's impossible to use needle.autograd.Tensor as type hints for functions under needle.init.
For example executing import needle as ndl in jupyter notebook fails with following error: AttributeError: module 'needle' has no attribute 'Tensor' if init.py contains following function:
import needle as ndl
def rand(*shape, low=0.0, high=1.0, device=None, dtype="float32", requires_grad=False) -> ndl.Tensor:
""" Generate random numbers uniform between low and high """
device = ndl.cpu() if device is None else device
array = device.rand(*shape) * (high - low) + low
return ndl.Tensor(array, device=device, dtype=dtype, requires_grad=requires_grad)
However, import needle as ndl works fine if there is no type hint for return value in init.py function:
import needle as ndl
def rand(*shape, low=0.0, high=1.0, device=None, dtype="float32", requires_grad=False):
""" Generate random numbers uniform between low and high """
device = ndl.cpu() if device is None else device
array = device.rand(*shape) * (high - low) + low
return ndl.Tensor(array, device=device, dtype=dtype, requires_grad=requires_grad)
The reason is that:
__init__.py imports autograd.Tensor before init module:
from .autograd import Tensor, cpu, all_devices
from . import ops
from .ops import *
from . import init
from . import data
from . import nn
from . import optim
- import of
autograd.Tensor leads to a subsequent import of init module because autograd.py contains following line:
by the way, relative import would be much clear in this case: from . import init. but that's not the issue
- when
init.py is imported by autograd.py, function signatures inside init.py are analyzed.
type hint def rand(...) -> ndl.Tensor leads to an error AttributeError: module 'needle' has no attribute 'Tensor'
because the process of importing autograd in not finished yet.
on import, only function signatures are analyzed. it allows to use ndl.Tensor inside function body (as is right now). the reason, I guess, is when functions are executed, all imports (including needle.autograd.Tensor) are alredy resolved.
To wrap up, it is impossible to use ndl.Tensor as type hints in init.py because of the current order of imports:
__init__.py -> autograd.py -> init.py
Solution
Solution is to:
- change the order of imports in
__init.py__ to import init earlier than autograd:
from . import init
from .autograd import Tensor, cpu, all_devices
from . import ops
from .ops import *
from . import data
from . import nn
from . import optim
- and to replace "global" import in
init.py to a relative one:
replace
with
from .autograd import Tensor, cpu
Description
It's impossible to use
needle.autograd.Tensoras type hints for functions underneedle.init.For example executing
import needle as ndlin jupyter notebook fails with following error:AttributeError: module 'needle' has no attribute 'Tensor'ifinit.pycontains following function:However,
import needle as ndlworks fine if there is no type hint for return value ininit.pyfunction:The reason is that:
__init__.pyimportsautograd.Tensorbeforeinitmodule:autograd.Tensorleads to a subsequent import ofinitmodule becauseautograd.pycontains following line:from . import init. but that's not the issueinit.pyis imported byautograd.py, function signatures insideinit.pyare analyzed.type hint
def rand(...) -> ndl.Tensorleads to an errorAttributeError: module 'needle' has no attribute 'Tensor'because the process of importing
autogradin not finished yet.on import, only function signatures are analyzed. it allows to use
ndl.Tensorinside function body (as is right now). the reason, I guess, is when functions are executed, all imports (includingneedle.autograd.Tensor) are alredy resolved.To wrap up, it is impossible to use
ndl.Tensoras type hints ininit.pybecause of the current order of imports:__init__.py -> autograd.py -> init.pySolution
Solution is to:
__init.py__to importinitearlier thanautograd:init.pyto a relative one:replace