[Python-Dev] Re: Questions about CPython's behavior on addition operator -- binary_op1 (abstract.c) and nb_add (typeobject.c)

2020-01-20 Thread Raphaël Monat


I'm also keen to understand this and think I can elucidate a little, 
from my study of the code. The perspective of someone who *didn't* 
write it might help, but I defer to the authors' version when it appears.



Thank you! I'd be happy to know the authors' opinion as well.

A crucial observation is that there is only one nb_add slot in a type 
definition. Think about adding a int(1) + float(2). Where it lands in 
long_add (v->ob_type->tp_as_number->nb_add) will return 
NotImplemented, because it does not understand the float right-hand 
argument, but float_add (w->ob_type->tp_as_number->nb_add) is able to 
give an answer, since it can float the int, behaving as 
float.__radd__(f, i). So the slots have to implement both __add__ and 
__radd__.


I agree. And by default, this is done by expanding the macro 
"SLOT1BIN(slot_nb_add, nb_add, "__add__", "__radd__")".


The logic is the same as binary_op1, but the function has to deal with 
the possibility that one or other type may already provide a special 
function wrapper function in its nb_add slot, which is what the test 
tp_as_number->SLOTNAME == TESTFUNC is about. TESTFUNC is nearly always 
the same as FUNCNAME. Then it also deals with quite a complex decision 
in method_is_overloaded().


I have overlooked this test, and now I'm confused by it. In the 
definition of slot_nb_add, it seems to check that tp_as_number->nb_add 
== slot_nb_add. Is it (a convoluted way) to check that 
tp_as_number->nb_add != NULL? Otherwise, I guess this always hold for 
standard library modules, but someone may change tp_as_number->nb_add 
for another function?


The partial repetition of the logic, which I think is now nested 
(because binary_op1() may have called slot_nb_add) is necessary to 
insert the more complex version into the decision tree. But this is 
roughly where my ability to visualise the paths runs out.



I have an hypothesis: when binary_op1(v, w, ...) is called:
1) either slotv (v->ob_type->tp_as_number->nb_add) is defined. This 
calls v's slot_nb_add. This slot_nb_add may then call either v's 
"__add__" or w's "__radd__" using the calls to vectorcall_maybe.
2) or slotv is not defined. In that case we start the whole process 
using w's slot_nb_add, which should be stored in 
w->ob_type->tp_as_number->nb_add.


In particular, does this mean that if slotv is defined, the if(slotw) 
 
will never be reached (meaning this if could be changed by an else if)? 
Letting the case where w is a subtype of v aside for now, this would 
mean that some tests may be performed twice, but only one slot_nb_add 
will be called? (of course, this slot_nb_add will be able to call either 
its __add__ or the __radd__ of the other)


I would not say they are "defined" by the slot_nb_add function. 
Rather, if one or other has been defined (in Python), v.__add__  or 
w.__radd__ is called by the single function slot_nb_add. They cannot 
be called directly from C, but call_maybe() supplies the mechanism.


A confusing factor is that for types defined in C and filling the 
nb_add slot, the slot function (float_add, or whatever) has to be 
wrapped by two descriptors that can then sit in the type's dictionary 
as "__add__" and "__radd__". In that case these *are* defined by a 
wrapped C function, but that function is the function in the 
implementation of the type (float_add, say), not slot_nb_add. There 
are two kinds of wrapper: one used "Python-side out", so 
Python-calling "__add__" leads to nb_add's behaviour, and one "C-side 
out" so C-calling via nb_add leads to "__add__".



This makes sense. Thank you!


I *think* it is changed to contain slot_nb_add as defined by the macro.

And then slot_nb_add is able to dispatch to __add__ or __radd__ with 
vectorcall_maybe. Thanks!



When this is all clearer (and hopefully accurate), I'll wrap it up in a 
blog post or something.


--
Raphaël
___
Python-Dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/[email protected]/message/C76K6DUQOGMNVTFJ23JQSK3SHMMZ3GHR/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Re: About "python-porting" mail list

2020-01-20 Thread Facundo Batista
El mar., 14 de ene. de 2020 a la(s) 16:36, Mark Sapiro
([email protected]) escribió:
>
> The list has been removed. The archives are still available at
> .
>

Thank you!!

-- 
.Facundo

Blog: http://www.taniquetil.com.ar/plog/
PyAr: http://www.python.org.ar/
Twitter: @facundobatista
___
Python-Dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/[email protected]/message/ZIG6UGPU62P7AZ6RKIZLEBXYWQJU7RSX/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-Dev] Documenting Python's float.__str__()

2020-01-20 Thread Karl O. Pinc
Hello,

There appears to be extremely minimal documentation on how floats are
formatted on output.  All I really see is that float.__str__() is
float.__repr__().  So that means that float->str->float does not
result in a different value.

It would be nice if the output format for float was documented, to the
extent this is possible.  #python suggested that I propose a patch,
but I see no way to write a documentation patch without having any
clue about what Python promises, whether in the CPython implementation
or as part of a specification for Python.

What are the promises Python makes about the str() of a float?  Will
it produce 1.0 today and 1.0e0 or +1.0 tomorrow?  When is the result
in exponential notation and when not?  Does any of this depend on the
underlying OS or hardware or Python implementation?  Etc.

I'm guessing that Python is consistent with an IEEE 754
"external character sequence", but don't know what the IEEE
specification says or whether python conforms.

I don't really care whether there's documentation for __str__() or
__repr__() or something else.  I'm just thinking that there should be
some way to guarantee a well defined "useful" float output formatting.
By "useful" I mean in exponential notation when non-exponential
notation is over-long.

I am writing a program that sometimes prints python floats and want to
be able to document what is printed.  Right now I can't truly
guarantee anything, other than the nan and inf and -inf
representations.  (I feel comfortable with nan and the like because I
don't see it likely that their representations will change.)  Of
course I could always re-implement Python's float.__repr__() in Python
so as to have full control, but this should be pointless.  Python's
output representation is unlikely to change and Python should be able
to make sufficient promises about its existing float representation.

I suppose there are similar issues with integers, but the varieties of
floating point number implementations and the existence of both
exponential and non-exponential representations make float
particularly problematic and representations potentially mercurial.

I also don't know if documentation changes with regard to external
representations would require a PEP.

I have found the following related information:

Use shorter float repr when possible
https://bugs.python.org/issue1580

https://github.com/python/cpython/blob/master/Python/pystrtod.c#L831

String conversion and formatting
https://docs.python.org/3/c-api/conversion.html

sys.float_repr_style
https://docs.python.org/3/library/sys.html#sys.float_repr_style

object.__str__(self)
https://docs.python.org/3/reference/datamodel.html#object.__str__

At the end of the day I don't _really_ care.  But having put thought
into the matter I care enough to write this email and ask the
question.

Regards,

Karl 
Free Software:  "You don't pay back, you pay forward."
 -- Robert A. Heinlein
___
Python-Dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/[email protected]/message/FV22TKT3S2Q3P7PNN6MCXI6IX3HRRNAL/
Code of Conduct: http://python.org/psf/codeofconduct/