This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author alexey-muranov
Recipients VA, alexey-muranov, gvanrossum, ncoghlan, r.david.murray, serhiy.storchaka
Date 2019-05-07.07:40:02
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1557214803.15.0.915604364824.issue32768@roundup.psfhosted.org>
In-reply-to
Content
Here is a use case for writable bases:

https://stackoverflow.com/q/56007866

class Stateful:
    """
    Abstract base class for "stateful" classes.

    Subclasses must implement InitState mixin.
    """

    @staticmethod
    def __new__(cls, *args, **kwargs):
        super_new = super(__class__, __class__).__new__

        # XXX: see https://stackoverflow.com/a/9639512
        class CurrentStateProxy(cls.InitState):
            @staticmethod
            def _set_state(state_cls=cls.InitState):
                __class__.__bases__ = (state_cls,)

        class Eigenclass(CurrentStateProxy, cls):
            @staticmethod
            def __new__(cls, *args, **kwargs):
                cls.__new__ = None  # just in case
                return super_new(cls, *args, **kwargs)

        return Eigenclass(*args, **kwargs)

class StatefulThing(Stateful):
    class StateA:
        """First state mixin."""

        def say_hello(self):
            print("Hello!")
            self.hello_count += 1
            self._set_state(self.StateB)
            return True

        def say_goodbye(self):
            print("Another goodbye?")
            return False

    class StateB:
        """Second state mixin."""

        def say_hello(self):
            print("Another hello?")
            return False

        def say_goodbye(self):
            print("Goodbye!")
            self.goodbye_count += 1
            self._set_state(self.StateA)
            return True

    # This one is required by Stateful.
    class InitState(StateA):
        """Third state mixin -- the initial state."""

        def say_goodbye(self):
            print("Why?")
            return False

    def __init__(self):
        self.hello_count = self.goodbye_count = 0

    def say_hello_followed_by_goodbye(self):
        self.say_hello() and self.say_goodbye()

# ----------
# ## Demo ##
# ----------
if __name__ == "__main__":
    t1 = StatefulThing()
    t2 = StatefulThing()
    print("> t1, say hello:")
    t1.say_hello()
    print("> t2, say goodbye:")
    t2.say_goodbye()
    print("> t2, say hello:")
    t2.say_hello()
    print("> t1, say hello:")
    t1.say_hello()
    print("> t1, say hello followed by goodbye:")
    t1.say_hello_followed_by_goodbye()
    print("> t2, say goodbye:")
    t2.say_goodbye()
    print("> t2, say hello followed by goodbye:")
    t2.say_hello_followed_by_goodbye()
    print("> t1, say goodbye:")
    t1.say_goodbye()
    print("> t2, say hello:")
    t2.say_hello()
    print("---")
    print( "t1 said {} hellos and {} goodbyes."
           .format(t1.hello_count, t1.goodbye_count) )
    print( "t2 said {} hellos and {} goodbyes."
           .format(t2.hello_count, t2.goodbye_count) )

    # Expected output:
    #
    #     > t1, say hello:
    #     Hello!
    #     > t2, say goodbye:
    #     Why?
    #     > t2, say hello:
    #     Hello!
    #     > t1, say hello:
    #     Another hello?
    #     > t1, say hello followed by goodbye:
    #     Another hello?
    #     > t2, say goodbye:
    #     Goodbye!
    #     > t2, say hello followed by goodbye:
    #     Hello!
    #     Goodbye!
    #     > t1, say goodbye:
    #     Goodbye!
    #     > t2, say hello:
    #     Hello!
    #     ---
    #     t1 said 1 hellos and 1 goodbyes.
    #     t2 said 3 hellos and 2 goodbyes.
History
Date User Action Args
2019-05-07 07:40:03alexey-muranovsetrecipients: + alexey-muranov, gvanrossum, ncoghlan, r.david.murray, serhiy.storchaka, VA
2019-05-07 07:40:03alexey-muranovsetmessageid: <1557214803.15.0.915604364824.issue32768@roundup.psfhosted.org>
2019-05-07 07:40:03alexey-muranovlinkissue32768 messages
2019-05-07 07:40:02alexey-muranovcreate