PEP 318 -- a couple use cases
I saw both of the following use cases mentioned on the list, and they seemed interesting, so I went ahead and wrote up implementations: def property_getter(func): """ A decorator that can be used to incrementally construct properties. For example, the following code constructs a property 'x' from an fget, an fset, and an fdel function: >>> class A: ... def x(self) [property_getter]: ... return self.__x ... def x(self, val) [property_setter]: ... self.__x = val ... def x(self) [property_deleter]: ... del self.__x In particular, this decorator checks if a property named 'func' is defined in the enclosing frame. If so, then it updates that property's fget to be 'func'. If not, then it creates a new property whose fget is 'func'. The property's docstring is taken from the first decorated property function to define a docstring. """ def generic(*type_signature): """ A decorator-generator that can be used to incrementally construct a generic function that delegates to individual functions based on the type signature of the arguments. For example, the following code defines a generic function that uses two different actual functions, depending on whether its argument is a string or an int: >>> def f(x) [generic(int)]: ... print x, 'is an int' >>> def f(x) [generic(str)]: ... print x, 'is a string' In particular, the decorator returned by this function checks if a Generic function-delegation object with the same name as the decorated function is defined in the enclosing frame. If so, then it registers the function with that generic object, under 'type_signature'. If not, then it creates a new Generic function-delegation object, and registers the function. """ Full code is at http://www.cis.upenn.edu/~edloper/pydecorators.html. But I still don't feel like I have a good handle on what "acceptable" uses of decorators are.. So, for each of these 2 use cases, is it... - an excellent example that should be included in the stdlib - perfectly acceptable, and belongs in the python cookbook - somewhat hackish, but ok under the right circumstances - an abhorition of nature (If one of the first 3, then maybe they should be added to the pep?) Thanks for the feedback. -Edward
I saw both of the following use cases mentioned on the list, and they seemed interesting, so I went ahead and wrote up implementations:
def property_getter(func): [...] def generic(*type_signature): [...] Full code is at http://www.cis.upenn.edu/~edloper/pydecorators.html.
But I still don't feel like I have a good handle on what "acceptable" uses of decorators are.. So, for each of these 2 use cases, is it... - an excellent example that should be included in the stdlib - perfectly acceptable, and belongs in the python cookbook - somewhat hackish, but ok under the right circumstances - an abhorition of nature
I'm wavering between 2 (perfectly acceptable) and 3 (somewhat hackish), only because I consider anything that uses sys._getframe() to be a danger to society unless proven innocent. I would probably prefer to do both of these using explicit, different names. In particular for properties, I *like* the fact that I can also explicitly call the getter or setter functions, so I'd probably continue to write those like this: class C(object): def getX(self): return self.__x def setX(self, x): self.__x = x x = property(getX, setX) I'm not sufficiently comfortable with generic functions to quite know what feels best there. But I like the notation you proposed (I would like it better with the decorators up front though). --Guido van Rossum (home page: http://www.python.org/~guido/)
I'm wavering between 2 (perfectly acceptable) and 3 (somewhat hackish), only because I consider anything that uses sys._getframe() to be a danger to society unless proven innocent.
Would these be preferable:? class C(object): [property] def x(self): return self.__x [property_setter(x)] def x(self, val): self.__x = val [property_deleter(x)] def x(self): del self.__x and: [generic(None, (int,int))] def f(x,y): print 'two ints' [generic(f, (float,float))] def f(x,y): print 'two floats' I.e., explicitly pass the old value in, rather than grabbing it from sys._getframe. Advantages: - no sys._getframe magic Disadvantages: - you have to type the property/function name twice - you have to do something special for the first def - you can't easily rearrange the defs -Edward
I'm wavering between 2 (perfectly acceptable) and 3 (somewhat hackish), only because I consider anything that uses sys._getframe() to be a danger to society unless proven innocent.
Would these be preferable:?
class C(object): [property] def x(self): return self.__x
[property_setter(x)] def x(self, val): self.__x = val
[property_deleter(x)] def x(self): del self.__x and: [generic(None, (int,int))] def f(x,y): print 'two ints'
[generic(f, (float,float))] def f(x,y): print 'two floats'
I.e., explicitly pass the old value in, rather than grabbing it from sys._getframe.
Advantages: - no sys._getframe magic Disadvantages: - you have to type the property/function name twice - you have to do something special for the first def - you can't easily rearrange the defs
I see no big advantage to this solution; the requirement to type the name an extra time seems arbitrary. --Guido van Rossum (home page: http://www.python.org/~guido/)
participants (2)
-
Edward Loper
-
Guido van Rossum