GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — Avoid needlessly accessing `ForwardRef.__forward_code__` in `evaluate_forward_ref()` · Issue #155278 · python/cpython Closed Closed Copy link Labels performancePerformance or resource usagePerformance or resource usagestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancementA feature request or enhancement DescriptionFeature or enhancementProposal:Following #124337, I think we could also avoid evaluating In Lines 193 to 205 in fe3a123
but in Lines 994 to 1003 in fe3a123
We can apply the following: diff --git a/Lib/typing.py b/Lib/typing.py index 809c0ff8860..29b858ff836 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -25,6 +25,7 @@ import collections.abc import copyreg import functools +import keyword import operator import sys import types @@ -998,8 +999,13 @@ def _make_forward_ref(code, *, parent_fwdref=None, **kwargs): if parent_fwdref.__owner__ is not None: kwargs['owner'] = parent_fwdref.__owner__ forward_ref = annotationlib.ForwardRef(code, **kwargs) - # For compatibility, eagerly compile the forwardref's code. - forward_ref.__forward_code__ + # For compatibility, eagerly compile the forwardref's code so that any + # SyntaxError is raised immediately rather than when the forward + # reference is evaluated. Similar to 'ForwardRef.evaluate(), we only compile + # it if necessary: + if not (code.isidentifier() and not keyword.iskeyword(code)): + forward_ref.__forward_code__ return forward_ref Scriptimport sys import timeit import typing class MyClass: pass def f(a: "int", b: "str", c: "MyClass", d: "MyClass") -> "MyClass": pass def bench(label, n, stmt): t = min(timeit.repeat(stmt, number=n, repeat=5, globals=globals())) print(f"{label:55s} {t / n * 1e9:9.1f} ns/call ({n} iters, best of 5)") if __name__ == "__main__": bench( "typing._make_forward_ref('MyClass').evaluate(...)", 200_000, "typing._make_forward_ref('MyClass').evaluate(globals={'MyClass': MyClass})", ) bench( "get_type_hints(f) # only identifier forward refs", 20_000, "typing.get_type_hints(f)", ) Results
Has this already been discussed elsewhere?This is a minor feature, which does not need previous discussion elsewhere Links to previous discussion of this feature:No response Linked PRsActivity
MetadataMetadataAssigneesLabelsperformancePerformance or resource usagePerformance or resource usagestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancementA feature request or enhancement ProjectsMilestoneRelationshipsDevelopmentIssue actions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |