On Mon, Jan 17, 2022 at 4:38 PM Christopher Barker <[email protected]> wrote:
>
> On Sun, Jan 16, 2022 at 6:34 PM Chris Angelico <[email protected]> wrote:
>>
>> > def fun():
>> > return "some string"
>> >
>> > doesn't return the same string, unless it's iterned, which is an
>> > implementation detail, yes?
>>
>> Not sure what you mean. That's a constant, so it'll always return the
>> exact same object, surely?
>
>
> I *think* that's only if it's interned -- and in any case, is a guarantee of
> the language, or an optimization?
>
> I tried to test with a longer string, and it was the same one, but then I
> found in this arbitrary post on the internet:
>
> ... in Python 3.7, this has been changed to 4096 characters
>
> ( I guess I haven't played with that since 3.7) -- I haven't actually tried
> with a string literal linger than 4096 chars :-)
When you return a literal, like that, the literal becomes a function
constant. That's not necessarily a language guarantee, but I would be
hard-pressed to imagine a Python implementation that copied it for no
reason.
> But this certainly doesn't:
>
> In [1]: def fun():
> ...: return [1,2,3]
> ...:
>
> In [2]: l1 = fun()
>
> In [3]: l2 = fun()
>
> In [4]: l1 is l2
> Out[4]: False
>
> So the issue is immutability and interning, not "literal display".
The difference is that list display isn't a literal, but a simple
quoted string is. The square brackets are guaranteed to construct a
new list every time.
> My point is that a frozenset litteral could open the door to interning frozen
> sets, but that could probably be done anyway. And why? Are they heavily used
> in any code base?
>
A frozenset literal would allow the same frozenset to be reused, but
it's not about interning. You're right that interning would be
possible even without a literal, but in order to intern frozensets
without a literal, we'd still need to construct a brand new
(non-frozen) set to pass to the constructor, since there needs to be a
way to indicate which elements we want.
Technically, there are no "complex literals", but thanks to constant
folding, a value like 3+4j can become a function constant. In theory,
I could imagine a Python implementation that treats 3 and 4j as
constants, but adds them at runtime, producing a unique complex object
every time. But since there are no shadowable name lookups, it's easy
enough to take advantage and gain a nice optimization.
In theory, what could be done for frozensets would be to use a *tuple*
for the arguments, which can then be used for an intern-style lookup:
_frozenset = frozenset
_fscache = {}
def frozenset(t):
if type(t) is tuple: # strict check, don't allow subclasses
if t not in _fscache: _fscache[t] = _frozenset(t)
return _fscache[t]
return _frozenset(t)
This would remove some of the copying, but at the cost of retaining
all the tuples (in other words: now you have a classic caching
problem). Could be useful for situations where it really truly is
constant, but it's still a bit of a roundabout way to do things.
A true frozenset literal can't possibly be shadowed, so the compiler
would be free to do all the same optimizations that it does with
tuples.
ChrisA
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/7LRVPVKTQULH7QSF7GURV2W2MIVTWLKK/
Code of Conduct: http://python.org/psf/codeofconduct/