Movatterモバイル変換
[0]ホーム
[Python-Dev] PEP 318: More examples of decorator use
Jim Huguninlists at hugunin.net
Tue Apr 6 18:08:54 EDT 2004
I'm a little scared of getting involved in the discussion of PEP 318.Nevertheless, I think any language design discussion can benefit from moreexamples. Here's a list of ways that I would use decorators in my Pythoncode if I had simpler syntax than is available today.*Interoperability with other languages and systemsjythonc parses method docstrings looking for a special directive to generateJava-compatible method signatures, i.e.def meth(self, a, b): "@sig public void meth(int a, int b)" passIf Python had structured metadata, this would change to[java_sig("public void meth(int a, int b)")]def meth(self, a, b): passC# uses this mechanism to provide interoperability with C, COM, and webservices. Here's a translation of a web services example from the .NETframework docs.[WebService(Description="Common Server Variables", Namespace="http://www.contoso.com/")]class ServerVariables: [WebMethod(Description="Obtains the Server Computer Name", EnableSession=false)] def GetMachineName(self): return self.Server.MachineName [SoapDocumentMethod(Action="http://www.contoso.com/Sample", RequestNamespace="http://www.contoso.com/Request", RequestElementName="GetUserNameRequest", ResponseNamespace="http://www.contoso.com/Response", ResponseElementName="GetUserNameResponse"), WebMethod(Description="Obtains the User Name")] def GetUserName(self): ...This is the same functionality motivating Bob Ipolito's pleas for thisfeature to support pyobjc, and it would obviously also help IronPython.*Tracing and other global policiesAspect-oriented programming has had great success capturing global policiesfor things like tracing in a single module. For a language like Python thatalready has strong meta-programming support it's possible to program in anAOP style without any language changes (see the tracing implementation inparrotbench/b0.py for an example).However, one lesson learned from actually applying AOP to large systems(http://hugunin.net/papers/pra03-colyer.pdf) was that there was always aneed to capture a few local exceptions. Current AOP systems can do this ina clumsy way, but almost everyone agrees that C#/Java attributes are thebest way to specify these kinds of exceptions.Here's an example of a tracing policy with a local exception.from tracing import notrace, add_tracingclass C: def m1(self): ... def m2(self): ... [notrace] def m0(self): ...if __DEBUG__: add_tracing(globals())This code will recursively walk all the declarations in a module and wrapall methods and functions with tracing code. Attributes are used here toindicate special handling for specific methods. In this case, m0 should notbe traced.*Unit testingThe nunit test framework uses attributes instead of naming conventions tolabel test methods. My favorite part of this is the additional attributes,for example 'expected_exception' to indicate that the correct behavior for atest is to throw a particular exception, i.e.[test, expected_exception(InsufficientFundsError)]def transfer2(self): self.source.transfer(100000000000)vs.def test_transfer2(self): self.assertRaises(InsufficientFundsError, self.source.transfer, 1000000000) This example is extremely compelling for C# or Java code where functionsaren't first class and a complicated try/catch block is required instead ofassertRaises. It's less compelling than I'd expected for Python; however, Istill find the version with attributes a little more clear.*ParsingThere are many simple parser implementations for Python that embed grammarrules in doc strings. This would be nicer to have in explicit metadata.Here's an example from Brian Sabbey's dparser for python.[action("exp", "exp '+' exp")]def d_add(t): return t[0] + t[2] [action("exp", '"[0-9]+"')]def d_number(t): return int(t[0])*SynchronizationI think a synchronized decorator would be useful, but more sophisticatedlocking policies are even more interesting. Here's an example ofreader/writer synchronization assuming a metaclass ReadWriteSynchro thatcooperates with attributes on specific methods.class DataStore(ReadWriteSynchro): [reader] def read(self, key): .... [writer] def write(self, key, value): ... ...*Other examples that I'd probably usememoized from Michael Chermside to automatically cache the results ofidempotent functionsaccepts and returns type checking wrappers from the PEP until/unless Pythongets a better answer for true optional type declarationsgeneric from Edward Loper to support generic functions. I both really likeand really hate this decorator. I'd love to have tolerable syntax forgeneric functions and this gives me something tolerable. On the other hand,I really dislike code that uses sys._getframe() so that might be enough toscare me off of this.*Some examples that I'd like to see in an anti-patterns listonexit from the PEP. I don't think decorators should have side-effectsvisible outside of the class/function itself. This seems MUCH betteraccomplished with the explicit call to the registration function.singleton from the PEP. Whenever possible, decorators should return thesame kind of thing that they are given. This code seems much less clearthan explicitly creating a singleton instance.propget, propset, propdel from Edward Loper via Guido. To me, these violatethe principle of modularity. I much prefer the explicit propertydeclaration that puts all of the parts together. class C(object): def getX(self): return self.__x def setX(self, x): self.__x = x x = property(getX, setX)-Jim
More information about the Python-Devmailing list
[8]ページ先頭