Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accelerate 'string'.format(value, ...) by using formatted string literals #72495

Open
serhiy-storchaka opened this issue Sep 29, 2016 · 2 comments
Assignees
Labels
3.12 bugs and security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) performance Performance or resource usage

Comments

@serhiy-storchaka
Copy link
Member

BPO 28308
Nosy @ericvsmith, @serhiy-storchaka, @isidentical
Dependencies
  • bpo-11549: Build-out an AST optimizer, moving some functionality out of the peephole optimizer
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/serhiy-storchaka'
    closed_at = None
    created_at = <Date 2016-09-29.08:50:04.036>
    labels = ['interpreter-core', '3.7', 'performance']
    title = "Accelerate 'string'.format(value, ...) by using formatted string literals"
    updated_at = <Date 2020-02-14.20:42:51.446>
    user = 'https://github.com/serhiy-storchaka'

    bugs.python.org fields:

    activity = <Date 2020-02-14.20:42:51.446>
    actor = 'BTaskaya'
    assignee = 'serhiy.storchaka'
    closed = False
    closed_date = None
    closer = None
    components = ['Interpreter Core']
    creation = <Date 2016-09-29.08:50:04.036>
    creator = 'serhiy.storchaka'
    dependencies = ['11549']
    files = []
    hgrepos = []
    issue_num = 28308
    keywords = []
    message_count = 2.0
    messages = ['277689', '277693']
    nosy_count = 3.0
    nosy_names = ['eric.smith', 'serhiy.storchaka', 'BTaskaya']
    pr_nums = []
    priority = 'low'
    resolution = None
    stage = None
    status = 'open'
    superseder = None
    type = 'performance'
    url = 'https://bugs.python.org/issue28308'
    versions = ['Python 3.7']

    @serhiy-storchaka
    Copy link
    Member Author

    For now using formatted string literals (PEP-498) is the fastest way of formatting strings.

    $ ./python -m perf timeit -s 'k = "foo"; v = "bar"' -- '"{!s} = {!r}".format(k, v)'
    Median +- std dev: 3.96 us +- 0.17 us
    
    $ ./python -m perf timeit -s 'k = "foo"; v = "bar"' -- 'f"{k!s} = {v!r}"'
    Median +- std dev: 1.09 us +- 0.08 us

    The compiler could translate new-style formatting with literal format string to the equivalent formatted string literal. The code '{!s} = {!r}'.format(k, v) could be translated to

        t1 = k; t2 = v; f'{t1!r} = {t2!s}'; del t1, t2

    or even simpler if k and v are initialized local variables.

    $ ./python -m perf timeit -s 'k = "foo"; v = "bar"' -- 't1 = k; t2 = v; f"{t1!s} = {t2!r}"; del t1, t2'
    Median +- std dev: 1.22 us +- 0.05 us

    This is not easy issue and needs first implementing the AST optimizer.

    @serhiy-storchaka serhiy-storchaka added 3.7 (EOL) end of life interpreter-core (Objects, Python, Grammar, and Parser dirs) performance Performance or resource usage labels Sep 29, 2016
    @ericvsmith
    Copy link
    Member

    One thing to be careful of here is that there's one slight difference between how str.format() and f-strings handle indexing of values. f-strings, of course, use normal Python semantics, but
    str.format() treats indexing by things that don't look like integers as string literals, not variables. It's an unfortunate left-over from the original PEP-3101 specification:

    >>> d = {'a':'string', 0:'integer'}
    >>> a = 0
    >>> f'{d[0]}'
    'integer'
    >>> '{d[0]}'.format(d=d)
    'integer'
    >>> f'{d[a]}'
    'integer'
    >>> '{d[a]}'.format(d=d)
    'string'

    Note that the exact same expression {d[a]} is evaluated differently by the two ways to format.

    There's a test for this in test_fstring.py.

    Someday, I'd like to deprecate this syntax in str.format(). I don't think it could ever be added back in, because it requires either additional named parameters which aren't used as formatting parameters, or it requires global/local lookups (which isn't going to happen).

    i.e., this:
    '{d[a]}'.format(d=d, a=a)

    @serhiy-storchaka serhiy-storchaka self-assigned this Dec 25, 2017
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    @iritkatriel iritkatriel added 3.12 bugs and security fixes and removed 3.7 (EOL) end of life labels Sep 12, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.12 bugs and security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) performance Performance or resource usage
    3 participants