thorwhalen / umpyre

Materials for python coaching
MIT License
1 stars 0 forks source link

Removing methods from a subclass #24

Closed thorwhalen closed 3 years ago

thorwhalen commented 3 years ago

Sometimes I'd like to subclass, but disable or delete some of the methods I don't need, and don't want to have to deal with. If there was only one or two, I'd just include them and overwrite them with a NotImplemented error. But when there's more, I start copy/pasting and have an eery feeling of "there must be a better way".

Here's an example where I'm subclassing deque, and only want append and extend methods.

from collections import deque
from functools import wraps

class InfiniteSeq(deque):
    @wraps(deque)
    def __init__(self, *args, **kwargs):
        super().__init__(self, *args, **kwargs)
        self.max_idx = 0  # should correspond to the number of items added

    def append(self, x) -> None:
        super().append(x)
        self.max_idx += 1

    def extend(self, iterable: Iterable) -> None:
        iterable = list(iterable)
        super().extend(iterable)
        self.max_idx += len(iterable)

for attr in {'appendleft', 'extendleft', 'insert', 'pop', 'popleft', 'remove', 'reverse', 'rotate', 'clear'}:
    delattr(InfiniteSeq, attr)
thorwhalen commented 3 years ago

Asked question here: https://stackoverflow.com/questions/66216789/healthy-ways-disable-delete-methods-in-a-subclass

thorwhalen commented 3 years ago

To transform methods in bulk consider:

from collections import deque
from functools import wraps

class InfiniteSeq(deque):
    @wraps(deque)
    def __init__(self, *args, **kwargs):
        super().__init__(self, *args, **kwargs)
        self.max_idx = 0  # should correspond to the number of items added

    def append(self, x) -> None:
        super().append(x)
        self.max_idx += 1

    def extend(self, iterable: Iterable) -> None:
        iterable = list(iterable)
        super().extend(iterable)
        self.max_idx += len(iterable)

    _locals = locals()
    for _attr in {'appendleft', 'extendleft', 'insert', 'pop', 'popleft', 'remove', 'reverse', 'rotate', 'clear'}:
        _locals[_attr] = decorator(getattr(deque, _attr))
    del _attr, _locals