[Python-ideas] Composition over Inheritance

Soni L. fakedme+py at gmail.com
Sat Oct 28 22:13:15 EDT 2017

On 2017-10-29 12:05 AM, Soni L. wrote:
> On 2017-10-28 11:57 PM, Chris Angelico wrote:
>> On Sun, Oct 29, 2017 at 12:46 PM, Soni L. <fakedme+py at gmail.com> wrote:
>>> But you should be able to do things like
>>> car = object()
>>> car[Engine] = SimpleEngine()
>>> car.[Engine].kickstart() # calls kickstart method with an instance of
>>> SimpleEngine as `self`/first argument and `car` as second argument.
>>> # etc
>>> Which your decorator-based approach quite obviously doesn't let you.
>> I think I follow what you're trying to do here. You want to have a way
>> to refer to a subobject while letting it know about the parent. We
>> already have something like that: when you call a function that was
>> attached to a class, it gets to know which instance of that class you
>> used to locate that function. Maybe there's a way to use descriptor
>> protocol for this too?
>> class SimpleEngine:
>>      def kickstart(self, caller):
>>          """*boot* Engine starts"""
>> class Car:
>>      Engine = magic(SimpleEngine)
>> car = Car()
>> When you look up car.Engine, it remembers a reference to car. Then you
>> look up any callable from there, and it automatically provides an
>> additional parameter. I'm not sure how the details would work, but in
>> theory, this should be possible, right?
> And how do you make the object creation so cheap to the point where 
> it's actually practical? (quick question: does Python use a single 
> opcode and an optimized codepath for method calls, or does it always 
> create a method wrapper, even for immediate o.m() calls? If it's the 
> latter then yeah I guess there's no reason for new syntax because it's 
> not gonna be significantly slower than what we currently have...)

Hmm thinking about it some more, this whole "magic()" thing is still bad.

Replace class Car with:

class Car:
# or something like that

and use it as:

car = Car()
car[Engine] = GasEngine() # please use the actual type instead of a 
stringy type for this.
car[Engine].kickstart() # kickstart gets the car as second argument.

And to have all cars have engines, you'd do:

class Car:
   def __init__(self, ???):
     self[Engine] = GasEngine()

car = Car()
car[Engine].kickstart() # kickstart gets the car as second argument.

And if you can't do that, then you can't yet do what I'm proposing, and 
thus the proposal makes sense, even if it still needs some refining...

>> ChrisA
>> _______________________________________________
>> Python-ideas mailing list
>> Python-ideas at python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/

More information about the Python-ideas mailing list