[Python-ideas] Multiple arguments for decorators

Andrew Barnert abarnert at yahoo.com
Tue Dec 1 04:01:05 EST 2015


On Nov 30, 2015, at 21:28, Kevin Modzelewski <kmod at dropbox.com> wrote:
> 
> Hmm I could have done a bit better with my example.  class defs can work with any callable as a "metaclass", so creating an actual metaclass was overkill:
> 
> def property_wrapper(name, bases, attrs):
>     return property(attrs.get('get'), attrs.get('set'), attrs.get('del'), attrs.get('__doc__'))
> 
> class Foo(object):
>     class myprop(metaclass=property_wrapper):
>         def get(self):
>             return 1
>         def set(self, v):
>             pass
>         __doc__ = 1

But even this is still more complicated than just changing the property type's initializer to take a class instead of a bunch of functions (that is, making property a normal class decorator instead of making it a weird multiple-function decorator and then writing a separate wrapper that lets you pass a class as if it were a normal class decorator)?

And again, what's the benefit from this extra complexity? Unless you have a whole lot of decorators written that all need this exact same transformation, you're just abstracting out an arbitrary part of the logic that doesn't seem to fit any natural grain.

> I wasn't suggesting it for performance reasons, just that there's already an API for "call a function with the locals defined in this scope" that we can use directly, rather than using a different wrapper of the underlying API (aka class creation).  But I think from a readability standpoint it's much nicer to wrap a normal classdef with a "@make_property" decorator rather than doing it via a metaclasss.  I think this could be different if there was a simpler way to use a metaclass (especially, a way that wasn't so class-related).  Here's an example of what it could look like:
> 
> scope(property_wrapper) myprop:
>   def get(self):
>     return 1

That's still a lot less readable than this:

    @property
    class myprop:
        def get(self):
             return 1

> The thing that's nice is that "scope(X) Y" can be just a simple transformation to "class Y(metaclass=X)".  Anyway, I'm not trying to seriously suggest this as the way to go, but just trying to say that if you want to apply a function to the locals defined in a scope, that feature already exists even if it is ugly to use :)
> 
> 
>> On Mon, Nov 30, 2015 at 8:37 PM, Andrew Barnert <abarnert at yahoo.com> wrote:
>> On Nov 30, 2015, at 19:21, Kevin Modzelewski via Python-ideas <python-ideas at python.org> wrote:
>> >
>> > Class scopes definitely feel like a good match -- they are a way of saying "evaluate all of these expression, pass the resulting locals to a custom function, and bind the result of that function to the classname".  Usually the function is type(), which constructs a new class, but by setting a custom metaclass we can avoid creating a class just to wrap the scope:
>> 
>> Is there really a harm in creating a class?
>> 
>> A property is a type, and the obvious way to simulate it in Python rather than C (as shown by the sample code in the HOWTO) is with a class statement.
>> 
>> Besides, if you're creating many thousands of properties in a loop, the time and space cost of property creation is probably the least of your worries.
>> 
>> Again, maybe that isn't true for other types of decorators this feature might be useful for, but without having any examples to think about, it's hard to guess...
>> 
>> > class PropertyMetaclass(type):
>> >     def __new__(cls, name, bases, attrs):
>> >         return property(attrs.get('get'), attrs.get('set'), attrs.get('del'), attrs.get('__doc__'))
>> 
>> I still don't get the benefit of having a metaclass or constructor function or wrapper function or anything else, instead of just making property take a class instead of four functions. The latter is significantly nicer on the user side, and only a tiny bit more verbose in the implementation of property, and easier to understand. Unless there are other decorators where they wouldn't be true, or so many potentially useful one-shot decorators that defining them all a little more succinctly is worth the cost, why add the extra layer?
> 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20151201/8b86dfab/attachment-0001.html>


More information about the Python-ideas mailing list