Chris Angelico <ros...@gmail.com>: > On Fri, Mar 7, 2014 at 10:53 AM, Marko Rauhamaa <ma...@pacujo.net> wrote: >> class MyStateMachine: >> def __init__(self): >> sm = self >> >> class IDLE: >> def ding(self): >> sm.open_door() >> sm.state = AT_DOOR() > > Yeah, that's an extremely unusual way to do things. Why keep on > instantiating objects when you could just reference functions?
That's not crucial. Even if the state objects were instantiated and inner classes not used, you'd get the same circularity: class State: def __init__(self, sm): self.sm = sm class Idle(State): def ding(self): self.sm.open_door() self.sm.state = self.sm.AT_DOOR class AtDoor(state): ... class MyStateMachine: def __init__(self): self.IDLE = Idle(self) self.AT_DOOR = AtDoor(self) ... self.state = self.IDLE The closure style is more concise and to the point and might perform no worse. > Nope; certainly not with closures. I do a whole lot of event-driven > programming (usually in Pike rather than Python, but they work the > same way in this), and there's no reference loop. Properly-done > event-driven programming should have two basic states: a reference > from some invisible thing that can trigger the event (eg a GUI widget) > to a callable, and a reference from that callable to its state. Once > the trigger is gone, the callable is dropped, its state is dropped, > and everything's cleaned up. You don't usually need a reference inside > the function to that function. I'm more familiar with networking. If you need a timer, you need to be able to start it so you need a reference to it. Ok, maybe you instantiate a new timer each time, but you may need to cancel the timer so starting the timer gives you a ticket you can use for canceling. Similarly, you need a socket (wrapper) to signal an I/O state change, and you also need to be able to close the socket at a bare minimum. The task scheduling service (asyncio has one) collects thunks that refer to your objects and your objects have a reference to the task scheduling service to be able to schedule new tasks. > Don't forget, a closure need only hang onto the things it actually > uses. It doesn't need all its locals. More importantly, there's nothing bad in circularity. No need to avoid it. No need to cut cords. Marko -- https://mail.python.org/mailman/listinfo/python-list