Post #170,742
8/23/04 9:21:46 PM
|
Python decorator proposal
There's been a bit of a fight in the Python community over the syntax which function decorators should adopt. There is a syntax adopted in the current alpha release which many Pythonistas dislike. I wrote a proposal over the weekend for the strongest replacement candidate; since IWETHEY is My Own Personal Blog, you all get to comment. :) Plus, I'd just like someone who's not a Python user to tell me what they think. Outsider perspectives are always good. Just don't propose new syntax! We have far too many variants already. The thing, itself: [link|http://www.aminus.org/rbre/python/pydec.html|http://www.aminus.or...python/pydec.html] Once the discussion dies down on the newsgroup, I'll call for signatories and send it to Guido (Python's Benevolent Dictator For Life) for consideration. 'Decorators', by the way, are callables which you pass a function and get back a function. The decorator can add attributes to that function, wrap it with another, or give you back a new function object. Whatever you want. The old way of doing this was def foo(cls):\n pass\nfoo = classmethod(foo)\nfoo.author = "Robert Brewer" The current alpha syntax would be @classmethod\n@funcattrs(author="Robert Brewer")\ndef foo(cls):\n pass and the proposal suggests using:\n classmethod\n funcattrs(author="Robert Brewer")\ndef foo(cls):\n pass
|
Post #170,771
8/24/04 8:42:40 AM
|
as a non python user, whats wrong with the old way?
These miserable swine, having nothing but illusions to live on, marshmallows for the soul in place of good meat, will now stoop to any disgusting level to prevent even those miserable morsels from vanishing into thin air. The country is being destroyed by these stupid, vicious right-wing fanatics, the spiritual brothers of the brownshirts and redstars, collectivists and authoritarians all, who would not know freedom if it bit them on the ass, who spend all their time trying to stamp, bludgeon, and eviscerate the very idea of the individual's right to his own private world. DRL questions, help? [link|mailto:pappas@catholic.org|email pappas at catholic.org]
|
Post #170,783
8/24/04 10:59:03 AM
|
Not really wrong, just annoying
...which isn't the best reason to introduce new syntax, but it's going in one way or another. Here's an example of the old way: def frombuf(cls, buf):\n """Construct a TarInfo object from a 512 byte string buffer.\n """\n tarinfo = cls()\n tarinfo.name = nts(buf[0:100])\n tarinfo.mode = int(buf[100:108], 8)\n tarinfo.uid = int(buf[108:116],8)\n tarinfo.gid = int(buf[116:124],8)\n tarinfo.size = long(buf[124:136], 8)\n tarinfo.mtime = long(buf[136:148], 8)\n tarinfo.chksum = int(buf[148:156], 8)\n tarinfo.type = buf[156:157]\n tarinfo.linkname = nts(buf[157:257])\n tarinfo.uname = nts(buf[265:297])\n tarinfo.gname = nts(buf[297:329])\n try:\n tarinfo.devmajor = int(buf[329:337], 8)\n tarinfo.devminor = int(buf[337:345], 8)\n except ValueError:\n tarinfo.devmajor = tarinfo.devmajor = 0\n tarinfo.prefix = buf[345:500]\n\n # The prefix field is used for filenames > 100 in\n # the POSIX standard.\n # name = prefix + '/' + name\n if tarinfo.type != GNUTYPE_SPARSE:\n tarinfo.name = normpath(os.path.join(nts(tarinfo.prefix), tarinfo.name))\n\n # Directory names should have a '/' at the end.\n if tarinfo.isdir() and tarinfo.name[-1:] != "/":\n tarinfo.name += "/"\n return tarinfo\n\n frombuf = classmethod(frombuf) Two things are "wrong": 1) The notation that this is a class method is a long way from the declaration of the function itself, and often gets missed when reading source code. 2) One has to type "frombuf" three times. In particular, some integration projects require you to a) wrap functions and b) use extremely long method names.
"Despite the seemingly endless necessity for doing so, it's actually not possible to reverse-engineer intended invariants from staring at thousands of lines of code (not in C, and not in Python code either)." Tim Peters on python-dev
|
Post #170,789
8/24/04 12:05:46 PM
|
I don't understand the example :(
Could you explain? What, exactly, is "classmethod"?
--
"...was poorly, lugubrious and intoxicated."
-- Patrick O'Brian, "Master and Commander"
|
Post #170,791
8/24/04 12:32:59 PM
|
classmthod
(my 'e' key has been failing me recently) Normal Python has classes which possess member functions (methods). Normal methods always take an initial parameter (usually called 'self') which refers to the instance of the class. For example: class Ball(object):\n def __init__(self):\n self.x = 0\n\n def bounce(self, distance):\n self.x += distance\n\nbasketball = Ball()\nbasketball.bounce(3) Inside 'bounce' (when we call it), 'self' refers to the basketball object instance, so you can manipulate it. Sometimes, however, you want a method which doesn't care about the instance, only the class. Often, these are constructors: class Ball(object):\n def __init__(self):\n self.x = 0\n self.y = 0\n\n def displaced(cls, x, y):\n b = cls()\n b.x = x\n b.y = y\n return b\n displaced = classmethod(displaced)\n\nbasketball = Ball.displaced(3, 4)\nbasketball.bounce(3) classmethod() takes what would have been a normal member function and makes it a class method. Class methods don't receive an instance as the first argument, but a class instead (classes are objects in Python). You have to pass in the class for the method to work on it. The above is pretty trivial--we could have just written b = Ball() instead of b = cls(), but once you start subclassing, you can take advantage of the generic nature of cls. Hope that helped <:)
"Despite the seemingly endless necessity for doing so, it's actually not possible to reverse-engineer intended invariants from staring at thousands of lines of code (not in C, and not in Python code either)." Tim Peters on python-dev
|
Post #170,813
8/24/04 4:38:37 PM
|
A more concrete example from Ruby
Take a look at their [link|http://www.rubycentral.com/ref/ref_c_file.html|File] class. Look at the class methods and the instance methods.
The class methods are all operations on the filesystem. The instance methods are all operations that you'd do to an individual file. If you see how they draw the distinction, you'll see why it can make sense to distinguish between them.
(The syntax for defining class methods in Ruby differs from Python, but the spirit is the same.)
Cheers, Ben
To deny the indirect purchaser, who in this case is the ultimate purchaser, the right to seek relief from unlawful conduct, would essentially remove the word consumer from the Consumer Protection Act - [link|http://www.techworld.com/opsys/news/index.cfm?NewsID=1246&Page=1&pagePos=20|Nebraska Supreme Court]
|
Post #170,819
8/24/04 5:08:40 PM
|
Oh, I underrstand class/object methods
The classmethod() thing was just an example of decorator. Other good examples include foo=synchronized(foo), foo=traced(foo), foo=remote(machine_name, foo) and so on. Any thing that modifies the way function executes.
BTW, FuManChu surreptitiously folded function attributes in there as well. I wonder if python is concistant enough that you can write not only
def foo(): pass
foo.author = "me"
but also
1.owner = "me"
or
"blah".speaker = "me"
:)
--
"...was poorly, lugubrious and intoxicated."
-- Patrick O'Brian, "Master and Commander"
|
Post #170,825
8/24/04 5:18:41 PM
|
You can't do that to builtins yet
But you can usually subclass builtins and get what you want.
PythonWin 2.3.2 (#49, Oct 2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)] on win32. Portions Copyright 1994-2001 Mark Hammond (mhammond@skippinet.com.au) - see 'Help/About PythonWin' for further copyright information. >>> "thing".x = 0 Traceback (most recent call last): File "<interactive input>", line 1, in ? AttributeError: 'str' object has no attribute 'x' >>> a = "thing" >>> a.x = 0 Traceback (most recent call last): File "<interactive input>", line 1, in ? AttributeError: 'str' object has no attribute 'x' >>> class Thing(str): ... \tpass ... >>> a = Thing() >>> a.x = 0 >>> a.x 0
"Despite the seemingly endless necessity for doing so, it's actually not possible to reverse-engineer intended invariants from staring at thousands of lines of code (not in C, and not in Python code either)." Tim Peters on python-dev
|
Post #170,840
8/24/04 8:47:03 PM
|
You can do that in Ruby
You can't do it exactly like you suggested - since there is no method named owner on the number 1, you cannot call that method. You have to create the method first. This works: \nclass Fixnum;\n attr_accessor :owner;\nend\n\n1.owner = "me";\nputs 1.owner;\n Cheers, Ben
To deny the indirect purchaser, who in this case is the ultimate purchaser, the right to seek relief from unlawful conduct, would essentially remove the word consumer from the Consumer Protection Act - [link|http://www.techworld.com/opsys/news/index.cfm?NewsID=1246&Page=1&pagePos=20|Nebraska Supreme Court]
|
Post #172,640
9/3/04 2:43:14 PM
|
An update on the proposed change
Apparently [link|http://lambda-the-ultimate.org/node/view/235|rejected by GvR].
|
Post #172,673
9/3/04 4:50:44 PM
|
Why, yes, he did. :)
However, we all (Guido included ;) learned a lot about community involvement in the design process. I'm quite pleased with the meta-outcomes. You can read the whole rejection notice at [link|http://article.gmane.org/gmane.comp.python.devel/63486|http://article.gmane...ython.devel/63486]
|