[Python-ideas] Classes inside functions [was Re: Add __parent__ to all classes, functions, and modules]

Guido van Rossum guido at python.org
Tue Oct 7 02:39:41 CEST 2014


On Mon, Oct 6, 2014 at 1:42 PM, Andrew Barnert <
abarnert at yahoo.com.dmarc.invalid> wrote:

>
>
> Sent from a random iPhone
>
> On Oct 6, 2014, at 10:23, Guido van Rossum <guido at python.org> wrote:
>
> On Mon, Oct 6, 2014 at 8:07 AM, Andrew Barnert <
> abarnert at yahoo.com.dmarc.invalid> wrote:
>
>> On Oct 5, 2014, at 20:04, Guido van Rossum <guido at python.org> wrote:
>>
>> On Sun, Oct 5, 2014 at 7:36 PM, Steven D'Aprano <steve at pearwood.info>
>> wrote:
>>
>>> On Sun, Oct 05, 2014 at 02:43:13PM -0700, Guido van Rossum wrote:
>>>
>>> > An alternative that wouldn't even require a metaclass would be to
>>> write a
>>> > helper function that looks the class object up by name after parsing
>>> > __qualname__. There are some limitations to this, e.g. classes defined
>>> > inside functions -- but that's already a suspect pattern anyway.
>>>
>>> I understand that "suspect pattern" doesn't mean "don't ever do this",
>>> but I wonder what aspect of defining classes inside a function is
>>> suspect. I think the suspect part is that each invocation of the
>>> function creates a new class which (at least in the naive case) has the
>>> same name, same functionality, and looks identical to the casual
>>> glance but actually isn't.
>>
>>>>
>> There's
>>> probably also implications for pickling as well. Are these the only
>>> "suspect" parts of defining classes inside functions, or have I missed
>>> something else?
>>>
>>
>> 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".
>>
>> The only non-evil use of this pattern that I can recall is in unit tests
>>
>>
>> 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.
>>
>
> 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.
>
>
> 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.
>

No problem! That's what I meant. (Note also that I didn't threaten to
remove the feature. :-)


>
> 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?
>>
>
> 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.
>
>
> 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.
>

Yup. But that code rarely takes the simple form

def make_a_class(parameters):
    ...
    class ClassTemplate:
        def method1(self):
            ...
        def method2(self):
            ...
        ...
    ...
    return C

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.
>

Right.

-- 
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20141006/864eb7b0/attachment.html>


More information about the Python-ideas mailing list