<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Oct 6, 2014 at 1:42 PM, Andrew Barnert <span dir="ltr"><<a href="mailto:abarnert@yahoo.com.dmarc.invalid" target="_blank">abarnert@yahoo.com.dmarc.invalid</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto"><span class=""><div><br><br>Sent from a random iPhone</div></span><span class=""><div><br>On Oct 6, 2014, at 10:23, Guido van Rossum <<a href="mailto:guido@python.org" target="_blank">guido@python.org</a>> wrote:<br><br></div><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Oct 6, 2014 at 8:07 AM, Andrew Barnert <span dir="ltr"><<a href="mailto:abarnert@yahoo.com.dmarc.invalid" target="_blank">abarnert@yahoo.com.dmarc.invalid</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto"><span><div>On Oct 5, 2014, at 20:04, Guido van Rossum <<a href="mailto:guido@python.org" target="_blank">guido@python.org</a>> wrote:</div><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sun, Oct 5, 2014 at 7:36 PM, Steven D'Aprano <span dir="ltr"><<a href="mailto:steve@pearwood.info" target="_blank">steve@pearwood.info</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Sun, Oct 05, 2014 at 02:43:13PM -0700, Guido van Rossum wrote:<br>
<br>
> An alternative that wouldn't even require a metaclass would be to write a<br>
> helper function that looks the class object up by name after parsing<br>
> __qualname__. There are some limitations to this, e.g. classes defined<br>
> inside functions -- but that's already a suspect pattern anyway.<br>
<br>
I understand that "suspect pattern" doesn't mean "don't ever do this",<br>
but I wonder what aspect of defining classes inside a function is<br>
suspect. I think the suspect part is that each invocation of the<br>
function creates a new class which (at least in the naive case) has the<br>
same name, same functionality, and looks identical to the casual<br>
glance but actually isn't.</blockquote></div></div></div></div></blockquote></span><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> …</blockquote></div></div></div></div></blockquote><span><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">There's<br>
probably also implications for pickling as well. Are these the only<br>
"suspect" parts of defining classes inside functions, or have I missed<br>
something else?<span></span><br></blockquote></div><br></div><div class="gmail_extra">Those (and their variations, e.g. using these in except clauses) are the main concerns; it also generally bothers me when something "smallish" like a function contains something "larger" like a class, especially when the class is substantial. It's another case of "flat is better than nested".<br><br>The only non-evil use of this pattern that I can recall is in unit tests </div></div></div></blockquote><div><br></div></span><div>I agree that returning a class from a function is an uncommon special case, and any code that does so ought to have a good and obvious reason. But to say that such functions are evil doesn't seem right.</div></div></blockquote></div></div></div></div></blockquote><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><div>I didn't say *all* uses (or all uses outside unit tests) are evil. I still maintain that most non-test code doing this has a bad smell and is difficult to maintain. <br></div></div></div></div></div></blockquote><div><br></div></span><div>OK, I think I just misinterpreted you here. If you're just saying that this is enough of a red flag that you need to pause and prove to yourself (and ideally your code's readers) that it's a "necessary evil" whenever you find yourself writing a function that returns a class, then that makes total sense. Apologies.</div></div></blockquote><div><br></div><div>No problem! That's what I meant. (Note also that I didn't threaten to remove the feature. :-)<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto"><span class=""><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto"><div>What about the functional constructors for namedtuple, or the two kinds of enums? Or a custom kind of enum (strings, bitsets, ...), which the PEP specifically suggests building on top of the stdlib support? Or something more inherently dynamic like a bridge library? Even in cases like generating an ORM from a SQL dump or a client from an RPC discovery call, which could be moved to a separate "pre-compilation" phase of building your application, is a function that generates source code for a class less suspect than one that just generates a class?</div></div></blockquote></div><br></div><div class="gmail_extra">How namedtuple is implemented should be nobody's business, except Raymond's, and it certainly isn't a pattern to be recommended. That's why it's in the stdlib -- so you don't have to write such code yourself. </div></div></div></blockquote><div><br></div></span><div><span>Sure, but I don't think you want every bridge library, dynamic RMDB/GUI/RPC/etc. binding library, etc. to be in the stdlib. _Someone_ has to write them, and the fact that Python makes such code writable (if not easy) is a strength of the language.</span></div></div></blockquote><div><br></div><div>Yup. But that code rarely takes the simple form<br><br>def make_a_class(parameters):<br>    ...<br></div><div>    class ClassTemplate:<br></div><div>        def method1(self):<br>            ...<br></div><div>        def method2(self):<br>            ...<br>        ...<br>    ...<br></div><div>    return C<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto"><div><span>Still, I take your point; I wouldn't trust a dynamic binding library that isn't being used by multiple independent projects, because it's so hard to verify by reading that it's gotten all the details right. And a proposal that makes such things slightly easier to write (while still leaving them very hard to get right) probably doesn't add much to the language.</span></div></div></blockquote></div><br></div><div class="gmail_extra">Right.<br clear="all"></div><div class="gmail_extra"><br>-- <br>--Guido van Rossum (<a href="http://python.org/~guido">python.org/~guido</a>)
</div></div>