This issue tracker has been migrated to GitHub ,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2016年03月17日 06:29 by Rosuav, last changed 2022年04月11日 14:58 by admin. This issue is now closed.
| Files | ||||
|---|---|---|---|---|
| File name | Uploaded | Description | Edit | |
| deco-docos.patch | Rosuav, 2016年03月17日 06:29 | review | ||
| deco-docos.patch | Rosuav, 2016年03月17日 07:38 | review | ||
| deco-docos.patch | Rosuav, 2016年03月19日 07:15 | review | ||
| Messages (13) | |||
|---|---|---|---|
| msg261888 - (view) | Author: Chris Angelico (Rosuav) * | Date: 2016年03月17日 06:29 | |
The official documentation declares an unambiguous equivalence which is not true in some corner cases: @deco def f(x): pass is not quite the same as def f(x): pass f = deco(f) as the name is never bound to the undecorated function. This is what makes @property and @prop.setter work; otherwise, the undecorated setter function would overwrite the property, and the decoration would fail. Attached patch loosens the wording slightly to "broadly equivalent"; this permits corner cases to vary from the equivalence, while still retaining its simplicity for the 99% of cases where it's correct. (Think of explaining "yield from iter" as "for x in iter: yield x" and you have a similar near-equivalence.) Also, class decorators aren't required to return classes. Text removed saying that they do. |
|||
| msg261889 - (view) | Author: Chris Angelico (Rosuav) * | Date: 2016年03月17日 06:36 | |
Question: Is it worth having an explanation somewhere of exactly what *does* happen? To what extent is it guaranteed by the language? |
|||
| msg261890 - (view) | Author: Georg Brandl (georg.brandl) * (Python committer) | Date: 2016年03月17日 07:02 | |
The patch is definitely an improvement. What about a remark like ", except that `deco` is evaluated before the function `f` is created"? That should cover the remaining difference. |
|||
| msg261891 - (view) | Author: Georg Brandl (georg.brandl) * (Python committer) | Date: 2016年03月17日 07:02 | |
(Also, toggled your "is committer" bit so you get the Python logo next to your name.) |
|||
| msg261892 - (view) | Author: Chris Angelico (Rosuav) * | Date: 2016年03月17日 07:16 | |
The remaining difference that's actually of use, perhaps. But the decoration itself happens before the name is bound. It's impossible to describe in Python code; but it can be probed - you can monkeypatch a class using a decorator:
def monkeypatch(cls):
orig = globals()[cls.__name__] # Undocumented magic
print("Monkeypatch",id(cls),"into",id(orig))
for attr in dir(cls):
if not attr.startswith("_"):
setattr(orig,attr,getattr(cls,attr))
return orig
class Foo:
def method1(self):
print("I am method 1")
print("Foo is currently",id(Foo))
some_object = Foo()
@monkeypatch
class Foo:
def method2(self):
print("I am method 2")
print("Foo is now",id(Foo))
some_object.method1()
some_object.method2()
Is this undocumented behaviour? Should it be supported? It works on every Python I've tried it on (CPython 2.7 and 3.6, PyPy2 and PyPy3, Jython, and MicroPython), but it's not something I'd depend on in production code unless it's documented.
|
|||
| msg261893 - (view) | Author: Chris Angelico (Rosuav) * | Date: 2016年03月17日 07:17 | |
I may be a committer, but I don't push to cpython - just to the peps. But sure, pretty little logo :) |
|||
| msg261894 - (view) | Author: Georg Brandl (georg.brandl) * (Python committer) | Date: 2016年03月17日 07:24 | |
That is definitely supported. Whether it's actually useful to document, I'm not sure. "except that the original function is not temporarily bound to the name `f`" could work. |
|||
| msg261895 - (view) | Author: Chris Angelico (Rosuav) * | Date: 2016年03月17日 07:38 | |
Sounds good to me. Replacement patch. |
|||
| msg261991 - (view) | Author: Terry J. Reedy (terry.reedy) * (Python committer) | Date: 2016年03月18日 20:05 | |
Guido, the discrepancy between the decorator doc's 'equivalent code' and actual, optimized, behavior with regard to skipping an intermediate binding of the function to the name came up soon after decorators were added. I cannot find the issue, but as I remember, you said at the time that the doc's 'equivalent' code was good enough, and perhaps that you did not want to force the optimization on other implementations (not sure of this latter). This issue has come up often enough on Python list and SO that many think that the actual behavior should be documented. But should it be documented as a guaranteed language feature or as just an optional optimization? |
|||
| msg262025 - (view) | Author: Raymond Hettinger (rhettinger) * (Python committer) | Date: 2016年03月19日 07:09 | |
Elsewhere we use "roughly equivalent to" instead of "broadly equivalent to". The latter seems a little bit off the mark. |
|||
| msg262026 - (view) | Author: Chris Angelico (Rosuav) * | Date: 2016年03月19日 07:15 | |
Sure - changing it to "roughly". I started with that wording, and then changed to "broadly", for reasons which I now can't remember - so they can't have been too important. Consistency wins. |
|||
| msg271877 - (view) | Author: Roundup Robot (python-dev) (Python triager) | Date: 2016年08月03日 07:17 | |
New changeset e0f9f8be7963 by Berker Peksag in branch '3.5': Issue #26576: Clarify that the @deco syntax is not always an equivalent of f = deco(f) https://hg.python.org/cpython/rev/e0f9f8be7963 New changeset 08359651815e by Berker Peksag in branch 'default': Issue #26576: Merge from 3.5 https://hg.python.org/cpython/rev/08359651815e |
|||
| msg271878 - (view) | Author: Berker Peksag (berker.peksag) * (Python committer) | Date: 2016年08月03日 07:19 | |
Thanks for the patch, Chris. I've only changed `func` to ``func`` (we don't use single backtick in reST.) |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:58:28 | admin | set | github: 70763 |
| 2016年08月03日 07:19:15 | berker.peksag | set | status: open -> closed type: enhancement versions: + Python 3.5, Python 3.6 nosy: + berker.peksag messages: + msg271878 resolution: fixed stage: resolved |
| 2016年08月03日 07:17:01 | python-dev | set | nosy:
+ python-dev messages: + msg271877 |
| 2016年03月19日 07:15:20 | Rosuav | set | files:
+ deco-docos.patch messages: + msg262026 |
| 2016年03月19日 07:09:18 | rhettinger | set | nosy:
+ rhettinger messages: + msg262025 |
| 2016年03月18日 20:05:04 | terry.reedy | set | nosy:
+ terry.reedy, gvanrossum messages: + msg261991 |
| 2016年03月17日 07:38:17 | Rosuav | set | files:
+ deco-docos.patch messages: + msg261895 |
| 2016年03月17日 07:24:19 | georg.brandl | set | messages: + msg261894 |
| 2016年03月17日 07:17:37 | Rosuav | set | messages: + msg261893 |
| 2016年03月17日 07:16:36 | Rosuav | set | messages: + msg261892 |
| 2016年03月17日 07:02:53 | georg.brandl | set | messages: + msg261891 |
| 2016年03月17日 07:02:08 | georg.brandl | set | nosy:
+ georg.brandl messages: + msg261890 |
| 2016年03月17日 06:36:18 | Rosuav | set | messages: + msg261889 |
| 2016年03月17日 06:29:58 | Rosuav | create | |