[Python-3000] More PEP 3101 changes incoming

Carl Johnson carlmj at hawaii.edu
Mon Aug 13 12:08:50 CEST 2007


(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.
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"
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
Does this make sense to anyone else?
--Carl Johnson


More information about the Python-3000 mailing list

AltStyle によって変換されたページ (->オリジナル) /