Dynamically creating descriptors

Hi folks, I’ve got a subclass of numpy array that keeps track of the labels of the axes. E.g.

arr = AxesArray(np.arange(4).reshape(2,2), {"ax_time": 0, "ax_coord": 1})
arr.ax_time == 0  # true
arr.n_time == 2

However, when slicing changes the dimension of the array, I need to reassign the axes. So I implemented descriptors for ax_time and ax_coord (and ax_spatial/ax_sample), and now:

arr[1,:].ax_coord == 0  # true
arr.n_time == 1

However, some people want to use ax_feature instead of ax_coord, which means that the axis attributes have to be determined at instantiation. I’m having trouble assigning these dynamically, e.g.:

class AxisName:
    def __set_name__(self, owner, name):
        self.public_name = name
        self.private_name = '_' + name

    def __get__(self, obj, objtype=None):
        return getattr(obj, self.private_name)

    def __set__(self, obj, value):
        setattr(obj, self.private_name, value)

class Foo:

    def __init__(self, axes):
        for ax_name, axis in axes.items():
            desc = AxisName()
            desc.__set_name__(self, ax_name)
            desc.__set__(self, axis)
            setattr(self, ax_name, desc) 

temp = Foo({"ax_time": 0, "ax_spatial": [1, 2]})

# <__main__.AxisName at 0x7f4a25ff5ff0>

This took a second to figure out, but makes sense: the Descriptor tutorial says that __getattribute__ checks class variables to determine if the attribute is a descriptor. I tried adding these names to the class:

Foo.ax_time = AxisName()
# AttributeError: AxisName object has no attribute 'private_name"

Ok so I must need to rerun __set_name__. But rewinding a bit and setting the name yields the same result:

desc = temp.ax_time
Foo.ax_time = AxisName()
desc.__set_name__(temp, "ax_time")
# AttributeError: 'AxisName' object has no attribute 'private_name

So I know there’s an option to have a single descriptor, axes, and to handle temp.ax_whateverr via __getattr__. But is there a way to properly assign descriptors dynamically? Am I misunderstanding something about owner, __set_name__, and how descriptors are created?