2

In a class I am writing, one of the member properties is a list:

@property
def address_list(self):
    return self._address_list

@address_list.setter
def address_list(self, addr_list):
    if type(addr_list) is not list:
        return
    self._address_list = addr_list

I want to be able to write a property so if someone wanted to append something onto the list, it would call something like another setter function, but for adding onto the list:

Object.address_list.append(value)

would call something like

@property.appender # I made this line up
def address_list.append(self, value):
    if value >= 0 and value <= 127:
        self._address_list.append(value)

so I could safely append values to my private list. Is something like this possible without having to create a new type of list object?

EDIT: Address list returns a standard python list

sawyermclane
  • 896
  • 11
  • 28

1 Answers1

2

you would need to create a new AddressList class to handle this. something like

class Wrapper(object):
    """Wrapper class that provides proxy access to an instance of some
       internal instance."""
    __wraps__  = None
    __ignore__ = "class mro new init setattr getattr getattribute"
    def __init__(self, obj):
        if self.__wraps__ is None:
            raise TypeError("base class Wrapper may not be instantiated")
        elif isinstance(obj, self.__wraps__):
            self._obj = obj
        else:
            raise ValueError("wrapped object must be of %s" % self.__wraps__)
    # provide proxy access to regular attributes of wrapped object
    def __getattr__(self, name):
        return getattr(self._obj, name)

    # create proxies for wrapped object's double-underscore attributes
    class __metaclass__(type):
        def __init__(cls, name, bases, dct):
            def make_proxy(name):
                def proxy(self, *args):
                    return getattr(self._obj, name)
                return proxy
            type.__init__(cls, name, bases, dct)
            if cls.__wraps__:
                ignore = set("__%s__" % n for n in cls.__ignore__.split())
                for name in dir(cls.__wraps__):
                    if name.startswith("__"):
                        if name not in ignore and name not in dct:
                            setattr(cls, name, property(make_proxy(name)))




class AddressList(Wrapper):
    __wraps__=list
    def append(self,x):
        if 0 <= x <= 127:
            self._obj.append(x)
        else:
            raise ValueError("Cannot append %r"%x)


class MyContainer:
    def __init__(self):
        self.address_list = AddressList([])


x = MyContainer()
x.address_list.append(1)
x.address_list.append(7)
x.address_list.append(-1)

print x.address_list

*note that this answer borrows heavily from https://stackoverflow.com/a/9059858/541038 *

Community
  • 1
  • 1
Joran Beasley
  • 110,522
  • 12
  • 160
  • 179