Resets an attribute (or adds a new attribute) to be lazily-evaluated.

def _reset_attr(self, name, func=None, doc=None, preload=False):
        "Resets an attribute (or adds a new attribute) to be lazily-evaluated."

        keys = set(self)
        if name not in keys:
            try:
                data, funcs = zip(*[
                    (
                        (
                            key, (
                                getattr(self._attr_data_, key)
                                if hasattr(self._attr_data_, key)
                                else None
                            )
                        ),
                        (
                            key, (
                                getattr(self._attr_func_, key)
                                if hasattr(self._attr_func_, key)
                                else None
                            )
                        ),
                    )
                    for key in keys
                ])

                keys.add(name)
                self._attr_data_ = keys
                self._attr_func_ = keys

                [
                    setattr(self._attr_data_, key,  value)
                    for key, value in data
                    if value is not None
                ]
                [
                    setattr(self._attr_func_, key,  value)
                    for key, value in funcs
                    if value is not None
                ]

            except ValueError:
                keys.add(name)
                self._attr_data_ = keys
                self._attr_func_ = keys

        if hasattr(self._attr_data_, name):
            delattr(self._attr_data_, name)

        if func is not None:
            setattr(self._attr_func_, name, func)

        elif hasattr(self._attr_func_, name):
            delattr(self._attr_func_, name)

        self._set_attr(name, doc, preload)