[Python] Alternative to setting self.__class__ to something else?

Discussão em 'Python' iniciado por Stack, Setembro 25, 2024.

  1. Stack

    Stack Membro Participativo

    What's the right way to add a method to any member of a set of sibling instances (i.e. each instance's class inherits from a common base class)?

    The siblings come from fsspec and are out of my control, but it's like this.

    class Base:
    def open(self): pass
    def read(self): pass

    class A(Base):
    def read(self): pass

    class B(Base):
    def read(self): pass


    There could be a C and some plugin might add a D ... these are out of my control. All my code gets is an instance of some subclass of Base.

    My code gets an instance and needs to hand it off to another library expecting an instance of a class inheriting from Base. But I want this instance to have a new feature (not something that would be of general utility outside my code, so no changes to fsspec). In code, something like this.

    with fsspec.open(...) as f: # f is an instance of `A`, `B`, etc.
    g = dunno_what(f) # asking about this part
    dataset = xarray.open_dataset(g) # handing off to xarray


    Now xarray is going to behave differently depending on what g implements, and requires g to be an instance of Base.

    The way I see it, my feature would come as a method of a mixin.

    class Mixin:
    def feature(self): pass


    Then the following appears to achieve my goals but has lots of drawbacks.

    for Item in (A, B):
    # `item` is the `f` in the minimal example above
    item = Item()
    # here's what I've tried, but is advised against
    item.__class__ = type("Item", (item.__class__, Mixin), {})
    # it works though ...
    assert isinstance(item, Base)
    assert item.open.__func__ is Base.open
    assert item.read.__func__ is Item.read
    assert item.feature.__func__ is Mixin.feature


    Assigning to item.__class__ is not for novices, so I am interested in the suggested alternatives given by abarnert (third one is outside of my control):

    • "Use a factory to create an instance of the appropriate class dynamically, instead of creating a base instance and then munging it into a derived one."
    • "Use __new__ or other mechanisms to hook the construction."

    I can't think of how to do either one while still achieving the goals given above as assertions. Thank you for showing me the way!

    Continue reading...

Compartilhe esta Página