How to get the original order of keyword arguments passed to a function call?

Getting the order of the keyword arguments passed through ** kwargs would be extremely useful in the particular project I'm working on. It is about creating a kind of nd numpy array with significant dimensions (now called dimarray), which is especially useful for processing geophysical data.

Now let's say that we have:

import numpy as np
from dimarray import Dimarray   # the handy class I am programming

def make_data(nlat, nlon):
    """ generate some example data
    """
    values = np.random.randn(nlat, nlon)
    lon = np.linspace(-180,180,nlon)
    lat = np.linspace(-90,90,nlat)
    return lon, lat, values

What works:

>>> lon, lat, values = make_data(180,360)
>>> a = Dimarray(values, lat=lat, lon=lon)
>>> print a.lon[0], a.lat[0]
-180.0 -90.0

What not:

>>> lon, lat, data = make_data(180,180) # square, no shape checking possible !
>>> a = Dimarray(values, lat=lat, lon=lon)
>>> print a.lon[0], a.lat[0] # is random 
-90.0, -180.0  # could be (actually I raise an error in such ambiguous cases)

The reason is because the signature of the Dimarray method __init__ (values, **kwargs), and since it kwargsis an unordered dictionary (dict), the best thing it can do is to check for the form values.

Of course, I want it to work for any measurements:

a = Dimarray(values, x1=.., x2=...,x3=...)

**kwargs . , , (values, axes, names, **kwargs) :

a = Dimarray(values, [lat, lon], ["lat","lon"]) 

(ipython), , ( !) python, numpy .

. , , :

import inspect
def f(**kwargs):
    print inspect.stack()[1][4]
    return tuple([kwargs[k] for k in kwargs])

>>> print f(lon=360, lat=180)
[u'print f(lon=360, lat=180)\n']
(180, 360)

>>> print f(lat=180, lon=360)
[u'print f(lat=180, lon=360)\n']
(180, 360)

- , , stack() :

>>> print (f(lon=360, lat=180), f(lat=180, lon=360))
[u'print (f(lon=360, lat=180), f(lat=180, lon=360))\n']
[u'print (f(lon=360, lat=180), f(lat=180, lon=360))\n']
((180, 360), (180, 360))

- , , ? ( ) , , lon=360, lat=180, - , ?

, , python , , (, , !!!).

: https://mail.python.org/pipermail/python-ideas/2011-January/009054.html , ?

, ** kwargs , . - ?

: pandas, , numpy. gitHub.

EDIT: I, dimarray. .

EDIT2: , , Dimarray values . , , , . , , , , names. , ( Dimarray ), python.

3, : kazagistar:

, , name="" units="", , , *args kwargs.

, :

* a:

a = Dimarray(values, lon=mylon, lat=mylat, name="myarray")
a = Dimarray(values, [mylat, mylon], ["lat", "lon"], name="myarray")

* b: kazagistar 2- , **kwargs

a = Dimarray(values, ("lat", mylat), ("lon",mylon), name="myarray")

* c: kazagistar 2- , **kwargs ( , **kwargs names= . )

a = Dimarray(values, lon=mylon, lat=mylat, name="myarray")
a = Dimarray(values, ("lat", mylat), ("lon",mylon), name="myarray")

* d: kazagistar 3- **kwargs

a = Dimarray(values, lon=mylon, lat=mylat, name="myarray")
a = Dimarray(values, [("lat", mylat), ("lon",mylon)], name="myarray")

, ( ?). b) c). , ** kwargs - . , , , , ...

. , , a), b) c) d)!

=====================

EDIT 4: : a)!, from_tuples. . , "x0", "x1" ..... , pandas, . ** kwargs . , .

a = Dimarray(values, lon=mylon, lat=mylat, name="myarray")
a = Dimarray(values, [mylat, mylon], ["lat", "lon"], name="myarray")
a = Dimarray.from_tuples(values, ("lat", mylat), ("lon",mylon), name="myarray")

5: pythonic ?: EDIT 4 api, dimarray, , Dimarray . , .

 from dimarray import dimarray, Dimarray 

 a = dimarray(values, lon=mylon, lat=mylat, name="myarray") # error if lon and lat have same size
 b = dimarray(values, [("lat", mylat), ("lon",mylon)], name="myarray")
 c = dimarray(values, [mylat, mylon, ...], ['lat','lon',...], name="myarray")
 d = dimarray(values, [mylat, mylon, ...], name="myarray2")

