@decorator syntax is sugar, but for what exactly?
mark_bottjer at hotmail.com
Mon Aug 9 00:41:09 CEST 2004
Avner Ben wrote:
> So, if the problem is to rid class definitions of bizarre function
> calls, stuck in the middle of nowhere, that actually add to the
> structure of the class (and which other OO languages solve by
> legitimate syntax), I am dissapointed to observe that functuion
> decorators do not do a complete job after all.
While true, I find this less of a disappointment than you. There are two
large differences between class/staticmethods and properties: methods
act like functions, while properties act like variables; and properties
have multiple associated code blocks (the getter and setter), while
methods have only one. @decorator as designed applies only to functions,
and is simply inappropriate for properties. Disappointing, perhaps, but
not surprising--variables and functions *are* fundamentally different.
> Talking about properties, I like the C# way of defining them, which
> is straightforward and readable. The property begins like a method,
> but has no argument list and includes a getter function with no
> arguments and a setter function with one argument. Adapted to Python,
> it would look something like:
> class hasProperty:
> def __init__(self,aProperty='')
> self.aProperty = aProperty
> def AProperty:
> def get(self):
> return self.aProperty
> def set(self,value):
> self.aProperty = value
> obj = hasProperty()
> obj.AProperty = 'test'
> print obj.AProperty
I, personally, don't like the idea of overloading def in this way. To
me, 'def' defines something that looks and acts like a function, just
like 'class' defines something that looks and acts like a class, or
'while' defines something which looks and acts like a loop. AProperty is
does not act like a function, so using def would be misleading.
I agree, though, that the best way to handle properties is though some
sort of extended syntax. After all, we already have *a* way of doing it,
we just don't like how it looks. To fix this, we need to compress the
various pieces (name, storage, getter, setter, etc.) into a single
declarative construct. (In fact, this is a large part of my problem with
the proposed @ syntax: it isn't part of the function it modifies, but
rather some sort of odd prefix. OTOH, the prefix notation would work
with variables as well as functions, which is not possible with an infix
notation: @global; x=10. Whether or not this is actually of any benefit
is left as an exercise for the reader.)
I've thought for a while now that Python is skirting a breakthrough in
how it treats statements. Python took a step in the right direction with
generalizing iteration via generators, and I see utility in generalizing
the idea of statements as well. In particular, what I'd like to see is
the ability to define new *types* of statement.
Consider again the classmethod, staticmethod, and property. If these
were defined as extended statements, we could code them more naturally:
c = 'Hi there!'
class_def cm( c, a, b): # class method
return 'C(%r).cm( %r, %r) -> %r' % (id(c), a, b, c.c)
static_def sm( a, b): # static method
return 'C.sm( %r, %r) -> %r' % (a, b, a % b)
def im( s, a, b): # instance method
return 'C(%r).im( %r, %r) -> %r' % (id(s), a, b, (a % b) * self.a)
def __init__( s, a): # constructor
def __init__( s, v):
__set__( s, v)
def __get__( s):
print 'C(%r).a -> %r' % (s, s.__a)
def __set__( s, v):
print 'C(%r).a <- %r' % (s, v)
a = v
>>> o = C( 3.1415)
C(<C instance at 0x98765432>).a <- 3.1415
>>> o.cm( 2, 3)
C(<class C at 0x12345678>).cm( 2, 3) -> 'Hi there!'
>>> o.sm( 4, 5)
C.sm( 4, 5) -> 4
>>> o.im( 6, 7)
C(<C instance at 0x98765432>).a -> 3.1415
C.im( 6, 7) -> 18.849
C(<C instance at 0x98765432>).a -> 3.1415
In the above, 'class' is as we know them. 'class_def' and 'static_def'
are statements similar to 'def', but define a class method or static
method, respectively. Finally, 'property' is a statement which defines a
new property, and takes a code block expected to contain functions with
predefined names. Each of these could be implemented natively, or the
way we would do it manually today.
Taking this to the extreme, all existing statement types (class, def,
print, del, etc.) could be recast as these generalized statements. We
could even allow subclassing of existing statements to modify their
behavior (for example, class_def subclassing def to make the new
function a class method). Strong Kung-Fu indeed. Scary, but strong.
Obviously, creating new control constructs is not something we'd want to
do every day, as it can be a great way to obfuscate code beyond all hope
of understanding--but the same is true of meta-classes. Just because it
*could* be abused doesn't mean that it would be.
On the flip side, this doesn't address some of the more creative uses of
decorators that people have been proposing. A new statement type, like
class_def, effectively applies a fixed set of decorators (in the case of
class_def, it applies only classmethod); if we want more variety, we
still need decorators. They are independent ideas, even though they can
overlap a bit.
I have absolutely no idea as to *how* any of this would be accomplished,
mind you, but it would be *terribly* nifty.
More information about the Python-list