Re: Multiple inheritance and a broken super() chain

2023-07-03 Thread Mats Wichmann via Python-list

On 7/3/23 12:13, Mats Wichmann via Python-list wrote:

To natter on a bit, and possibly muddy the waters even further...


Now, as I see it, from the super()'s point of view, there are two
inheritance chains, one starting at Left and the other at Right. But
*Right.__init__()* is called twice.
No: each class has just a single inheritance chain, built up when the 
class object is constructed, to avoid going insane. Yes, the chain for 
Left and for Right are different, but you're not instantiating *either* 
of those classes when you make a Bottom, so they don't matter here. 
You're just filling out a Bottom: it looks for init, finds it, and so 
would stop hunting - but then the super() call there sends it to the 
next class object in the chain to look for the method you told it to 
(also init), where it would stop since it found it, except you sent it 
on with another super(), and so on.  Python is a bit... different :) 
(compared to other languages with class definitions)


--
https://mail.python.org/mailman/listinfo/python-list


Re: Multiple inheritance and a broken super() chain

2023-07-03 Thread Chris Angelico via Python-list
On Tue, 4 Jul 2023 at 03:39, Peter Slížik via Python-list
 wrote:
>
> Hello.
>
> The legacy code I'm working with uses a classic diamond inheritance. Let me
> call the classes *Top*, *Left*, *Right*, and *Bottom*.
> This is a trivial textbook example. The classes were written in the
> pre-super() era, so all of them initialized their parents and Bottom
> initialized both Left and Right in this order.
>
> The result was expected: *Top* was initialized twice:
>
> Top.__init__() Left.__init__() Top.__init__() Right.__init__()
> Bottom.__init__()

What happens when Top is initialized twice? This seems like a problem
waiting to happen, and when you moved to using super(), you more than
likely simplified things and fixed things.

There are not two instances of Top to be initialized, only one.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multiple inheritance and a broken super() chain

2023-07-03 Thread Mats Wichmann via Python-list

On 7/3/23 12:01, Richard Damon via Python-list wrote:

On 7/3/23 1:38 PM, Peter Slížik via Python-list wrote:

Hello.

The legacy code I'm working with uses a classic diamond inheritance. 
Let me

call the classes *Top*, *Left*, *Right*, and *Bottom*.
This is a trivial textbook example. The classes were written in the
pre-super() era, so all of them initialized their parents and Bottom
initialized both Left and Right in this order.

The result was expected: *Top* was initialized twice:

Top.__init__() Left.__init__() Top.__init__() Right.__init__()
Bottom.__init__()

Now I replaced all parent init calls with *super()*. After this, Top was
initialized only once.

Top.__init__() Right.__init__() Left.__init__() Bottom.__init__()

But at this point, I freaked out. The code is complex and I don't have 
the
time to examine its inner workings. And before, everything worked 
correctly
even though Top was initialized twice. So I decided to break the 
superclass

chain and use super() only in classes inheriting from a single parent. My
intent was to keep the original behavior but use super() where 
possible to

make the code more readable.

class Top:
def __init__(self):
print("Top.__init__()")

class Left(Top):
def __init__(self):
super().__init__()
print("Left.__init__()")

class Right(Top):
def __init__(self):
super().__init__()
print("Right.__init__()")

class Bottom(Left, Right):
def __init__(self):
Left.__init__(self) # Here I'm calling both parents manually
Right.__init__(self)
print("Bottom.__init__()")

b = Bottom()


The result has surprised me:

Top.__init__() Right.__init__() Left.__init__() Top.__init__()
Right.__init__() Bottom.__init__()

Now, as I see it, from the super()'s point of view, there are two
inheritance chains, one starting at Left and the other at Right. But
*Right.__init__()* is called twice. What's going on here?

Thanks,
Peter


Because the MRO from Bottom is [Bottom, Left, Right, Top] so super() in 
Left is Right. It doesn't go to Top as the MRO knows that Right should 
go to Top, so Left needs to go to Right to init everything, and then

Bottom messes things up by calling Right again.


And you can see this a little better in your toy example by using begin 
*and* end prints in your initializers.


Also, you might find that because of the MRO, super() in your Bottom 
class would actually give you what you want.


And if not sure, print out Bottom.__mro__



--
https://mail.python.org/mailman/listinfo/python-list


Re: Multiple inheritance and a broken super() chain

2023-07-03 Thread Richard Damon via Python-list

On 7/3/23 1:38 PM, Peter Slížik via Python-list wrote:

Hello.

The legacy code I'm working with uses a classic diamond inheritance. Let me
call the classes *Top*, *Left*, *Right*, and *Bottom*.
This is a trivial textbook example. The classes were written in the
pre-super() era, so all of them initialized their parents and Bottom
initialized both Left and Right in this order.

The result was expected: *Top* was initialized twice:

Top.__init__() Left.__init__() Top.__init__() Right.__init__()
Bottom.__init__()

Now I replaced all parent init calls with *super()*. After this, Top was
initialized only once.

Top.__init__() Right.__init__() Left.__init__() Bottom.__init__()