:

 e = Dimarray.from_dict(values, lon=mylon, lat=mylat) # error if lon and lat have same size
 e.set(name="myarray", inplace=True)
 f = Dimarray.from_tuples(values, ("lat", mylat), ("lon",mylon), name="myarray")
 g = Dimarray.from_list(values, [mylat, mylon, ...], ['lat','lon',...], name="myarray")
 h = Dimarray.from_list(values, [mylat, mylon, ...], name="myarray")

d) h) "x0", "x1" .., mylat, mylon Axis ( , Axes and Axis , ).

:

class Dimarray(object):
    """ ndarray with meaningful dimensions and clean interface
    """
    def __init__(self, values, axes, **kwargs):
        assert isinstance(axes, Axes), "axes must be an instance of Axes"
        self.values = values
        self.axes = axes
        self.__dict__.update(kwargs)

    @classmethod
    def from_tuples(cls, values, *args, **kwargs):
        axes = Axes.from_tuples(*args)
        return cls(values, axes)

    @classmethod
    def from_list(cls, values, axes, names=None, **kwargs):
        if names is None:
            names = ["x{}".format(i) for i in range(len(axes))]
        return cls.from_tuples(values, *zip(axes, names), **kwargs)

    @classmethod
    def from_dict(cls, values, names=None,**kwargs):
        axes = Axes.from_dict(shape=values.shape, names=names, **kwargs)
        # with necessary assert statements in the above
        return cls(values, axes)

():

def dimarray(values, axes=None, names=None, name=..,units=..., **kwargs):
    """ my wrapper with all fancy options
    """
    if len(kwargs) > 0:
        new = Dimarray.from_dict(values, axes, **kwargs) 

    elif axes[0] is tuple:
        new = Dimarray.from_tuples(values, *axes, **kwargs) 

    else:
        new = Dimarray.from_list(values, axes, names=names, **kwargs) 

    # reserved attributes
    new.set(name=name, units=units, ..., inplace=True) 

    return new

, , - args, . .

. python ?

( )

=====================

(EDIT: , a), b), c), d) ), , :

* a :

def __init__(self, values, axes=None, names=None, units="",name="",..., **kwargs):
    """ schematic representation of Dimarray init method
    """
    # automatic ordering according to values' shape (unless names is also provided)
    # the user is allowed to forget about the exact shape of the array
    if len(kwargs) > 0:
        axes = Axes.from_dict(shape=values.shape, names=names, **kwargs)

    # otherwise initialize from list
    # exact ordering + more freedom in axis naming 
    else:
        axes = Axes.from_list(axes, names)

    ...  # check consistency

    self.values = values
    self.axes = axes
    self.name = name
    self.units = units         

* b) c) :

def __init__(self, values, *args, **kwargs):
    ...

b) , , kwargs, self.__dict__.update(kwargs). .

c) :

def __init__(self, values, *args, **kwargs):
   """ most flexible for interactive use
   """
   # filter out known attributes
   default_attrs = {'name':'', 'units':'', ...} 
   for k in kwargs:
       if k in 'name', 'units', ...:
           setattr(self, k) = kwargs.pop(k)
       else:
           setattr(self, k) = default_attrs[k]

   # same as before
   if len(kwargs) > 0:
       axes = Axes.from_dict(shape=values.shape, names=names, **kwargs)

   # same, just unzip
   else:
       names, numpy_axes = zip(*args)
       axes = Axes.from_list(numpy_axes, names)

, () , name= ", units =" " .

* d: clear __init__

def __init__(self, values, axes, name="", units="", ..., **kwaxes)

.

==========

EDIT, FYI. axes , , dims= labels= . dimarray github. kazagistar.

+4
2

, , , dicionary. ( , collections.OrderedDict ).

, ? :

a = Dimarray(values, 'lat', lat, 'lon', lon)

(, )

a = Dimarray(values, ('lat', lat), ('lon', lon))

( )

a = Dimarray(values, [('lat', lat), ('lon', lon)])

, , . ** kwargs , "", . , , , , + , , .

+3

:

https://github.com/claylabs/ordered-keyword-args

def multiple_kwarguments(first , **lotsofothers):
    print first

    for i,other in lotsofothers.items():
         print other
    return True

multiple_kwarguments("first", second="second", third="third" ,fourth="fourth" ,fifth="fifth")

:

first
second
fifth
fourth
third

orderkwargs

from orderedkwargs import ordered kwargs  
@orderedkwargs  
def mutliple_kwarguments(first , *lotsofothers):
    print first

    for i, other in lotsofothers:
        print other
    return True


mutliple_kwarguments("first", second="second", third="third" ,fourth="fourth" ,fifth="fifth")

:

first
second
third
fourth
fifth

. .

+1

All Articles