Just for investigation sake, I'm trying to simulate OO-inheritance. (*) What did I do?
I decided that objects would be dictionaries and methods would be procedures stored in the object. A class is just a procedure that creates such object-dictionary. So far so good. Trouble arrived when I decided to have inheritance. The problem might related to the lexical-nature of closures, but I'm not sure. (*) A problem Say I have a Counter-creating object procedure and a Car-creating object procedure. Cars want to track how many times they park, so they inherit a counter. --8<---------------cut here---------------start------------->8--- def Car(maker = None, color = None): o = inherit(Object(), Counter()) o["maker"] = maker o["color"] = color o["speed"] = 0 --8<---------------cut here---------------end--------------->8--- What Object() does is just to return a dictionary. What inherit() does is just to merge the two dictionaries into a single one (to be used by the Car procedure). This didn't come out as I expected, though. Let me show you step-by-step where the problem is. First, here's a counter in action. >>> c1 = Counter() >>> c1["inc"]()["inc"]() {'id': <function Object.<locals>.id at 0x0000016547C648B0>, 'n': 2, [...]} >>> c1["n"] 2 That's good and expected: I incremented it twice. But look what happens with a Car's counter. >>> c = Car() >>> c = Car() >>> c {'id': <function Object.<locals>.id at 0x0000016547C64B80>, 'n': 0, 'inc': <function Counter.<locals>.inc at 0x0000016547C64C10>, 'dec': <function Counter.<locals>.dec at 0x0000016547C64CA0>, 'maker': None, 'color': None, 'speed': 0, 'accelerate': <function Car.<locals>.accelerate at 0x0000016547C64AF0>, 'park': <function Car.<locals>.park at 0x0000016547C64D30>} >>> c["inc"]() {'id': <function Object.<locals>.id at 0x0000016547C64B80>, 'n': 1, 'inc': <function Counter.<locals>.inc at 0x0000016547C64C10>, 'dec': <function Counter.<locals>.dec at 0x0000016547C64CA0>} We can see something got incremented! But... >>> c["n"] 0 Indeed, what got incremented is the dictionary attached to the /inc/ procedure of the Counter closure, so it's that dictionary that's being mutated. My /inherit/ procedure is not able to bring that procedure into the Car dictionary. Is that at all possible somehow? Alternatively, how would you do your toy oop-system? (*) Full code below from random import random def Object(): myid = random() def id(): return myid return { "id": id } def inherit(o, parentObject): o.update(parentObject) return o def Counter(begin_at = 0): o = Object() o["n"] = begin_at def inc(): nonlocal o o["n"] += 1 return o o["inc"] = inc def dec(): nonlocal o o["n"] -= 1 return o o["dec"] = dec return o def Car(maker = None, color = None): o = inherit(Object(), Counter()) o["maker"] = maker o["color"] = color o["speed"] = 0 def accelerate(speed): nonlocal o print(f"Car-{o['id']()}: accelerating to {speed}...") o["speed"] = speed return o o["accelerate"] = accelerate def park(): nonlocal o o["speed"] = 0 o["parked"] = True o["inc"]() print(f"Car-{o['id']()}: parked! ({o['n']} times)") return o o["park"] = park return o def tests(): c1 = Counter() c2 = Counter(100) c1["inc"]()["inc"]() c2["dec"]()["dec"]()["dec"]() print("c1 is 2:", c1["n"]) print("c2 is 97:", c2["n"]) car1 = Car("VW", "Red") car1["accelerate"](100) print("speed is 100:", car1["speed"]) car2 = Car("Ford", "Black") car2["accelerate"](120)["park"]() car2["accelerate"](50)["park"]() print("has parked 2 times:", car2["n"]) -- https://mail.python.org/mailman/listinfo/python-list