But at this point, I freaked out. The code is complex and I don't have the
time to examine its inner workings. And before, everything worked correctly
even though Top was initialized twice. So I decided to break the superclass
chain and use super() only in classes inheriting from a single parent. My
intent was to keep the original behavior but use super() where possible to
make the code more readable.

class Top:
def __init__(self):
print("Top.__init__()")

class Left(Top):
def __init__(self):
super().__init__()
print("Left.__init__()")

class Right(Top):
def __init__(self):
super().__init__()
print("Right.__init__()")

class Bottom(Left, Right):
def __init__(self):
Left.__init__(self) # Here I'm calling both parents manually
Right.__init__(self)
print("Bottom.__init__()")

b = Bottom()


The result has surprised me:

Top.__init__() Right.__init__() Left.__init__() Top.__init__()
Right.__init__() Bottom.__init__()

Now, as I see it, from the super()'s point of view, there are two
inheritance chains, one starting at Left and the other at Right. But
*Right.__init__()* is called twice. What's going on here?

Thanks,
Peter


Because the MRO from Bottom is [Bottom, Left, Right, Top] so super() in 
Left is Right. It doesn't go to Top as the MRO knows that Right should 
go to Top, so Left needs to go to Right to init everything, and then 
Bottom messes things up by calling Right again.


--
Richard Damon

--
https://mail.python.org/mailman/listinfo/python-list


Multiple inheritance and a broken super() chain

2023-07-03 Thread Peter Slížik via Python-list
Hello.

The legacy code I'm working with uses a classic diamond inheritance. Let me
call the classes *Top*, *Left*, *Right*, and *Bottom*.
This is a trivial textbook example. The classes were written in the
pre-super() era, so all of them initialized their parents and Bottom
initialized both Left and Right in this order.

The result was expected: *Top* was initialized twice:

Top.__init__() Left.__init__() Top.__init__() Right.__init__()
Bottom.__init__()

Now I replaced all parent init calls with *super()*. After this, Top was
initialized only once.

Top.__init__() Right.__init__() Left.__init__() Bottom.__init__()

But at this point, I freaked out. The code is complex and I don't have the
time to examine its inner workings. And before, everything worked correctly
even though Top was initialized twice. So I decided to break the superclass
chain and use super() only in classes inheriting from a single parent. My
intent was to keep the original behavior but use super() where possible to
make the code more readable.

class Top:
def __init__(self):
print("Top.__init__()")

class Left(Top):
def __init__(self):
super().__init__()
print("Left.__init__()")

class Right(Top):
def __init__(self):
super().__init__()
print("Right.__init__()")

class Bottom(Left, Right):
def __init__(self):
Left.__init__(self) # Here I'm calling both parents manually
Right.__init__(self)
print("Bottom.__init__()")

b = Bottom()


The result has surprised me:

Top.__init__() Right.__init__() Left.__init__() Top.__init__()
Right.__init__() Bottom.__init__()

Now, as I see it, from the super()'s point of view, there are two
inheritance chains, one starting at Left and the other at Right. But
*Right.__init__()* is called twice. What's going on here?

Thanks,
Peter
-- 
https://mail.python.org/mailman/listinfo/python-list


[Python-announce] [Release] Kedro 0.18.11 

2023-07-03 Thread Juan Luis Cano via Python-announce-list
Hi all,

It fills us with astronomical joy to announce the release of Kedro 0.18.11! 

Kedro is an open source, orchestrator-agnostic Python framework for creating 
reproducible, maintainable and modular data science code. It reduces technical 
debt when moving prototypes into production by providing a declarative data 
catalog, a solid project template, plumbing for creating data pipelines, and 
more. It features a rich ecosystem of plugins and third-party datasets and is 
currently an incubation-stage project of the LF AI & Data Foundation.

You can install it using pip or conda/[micro]mamba:

```
pip install kedro==0.18.11
conda/[micro]mamba install kedro=0.18.11 --channel conda-forge
```

In this release, we added added a new `databricks-iris` official starter and 
significantly improved the documentation around Databricks deployments. We also 
fixed some bugs around micropackaging and remote datasets, updated the 
documentation for Prefect 2.0, and deprecated some class names.

You can read the full release notes online:

https://github.com/kedro-org/kedro/blob/main/RELEASE.md#release-01811

If you want to know more, you can watch our recent workshop “Refactor your 
Jupyter notebooks using Kedro ” on YouTube:

https://youtu.be/qClSGY6B0r0

Follow us on the Fediverse and join our community in Slack:

https://social.lfx.dev/@kedro
https://slack.kedro.org/

Happy pipelining!

--
Cano Rodríguez, Juan Luis
Principal Product Manager & Lead Developer Advocate
QuantumBlack, AI by McKinsey
Pronouns: he/him/his
M +34 686 75 72 97


+=+
This email is confidential and may be privileged. If you have received 
it in error, please notify us immediately, delete the email, and do not 
copy it, disclose its contents or use it for any purpose.
+=+
___
Python-announce-list mailing list -- python-announce-list@python.org
To unsubscribe send an email to python-announce-list-le...@python.org
https://mail.python.org/mailman3/lists/python-announce-list.python.org/
Member address: arch...@mail-archive.com