<div dir="ltr">The technique Eric suggests is probably better than what I had in mind.  But I was thinking you could have an "inherit" decorator for methods (or for a class as a whole).  It's easy enough for a decorator to attach a `.__contracts__` attribute to either the class or the individual methods.  Then the decorator(s) in the child can simply look through the `.__mro__` to find any such parent contracts.  E.g.:<blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><br></div><div><font face="monospace, monospace">class B(A):</font></div><div><font face="monospace, monospace">    @inherit_invariants</font></div><div><font face="monospace, monospace">    def some_method(self, x: int) -> None:</font></div><div><font face="monospace, monospace">        pass</font></div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="monospace, monospace">    </font></div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="monospace, monospace">    @precondition(lambda x: x=42, inherit_parent=True)</font></div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="monospace, monospace">    def other_method(self, x: int) -> float:</font></div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="monospace, monospace">        return 42/5</font></div></blockquote><font face="arial, helvetica, sans-serif"><div><font face="arial, helvetica, sans-serif"><br></font></div>I'm not writing a library to do this, so you can tweak the API to be different than my example.  But this is already well possible.</font><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">On the broader idea:</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div>Is there any logical or empirical objection that the design-by-contract is not useful and hence does not merit to be introduced into the core language? There is little point in writing a PEP and fleshing out the details if the community will reject it on grounds that design-by-contract by itself is meaningless.</div></blockquote><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">Lots of people have explained this relative to lots of ideas, probably mostly better than I will.  Adding a new feature, even if it is *technically* backwards compatible, has HUGE costs.  All the documentation—the books, articles, blog posts, videos, webinars, tutorials, etc.—about Python has to be updated.  We get a divide between "code that will work in Python 3.9" versus what will run in 3.7.  The cognitive burden of learning Python is increased for everyone in the world (millions of people) because even if they do not use a feature they will encounter code that does.  There is another section of code in the implementation(s) of Python that can potentially have bugs and needs to be maintained by someone.</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">Obviously, design-by-contract is not *meaningless*! It's a specific feature that is relatively well defined as a concept (and precisely defined in regard to Eiffel specifically; but we might not implement those *exact* semantics).  It's also a feature that no languages in particularly widespread use have decided to implement at the language level.  I've chatted with Meyer; he's definitely very smart and definitely strongly opinionated, but I also think he's wrong about the overall importance of this feature versus lots of others.</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">In my mind, this feature doesn't come close to meeting the burden of those high costs listed above (and others I did not mention).  But I don't have any say in what the core developers will do, beyond in that they might be influenced by my opinion here.</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">Yours, David...<br></font><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="monospace, monospace"><br></font></div></blockquote><div><div class="gmail_quote"><div dir="ltr">On Wed, Aug 29, 2018 at 6:41 PM Eric Fahlgren <<a href="mailto:ericfahlgren@gmail.com">ericfahlgren@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div style="color:rgb(0,0,0)"><span style="color:rgb(34,34,34)">On Wed, Aug 29, 2018 at 3:07 PM Marko Ristin-Kaufmann <<a href="mailto:marko.ristin@gmail.com" target="_blank">marko.ristin@gmail.com</a>> wrote:</span></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div>Could you please elaborate a bit? I don't see how the annotations would make the contracts invoked on inheritance. Consider this simple case:<br><pre style="background-color:rgb(255,255,255);color:rgb(0,0,0);font-family:"DejaVu Sans Mono""><font size="2"><span style="color:rgb(0,0,128);font-weight:bold">class </span>A:<br>    <span style="color:rgb(0,0,178)">@icontract.pre</span>(<span style="color:rgb(0,0,128);font-weight:bold">lambda </span>x: x > <span style="color:rgb(0,0,255)">0</span>)<br>    <span style="color:rgb(0,0,128);font-weight:bold">def </span>some_method(<span style="color:rgb(148,85,141)">self</span>, x: <span style="color:rgb(0,0,128)">int</span>)-><span style="color:rgb(0,0,128);font-weight:bold">None</span>:<br>        <span style="color:rgb(0,0,128);font-weight:bold">pass<br></span><span style="color:rgb(0,0,128);font-weight:bold"><br></span><span style="color:rgb(0,0,128);font-weight:bold">class </span>B(A):<br>    <span style="color:rgb(128,128,128);font-style:italic"># Precondition should be inherited here.<br></span><span style="color:rgb(128,128,128);font-style:italic">    </span><span style="color:rgb(0,0,128);font-weight:bold">def </span>some_method(<span style="color:rgb(148,85,141)">self</span>, x: <span style="color:rgb(0,0,128)">int</span>) -> <span style="color:rgb(0,0,128);font-weight:bold">None</span>:<br>        <span style="color:rgb(0,0,128);font-weight:bold">pass</span></font></pre></div><div>You would still need to somehow decorate manually the overridden methods even though you would not specify any new contracts, right? Is there a mechanism in Python that I am not aware of that would allow us to accomplish that?</div></div></div></div></blockquote><div><br></div><div style="color:rgb(0,0,0)">A metaclass does this pretty easily.  I have a thing I wrote years ago called MIS (Multi-Inheritance Safety) that is used to ensure you don't do anything stupid in our physics-modeling database.  The database is a collection of ~200 Python classes/mixins all deriving madly from each other to get various behaviors (Has mass? You'll need this.  Has moments?  You'll need this.  Has physical extent, i.e., can be seen?  You'll need these...).</div><div style="color:rgb(0,0,0)"><br></div><div style="color:rgb(0,0,0)">Anyhow, the basemost class has the metaclass, which traverses all the methods in the subclasses and makes sure you don't have methods with the same name in two distinct superclass trees and such things.  It also forces you to be explicit when you overload a method from a base class (among other things, but this one is easy to illustrate).</div><div style="color:rgb(0,0,0)"><br></div><div style="color:rgb(0,0,0)">class MIS(type):</div><div style="color:rgb(0,0,0)">    def __init__(cls, name, bases, namespace):</div><div style="color:rgb(0,0,0)">        mro = cls.mro()[1:-1]  # All the stuff between new class and 'object'</div><div style="color:rgb(0,0,0)"><div>        for method_name, method in namespace.items():</div><div>            if isinstance(method, executable_types):</div><div>                if not getattr(method, '_its_ok', False):</div><div>                    # Make sure it's not in any baser class.</div><div>                # Could easily check for decorated pre/post properties and copy them...</div><div><br></div><div>def override(func):</div><div>    # Mark the function as a valid override...</div><div>    func._its_ok = True</div><div>    return func</div><div><br></div></div><div style="color:rgb(0,0,0)">class Base(metaclass=MIS):</div><div style="color:rgb(0,0,0)">    def something(self):</div><div style="color:rgb(0,0,0)">        pass</div><div style="color:rgb(0,0,0)"><br></div><div style="color:rgb(0,0,0)">class Derived(Base):</div><div style="color:rgb(0,0,0)">    @override # Signal that this is ok, otherwise we get an error.</div><div style="color:rgb(0,0,0)">    def something(self): ...</div><div style="color:rgb(0,0,0)">       </div></div></div></div>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/codeofconduct/</a><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">Keeping medicines from the bloodstreams of the sick; food <br>from the bellies of the hungry; books from the hands of the <br>uneducated; technology from the underdeveloped; and putting <br>advocates of freedom in prisons.  Intellectual property is<br>to the 21st century what the slave trade was to the 16th.<br></div></div></div></div>