Re: [Python-ideas] Dunder method to make object str-like
Why strings and not, say, floats or bools or lists or bytes? Is it because strings have a uniquely compelling use case, or...? (For context from the numpy side of things, since IIUC numpy's fixed-width integer types were the impetus for __index__: numpy actually has a shadow type system that has versions of all of those types above except list. It also has a general conversion/casting system with a concept of different levels of safety, so for us __index__ is like a "safe" cast to int, and __int__ is like a "unsafe", and we have versions of this for all pairs of internal types, which if you care about this in general then having a single parametrized concept of safe casting might make more sense then adding new methods one by one. I'm not aware of any particular pain points triggered by numpy's strings not being real strings, though, at least in numpy's current design.) -n On Apr 7, 2016 6:05 AM, "Chris Angelico" <rosuav@gmail.com> wrote: This is a spin-off from the __fspath__ discussion on python-dev, in which a few people said that a more general approach would be better. Proposal: Objects should be allowed to declare that they are "string-like" by creating a dunder method (analogously to __index__ for integers) which implies a loss-less conversion to str. This could supersede the __fspath__ "give me the string for this path" protocol, or could stand in parallel with it. Obviously str will have this dunder method, returning self. Most other core types (notably 'object') will not define it. Absence of this method implies that the object cannot be treated as a string. String methods will be defined as accepting string-like objects. For instance, "hello"+foo will succeed if foo is string-like. Downside: Two string-like objects may behave unexpectedly - foo+bar will concatenate strings if either is an actual string, but if both are other string-like objects, depends on the implementation of those objects. Bikeshedding: 1) What should the dunder method be named? __str_coerce__? __stringlike__? 2) Which standard types are sufficiently string-like to be used thus? 3) Should there be a bytes equivalent? 4) Should there be a format string "coerce to str"? "{}".format(x) is equivalent to str(x), but it might be nice to be able to assert that something's stringish already. Open season! _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
On Fri, Apr 8, 2016 at 12:56 AM, Nathaniel Smith <njs@pobox.com> wrote:
Why strings and not, say, floats or bools or lists or bytes? Is it because strings have a uniquely compelling use case, or...?
(For context from the numpy side of things, since IIUC numpy's fixed-width integer types were the impetus for __index__: numpy actually has a shadow type system that has versions of all of those types above except list. It also has a general conversion/casting system with a concept of different levels of safety, so for us __index__ is like a "safe" cast to int, and __int__ is like a "unsafe", and we have versions of this for all pairs of internal types, which if you care about this in general then having a single parametrized concept of safe casting might make more sense then adding new methods one by one.
I'm not aware of any particular pain points triggered by numpy's strings not being real strings, though, at least in numpy's current design.)
I'm not against there being more such "treat as" dunder methods, but I'm not sure which types need them. We have __index__/__int__, and I'm proposing adding __something__/__str__; bytes was mentioned in the "okay folks, start bikeshedding" section. With bool, I'm not sure there needs to be anything. What object would need to say "I'm functionally a boolean!" in a way that's stronger than truthiness/falsiness? In what context would it be appropriate to use True and numpy.bool8(1) identically, but *not* use 42 or "spam" or object() to also mean true? If there's a use-case for that, then sure, that can be added to the proposal, and maybe something generic should be added. +0. Similar with float. I don't know of any use-cases myself, but I'd guess numpy is the best place to look. Remember, though, this would convert the other object into a float, not the float into a numpy object; if you want that, stick with the existing dunder methods and implement them yourself - numpy.float64(1.0)+2.0 is an instance of numpy.float64, NOT float. +0. With lists, though, I'm -1. The normal way to say "I function as a list" is to implement sequence protocol. If you want to be able to accept a list or a "thing like a list", what you usually want is a Sequence. So are you suggesting that we should instead have a single "safe cast" dunder method? class object: def __interpret_as__(self, t): """Return the same value as self, as an instance of t. If self cannot losslessly be interpreted as t, raise TypeError. """ if self.__class__ is t: return self if t is int and hasattr(self, "__index__"): return self.__index__() raise TypeError("'%s' object cannot be interpreted as %s" % (self.__class__.__name__, t.__name__)) class Path: def __interpret_as__(self, t): if t is str: return str(self) return super().__interpret_as__(t) Maybe that's the way things should be looking. ChrisA
participants (2)
-
Chris Angelico
-
Nathaniel Smith