
@property def data(self): return f"{self}" Not at a workstation but this should be faster than join() while still using syntax and not builtin functions. ~ Jeremiah On Tue, Dec 20, 2022 at 5:38 PM Christopher Barker <pythonchb@gmail.com> wrote:
As has been said, a builtin *could* be written that would be "friendly to subclassing", by the definition in this thread. (I'll stay out of the argument for the moment as to whether that would be better)
I suspect that the reason str acts like it does is that it was originally written a LONG time ago, when you couldn't subclass basic built in types at all.
Secondarily, it could be a performance tweak -- minimal memory and peak performance are pretty critical for strings.
But collections.UserString does exist -- so if you want to subclass, and performance isn't critical, then use that. Steven A pointed out that UserStrings are not instances of str though. I think THAT is a bug. And it's probably that way because with the magic of duck typing, no one cared -- but with all the static type hinting going on now, that is a bigger liability than it used to be. Also basue when it was written, you couldn't subclass str.
Though I will note that run-time type checking of string is relatively common compared to other types, due to the whole a-str-is-a-sequence-of-str issue making the distinction between a sequence of strings and a string itself is sometimes needed. And str is rarely duck typed.
If anyone actually has a real need for this I'd post an issue -- it'd be interesting if the core devs see this as a bug or a feature (well, probably not feature, but maybe missing feature)
OK -- I got distracted and tried it out -- it was pretty easy to update UserString to be a subclass of str. I suspect it isn't done that way now because it was originally written because you could not subclass str -- so it stored an internal str instead.
The really hacky part of my prototype is this:
# self.data is the original attribute for storing the string internally. Partly to prevent my having to re-write all the other methods, and partly because you get recursion if you try to use the methods on self when overriding them ...
@property def data(self): return "".join(self)
The "".join is because it was the only way I quickly thought of to make a native string without invoking the __str__ method and other initialization machinery. I wonder if there is another way? Certainly there is in C, but in pure Python?
Anyway, after I did that and wrote a __new__ -- the rest of it "just worked".
def __new__(cls, s): return super().__new__(cls, s)
UserString and its subclasses return instances of themselves, and instances are instances of str.
Code with a couple asserts in the __main__ block enclosed.
Enjoy!
-CHB
NOTE: VERY minimally tested :-)
On Tue, Dec 20, 2022 at 4:17 PM Chris Angelico <rosuav@gmail.com> wrote:
On Wed, 21 Dec 2022 at 09:30, Cameron Simpson <cs@cskk.id.au> wrote:
On 19Dec2022 22:45, Chris Angelico <rosuav@gmail.com> wrote:
On Mon, 19 Dec 2022 at 22:37, Steven D'Aprano <steve@pearwood.info>
wrote:
But this much (say with a better validator) gets you static type checking, syntax highlighting, and inherent documentation of intent.
Any half-way decent static type-checker will immediately fail as soon as you call a method on this html string, because it will know that the method returns a vanilla string, not a html string.
But what does it even mean to uppercase an HTML string? Unless you define that operation specifically, the most logical meaning is "convert it into a plain string, and uppercase that".
Yes, this was my thought. I've got a few subclasses of builtin types. They are not painless.
For HTML "uppercase" is a kind of ok notion because the tags are case insensitive.
Tag names are, but their attributes might not be, so even that might not be safe.
Notthe case with, say, XML - my personal nagging example is from KML (Google map markup dialect) where IIRC a "ScreenOverlay" and a "screenoverlay" both existing with different semantics. Ugh.
Ugh indeed. Why? Why? Why?
So indeed, I'd probably _want_ .upper to return a plain string and have special methods to do more targetted things as appropriate.
Agreed.
ChrisA _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/T7FZ3F... Code of Conduct: http://python.org/psf/codeofconduct/
-- Christopher Barker, PhD (Chris)
Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/I62E7P... Code of Conduct: http://python.org/psf/codeofconduct/