Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting var._attrs = None creates an empty dictionary? #9560

Closed
allen-adastra opened this issue Sep 30, 2024 · 6 comments
Closed

Setting var._attrs = None creates an empty dictionary? #9560

allen-adastra opened this issue Sep 30, 2024 · 6 comments

Comments

@allen-adastra
Copy link

What is your issue?

If I do the following in repl, I get the weird behavior (described in comments).

>> import xarray as xr
>> import numpy as np
>> foo=xr.Variable(('x',), np.ones(10))
>> foo._attrs = None
>> print(foo._attrs) # Gives a None
>> foo
>> print(foo._attrs) # Gives a {}

Wondering what might be the cause of this? I know I am not using it as intended; this is for the xarray_jax experiment.

@shoyer would be good to get your perspective

@allen-adastra allen-adastra added the needs triage Issue that has not been reviewed by xarray team member label Sep 30, 2024
Copy link

welcome bot commented Sep 30, 2024

Thanks for opening your first issue here at xarray! Be sure to follow the issue template!
If you have an idea for a solution, we would really welcome a Pull Request with proposed changes.
See the Contributing Guide for more.
It may take us a while to respond here, but we really value your contribution. Contributors like you help make xarray better.
Thank you!

@keewis
Copy link
Collaborator

keewis commented Sep 30, 2024

Variable (or rather, its base class NamedArray) uses xarray.core.formatting.array_repr to format the array, which accesses the attrs property to format the attributes:

@property
def attrs(self) -> dict[Any, Any]:
"""Dictionary of local attributes on this NamedArray."""
if self._attrs is None:
self._attrs = {}
return self._attrs
Since _attrs is None at that point, it is replaced by an empty dict.

@keewis keewis removed the needs triage Issue that has not been reviewed by xarray team member label Sep 30, 2024
@allen-adastra
Copy link
Author

Gotcha, if this is expected behavior, then perhaps in the context of xarray_jax the following is the solution

def _flatten_variable(
    v: xarray.Variable,
) -> Tuple[Tuple[jax.typing.ArrayLike], Tuple[Hashable, ...]]:
    children = (v._data,)
    aux = (
        v._dims,
        # Xarray will sometimes turn None into empty dictionaries. To maintain consistent tree structures, we convert None to empty dictionaries.
        # https://github.com/pydata/xarray/issues/9560
        {} if v._attrs is None else v._attrs,
    )
    return children, aux

@keewis
Copy link
Collaborator

keewis commented Sep 30, 2024

also, interestingly, if you look at the setter you'll notice that we're storing None instead of an empty dict:

@attrs.setter
def attrs(self, value: Mapping[Any, Any]) -> None:
self._attrs = dict(value) if value else None

@shoyer
Copy link
Member

shoyer commented Sep 30, 2024

aux = (

I would suggest using public APIs to side-step Xarray's caching layer is possible, e.g., v.data, v.dims, v.attrs.

@allen-adastra
Copy link
Author

aux = (

I would suggest using public APIs to side-step Xarray's caching layer is possible, e.g., v.data, v.dims, v.attrs.

Nice, seems to work for .attrs. I've made a list of the places where the public API works and does not work on flattening (seems to be .data, .coords and .indexes that cause problems) allen-adastra/xarray_jax#14

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants