How can I make an alias to a non-function member attribute in a Python class?

后端 未结 6 1869
Happy的楠姐
Happy的楠姐 2021-02-01 05:05

I\'m in the midst of writing a Python library API and I often run into the scenario where my users want multiple different names for the same functions and variables.

If

6条回答
  •  名媛妹妹
    2021-02-01 06:00

    You could use some of ideas shown in the ActiveState Python recipe titled Caching and aliasing with descriptors. Here's a concise version of the code shown there which provides the functionality you seek.

    Edit: A class containing Alias attributes could be made to automatically delete any associated target attributes when you del one (and vice-versa). The code for my answer now illustrates one easy way this could be done using a convenient class decorator which adds a custom __delattr__() to do the specialized deletion management when attribute Alias's could be involved.

    class Alias(object):
        """ Descriptor to give an attribute another name. """
        def __init__(self, name):
            self.name = name
        def __get__(self, inst, cls):
            if inst is None:
                return self  # a class attribute reference, return this descriptor
            return getattr(inst, self.name)
        def __set__(self, inst, value):
            setattr(inst, self.name, value)
        def __delete__(self, inst):
            delattr(inst, self.name)
    
    
    def AliasDelManager(cls):
        """ Class decorator to auto-manage associated Aliases on deletion. """
        def __delattr__(self, name):
            """ Deletes any Aliases associated with a named attribute, or
                if attribute is itself an Alias, deletes the associated target.
            """
            super(cls, self).__delattr__(name) # Use base class' method.
            for attrname in dir(self):
                attr = getattr(cls, attrname)
                if isinstance(attr, Alias) and attr.name == name:
                    delattr(cls, attrname)
    
        setattr(cls, '__delattr__', __delattr__)
        return cls
    
    
    if __name__=='__main__':
        @AliasDelManager
        class Dummy(object):
            def __init__(self):
                self.x = 17
            xValue = Alias('x')  # create an Alias for attr 'x'
    
        d = Dummy()
        assert d.x == 17
        assert d.xValue == 17
        d.x = 23
        assert d.xValue == 23
        d.xValue = 1492
        assert d.x == 1492
        assert d.x is d.xValue
        del d.x  # should also remove any associated Aliases
        assert 'xValue' not in dir(d)
        print('done - no exceptions were raised')
    
    

提交回复
热议问题