Carl Johnson wrote: > (First, let me apologize for diving into a bike shed discussion.) > > There are two proposed ways to handle custom __format__ methods: > >> class MyInt: >> def __format__(self, spec): >> if int.is_int_specifier(spec): >> return int(self).__format__(spec) >> return "MyInt instance with custom specifier " + spec >> def __int__(self): >> return <some local state> > > and > >> class MyInt: >> def __format__(self, spec): >> if is_custom_spec(spec): >> return "MyInt instance with custom specifier " + spec >> return NotImplemented >> def __int__(self): >> return <some local state> > > I think this would be more straightforward as: > > class MyInt: > def __format__(self, spec): > if is_MyInt_specific_spec(spec): > return "MyInt instance with custom specifier " + spec > else: > return int(self).__format__(spec) > def __int__(self): > return <some local state> > > The makers of the MyInt class should be the ones responsible for > knowing that > MyInt can be converted to int as needed for output. If they want > MyInt to > handle all the same format spec options as MyInt, it's up to them to > either > implement them all in their __format__ or to cast the instance object > to int > then call its __format__ object by themselves. I don't see the point > in having > format guess what MyInt should be converted to if it can't handle the > options > passed to it. If we go too far down this road, if MyInt craps out > when given > ":MM-DD-YY", then format will be obliged to try casting to Date just > to see if > it will work. No, I think the format function should be somewhat > dumb, since > dumb makes more sense to __format__ implementers than clever. Let > them figure > out what their type can be cast into.
+1 > In the case that regular int can't handle the given format spec either, > int.__format__ will raise (return?) NotImplemented, in which case the > format > function will try string conversion, and then if that also pukes, a > runtime > exception should be raised. > > I also like the idea of using "!r" for calling repr and agree that it > should be > listed first. The syntax seems to be calling out for a little bit of > extension > though. Might it be nice to be able to do something like this? > > s = "10" > print("{0!i:+d}".format(s)) #prints "+10" It's been talked about extending it. The plan is to first implement the more restricted version and let people hack on it, adding what features are deemed useful in practice. > The !i attempts to cast the string to int. If it fails, then an > exception is > raised. If it succeeds, then the int.__format__ method is used on the > remainder > of the spec string. The logic is that ! commands are abbreviated > functions that > are applied to the input before other formatting options are given. > > On the one hand, this does risk a descent into "line noise" if too > many ! > options are provided. On the other hand, I think that providing ! > options for > just repr, str, int, and float probably wouldn't be too bad, and > might save > some tedious writing of int(s), etc. in spots. It seems like if we're > going to > have a weird syntax for repr anyway, we might as well use it to make > things > more convenient in other ways. Or is this too TMTOWTDI-ish, since one > could > just write int(s) instead? (But by that logic, one could write repr > (s) too…) > > The format function would end up looking like this: > > def format(obj, spec): > if spec[0] == "!": > switch statement for applying obj = repr(obj), obj = int > (obj), etc. > spec = spec[2:] > if obj.__format__ and type(obj) is not str: > try: > #if spec contains letters not understood, __format__ > raises NI > return obj.__format__(spec) > except NotImplemented: > pass #everything gets put through str as a last resort > return str(obj).__format__(spec) #last chance before throwing > exception The built-in 'format' function doesn't handle '!r', that's done by the caller. The 'spec' argument passed in to 'format' is the part *after* the colon. Also, there's no need to test for the existence __format__, because all objects will have a __format__ method which is inherited from object.__format__. > Does this make sense to anyone else? Perfectly. > --Carl Johnson > _______________________________________________ > Python-3000 mailing list > Python-3000@python.org > http://mail.python.org/mailman/listinfo/python-3000 > Unsubscribe: > http://mail.python.org/mailman/options/python-3000/talin%40acm.org > _______________________________________________ Python-3000 mailing list Python-3000@python.org http://mail.python.org/mailman/listinfo/python-3000 Unsubscribe: http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com