html_url,issue_url,id,node_id,user,created_at,updated_at,author_association,body,reactions,performed_via_github_app,issue https://github.com/pydata/xarray/issues/1080#issuecomment-261144489,https://api.github.com/repos/pydata/xarray/issues/1080,261144489,MDEyOklzc3VlQ29tbWVudDI2MTE0NDQ4OQ==,1217238,2016-11-17T03:22:02Z,2016-11-17T03:22:02Z,MEMBER,"I think we probably need to agree to disagree here. I will update the docs in response to feedback (which is greatly appreciated!) and when I do so I will close out this issue. > Perhaps I will suggest `DataArray.__call__ = DataArray.pipe` (maybe that could be added in xarray ? This seems too magical to me, but you are welcome to make another issue to see what others think. `__call__` is not searchable in the way the `.pipe` is. ","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,187373423 https://github.com/pydata/xarray/issues/1080#issuecomment-259270684,https://api.github.com/repos/pydata/xarray/issues/1080,259270684,MDEyOklzc3VlQ29tbWVudDI1OTI3MDY4NA==,1217238,2016-11-08T21:50:33Z,2016-11-08T21:50:33Z,MEMBER,"> Python's introspection capabilities are powerful enough that users can find out such information. I don't really agree here. Code is read in text form more often than it is interactively explored. At Google, our Python style guide actually prohibits writing import like `from xarray import Dataset`. You have to write `import xarray` or `import xarray as xr` and always use the namespace. > And then there""s also the problem of accessors not being usable in functional programming paradigms. xarray objects are already non-threadsafe, in the same way that the built-in `list` and `dict` are not threadsafe. I don't see how caching attributes changes this. You can choose whether or not to save state on the accessor (and of course, generally it would be better not to). Finally, I'll note that we also have the `.pipe` method (e.g., `array.pipe(square)`), so if you just want functions that you can call with method chaining syntax, you don't even need to write an accessor at all. You are certainly welcome to monkey patch -- that's the Python philosophy, after all -- but I'm not going to recommend it or make it easy. But I would even subclassing before considering monkey patching -- at least then your methods are contained to your own code, instead of contaminating a global namespace. ","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,187373423 https://github.com/pydata/xarray/issues/1080#issuecomment-258680571,https://api.github.com/repos/pydata/xarray/issues/1080,258680571,MDEyOklzc3VlQ29tbWVudDI1ODY4MDU3MQ==,1217238,2016-11-06T13:22:42Z,2016-11-06T13:22:51Z,MEMBER,"> Is it because of namespace growth/conflicts? There are already many methods like diff, any which don't seem particularly more important than others. For instance, ndarray has no diff method yet you implement it. Indeed. My thinking was the `xarray.Dataset` and `xarray.DataArray` are in the ""xarray"" namespace. We allow you to register an extension namespace, but want to keep it well contained and under one attribute, so it's clear(er) to users and developers what is going on, and where the code comes from. A stricter approach would have been to put everything under an attribute just for extensions, e.g., `Dataset.x.namespace` instead of `Dataset.namespace`, but this gets even more cumbersome -- and also conflicts with variables named `x`! > Could you please give some clear arguments why you discourage the use of normal methods? The two arguments listed in the docs don't really make a compelling case against method monkey-patching, because > 1. name clashes can be easily checked for either approach (in either case you just check the existence of a class attribute) I'll add a note about the value of namespaces to the doc. > 1. caching on the dataset sometimes makes no sense and just adds redundancy and complicates the design and registering of extra functionality We could certainly turn this off (optionally) if there are cases where it does the wrong thing. Could you go into this in a little more detail, perhaps with a concrete example? My expectation was that this should have minimal design or performance downsides. ","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,187373423 https://github.com/pydata/xarray/issues/1080#issuecomment-258582609,https://api.github.com/repos/pydata/xarray/issues/1080,258582609,MDEyOklzc3VlQ29tbWVudDI1ODU4MjYwOQ==,1217238,2016-11-05T01:32:02Z,2016-11-05T01:32:02Z,MEMBER,"I don't see a conflict between encouraging accessors and making duplicate methods/functions. If you want duplicate method/functions, you can totally do that on an accessor class: ``` python import functools import xarray @xarray.register_dataarray_accessor('custom') class CustomAccessor(object): def __init__(self, data_array): self._data_array = data_array def patch_custom(func): @functools.wraps(func) def method(accessor, *args, **kwargs): return func(accessor._data_array, *args, **kwargs) setattr(CustomAccessor, func.__name__, method) return func @patch_custom def square(data_array): return data_array ** 2 xarray.DataArray([1, 2, 3], dims='x').custom.square() # # array([1, 4, 9]) # Coordinates: # * x (x) int64 0 1 2 ``` If you really desire, you can even make method-like accessors by adding a `__call__` method, e.g., ``` @xarray.register_dataarray_accessor('square') class Square(object): def __init__(self, data_array): self._data_array = data_array def __call__(self): return self._data_array ** 2 ``` or even simpler ``` @xarray.register_dataarray_accessor('square') def square_accessor(data_array): def square(): return data_array ** 2 return square ``` I would definitely discourage writing too many of such methods, though. Finally, it seems like the simplest solution to your concern about needing methods for `Dataset.apply` would be to register an accessor for `Dataset` as well, with `register_dataset_accessor`. ","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,187373423