On Mon, Jan 17, 2022 at 4:38 PM Christopher Barker <python...@gmail.com> wrote: > > On Sun, Jan 16, 2022 at 6:34 PM Chris Angelico <ros...@gmail.com> 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 -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/7LRVPVKTQULH7QSF7GURV2W2MIVTWLKK/ Code of Conduct: http://python.org/psf/codeofconduct/