Mailing List Archive

evaluation question
Hi

This is probably a dumb newbie question but I've just started to learn
python3 and eval() isn't behaving as I'd expect in that it works for
some things and not others. eg:

>>> eval("1+1")
2
>>> eval("print(123)")
123
>>> eval("for i in range(1,10): i")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1
for i in range(1,10): i
^
SyntaxError: invalid syntax

Why did the 3rd one fail? Does it not handle complex expressions?

Thanks for any help



--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
Muttley@dastardlyhq.com writes:

> Hi

It looks like you posted this question via Usenet. comp.lang.python is
essentially dead as a Usenet group. It exists, and gets NNTP versions
of mail sent to the mailing list, but nothing posted to the group via
NNTP get send on the mailing list. I prefer Usenet and dislike mailing
lists but that just means I can't really contribute to this "group"

The "python-list" an an excellent resource (if you like the email
interface) and you can subscribe here:

https://mail.python.org/mailman/listinfo/python-list>,

> This is probably a dumb newbie question but I've just started to learn
> python3 and eval() isn't behaving as I'd expect in that it works for
> some things and not others. eg:
>
>>>> eval("1+1")
> 2
>>>> eval("print(123)")
> 123
>>>> eval("for i in range(1,10): i")
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "<string>", line 1
> for i in range(1,10): i
> ^
> SyntaxError: invalid syntax
>
> Why did the 3rd one fail? Does it not handle complex expressions?

It handles only expressions, and "for i in range(1,10): i" is not an
expression. You can use

>>> exec("for i in range(1,10): i")

or, to confirm that something is happening:

>>> exec("for i in range(1,10): print(i)")
1
2
3
4
5
6
7
8
9

See: https://docs.python.org/3/library/functions.html?highlight=eval#eval
and the immediately following entry.

--
Ben.
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Sat, 28 Jan 2023 at 11:45, <Muttley@dastardlyhq.com> wrote:
>
> Hi
>
> This is probably a dumb newbie question but I've just started to learn
> python3 and eval() isn't behaving as I'd expect in that it works for
> some things and not others. eg:
>
> >>> eval("1+1")
> 2
> >>> eval("print(123)")
> 123
> >>> eval("for i in range(1,10): i")
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "<string>", line 1
> for i in range(1,10): i
> ^
> SyntaxError: invalid syntax
>
> Why did the 3rd one fail? Does it not handle complex expressions?
>

There's a difference between *expressions* (which have values) and
*statements* (which do stuff, including control flow like loops). You
may want the exec function instead.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 28/01/2023 05.37, Muttley@dastardlyhq.com wrote:
> This is probably a dumb newbie question but I've just started to learn
> python3 and eval() isn't behaving as I'd expect in that it works for
> some things and not others. eg:
>
>>>> eval("1+1")
> 2
>>>> eval("print(123)")
> 123
>>>> eval("for i in range(1,10): i")
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "<string>", line 1
> for i in range(1,10): i
> ^
> SyntaxError: invalid syntax
>
> Why did the 3rd one fail? Does it not handle complex expressions?

eval() is very powerful, and therefore rather dangerous in the risks it
presents.

Thus, seems a strange/advanced question for a "newbie" to be asking. YMMV!

Do you know about the Python REPL?

If you open python within a terminal, each of the three
expressions/compound-statements listed will work, as desired, without
eval().

dn $ ... python
Python 3.11.1 (main, Jan 6 2023, 00:00:00) [GCC 12.2.1 20221121 (Red
Hat 12.2.1-4)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 1+1
2
>>> print( 123 )
123
>>> for i in range( 1, 10 ): i
...
1
2
3
4
5
6
7
8
9
>>> exit()

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Fri, 27 Jan 2023 21:04:58 +0000
Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
>Muttley@dastardlyhq.com writes:
>
>> Hi
>
>It looks like you posted this question via Usenet. comp.lang.python is
>essentially dead as a Usenet group. It exists, and gets NNTP versions
>of mail sent to the mailing list, but nothing posted to the group via
>NNTP get send on the mailing list. I prefer Usenet and dislike mailing
>lists but that just means I can't really contribute to this "group"
>
>The "python-list" an an excellent resource (if you like the email
>interface) and you can subscribe here:
>
>https://mail.python.org/mailman/listinfo/python-list>,
>
>> This is probably a dumb newbie question but I've just started to learn
>> python3 and eval() isn't behaving as I'd expect in that it works for
>> some things and not others. eg:
>>
>>>>> eval("1+1")
>> 2
>>>>> eval("print(123)")
>> 123
>>>>> eval("for i in range(1,10): i")
>> Traceback (most recent call last):
>> File "<stdin>", line 1, in <module>
>> File "<string>", line 1
>> for i in range(1,10): i
>> ^
>> SyntaxError: invalid syntax
>>
>> Why did the 3rd one fail? Does it not handle complex expressions?
>
>It handles only expressions, and "for i in range(1,10): i" is not an
>expression. You can use
>
>>>> exec("for i in range(1,10): i")

Ok, thanks.

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Sat, 28 Jan 2023 14:22:01 +1300
dn <PythonList@DancesWithMice.info> wrote:
>On 28/01/2023 05.37, Muttley@dastardlyhq.com wrote:
>> This is probably a dumb newbie question but I've just started to learn
>> python3 and eval() isn't behaving as I'd expect in that it works for
>> some things and not others. eg:
>>
>>>>> eval("1+1")
>> 2
>>>>> eval("print(123)")
>> 123
>>>>> eval("for i in range(1,10): i")
>> Traceback (most recent call last):
>> File "<stdin>", line 1, in <module>
>> File "<string>", line 1
>> for i in range(1,10): i
>> ^
>> SyntaxError: invalid syntax
>>
>> Why did the 3rd one fail? Does it not handle complex expressions?
>
>eval() is very powerful, and therefore rather dangerous in the risks it
>presents.
>
>Thus, seems a strange/advanced question for a "newbie" to be asking. YMMV!

Well ok, new-ish :)

>Do you know about the Python REPL?

Haven't learnt the acronyms yet.

>If you open python within a terminal, each of the three
>expressions/compound-statements listed will work, as desired, without
>eval().

Umm, yeah, thats kind of obvious isn't it?

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 1/27/2023 9:37 AM, Muttley@dastardlyhq.com wrote:
> Hi
>
> This is probably a dumb newbie question but I've just started to learn
> python3 and eval() isn't behaving as I'd expect in that it works for
> some things and not others. eg:
>
>>>> eval("1+1")
> 2
>>>> eval("print(123)")
> 123
>>>> eval("for i in range(1,10): i")
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "<string>", line 1
> for i in range(1,10): i
> ^
> SyntaxError: invalid syntax
>
> Why did the 3rd one fail? Does it not handle complex expressions?
>
> Thanks for any help
>
>
>

This might -- or might not -- be useful:

eval( "print( [i for i in range(1, 10)] )" )

It prints a list, but you probably knew that:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

Louis
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
Muttley@dastardlyhq.com wrote:
> On Sat, 28 Jan 2023 14:22:01 +1300
> dn <PythonList@DancesWithMice.info> wrote:
>> Do you know about the Python REPL?
>
> Haven't learnt the acronyms yet.

REPL stands for "Read Evaluate Print Loop". It basically refers to the
interactive interpreter, which reads input you type, evaluates it,
prints the result, and loops (repeatedly does that).

An interesting point from your examples is that the output from the
first two comes from different steps in that loop.

>>> eval("1+1")
2

Here, the E (evaluation) step runs eval("1+1"), which returns 2. The P
(print) step then prints that result. If this was in a script, you
wouldn't see any output, and the statement is pretty much useless -
you'd need to assign the result to a variable or explicitly print it.

>>> eval("print(123)")
123

Here, the E step runs eval("print(123)"), which prints 123 and returns
None. The P step doesn't print anything if the result is None. You'd
still see that output if this was in a script.

Using eval in those examples is pretty pointless, since:
>>> 1+1
>>> print(123)
would produce the same results - but of course they were just simple
examples.

--
Mark.
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 1/29/2023 4:15 PM, elvis-85792@notatla.org.uk wrote:
> On 2023-01-28, Louis Krupp <lkrupp@invalid.pssw.com.invalid> wrote:
>> On 1/27/2023 9:37 AM, Muttley@dastardlyhq.com wrote:
>
>
>>>>>> eval("print(123)")
>>> 123
>
>
> Does OP expect the text to come from the eval or from the print?
>
>>>> x = print( [i for i in range(1, 10)] )
> [1, 2, 3, 4, 5, 6, 7, 8, 9]
>
>>>> x
> (nothing printed)

Because print() returns nothing (i.e., the statement x is None is True).
Other common constructs that return nothing are append(), sort(), and
add(). It can be easy to forget this and write

l2 = l1.sort() # l2 == None

OTOH, you can (by slightly abusing the lambda) use this behavior to make
a lambda expression print what it's receiving:

>>> y = lambda x: print(f'Got {x}') or x**2
>>> z = y(3)
Got 3
>>> z
9
>>>

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Sun, 29 Jan 2023 23:57:51 -0500
Thomas Passin <list1@tompassin.net> wrote:
>On 1/29/2023 4:15 PM, elvis-85792@notatla.org.uk wrote:
>> On 2023-01-28, Louis Krupp <lkrupp@invalid.pssw.com.invalid> wrote:
>>> On 1/27/2023 9:37 AM, Muttley@dastardlyhq.com wrote:
>>
>>
>>>>>>> eval("print(123)")
>>>> 123
>>
>>
>> Does OP expect the text to come from the eval or from the print?
>>
>>>>> x = print( [i for i in range(1, 10)] )
>> [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>
>>>>> x
>> (nothing printed)
>
>Because print() returns nothing (i.e., the statement x is None is True).

I don't understand this. What was the point of the upheaval of converting
the print command in python 2 into a function in python 3 if as a function
print() doesn't return anything useful? Surely even the length of the
formatted string as per C's sprintf() function would be helpful?

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 30/01/2023 09:41, Muttley@dastardlyhq.com wrote:
> On Sun, 29 Jan 2023 23:57:51 -0500
> Thomas Passin <list1@tompassin.net> wrote:
>> On 1/29/2023 4:15 PM, elvis-85792@notatla.org.uk wrote:
>>> On 2023-01-28, Louis Krupp <lkrupp@invalid.pssw.com.invalid> wrote:
>>>> On 1/27/2023 9:37 AM, Muttley@dastardlyhq.com wrote:
>>>
>>>>>>>> eval("print(123)")
>>>>> 123
>>>
>>> Does OP expect the text to come from the eval or from the print?
>>>
>>>>>> x = print( [i for i in range(1, 10)] )
>>> [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
>>>>>> x
>>> (nothing printed)
>> Because print() returns nothing (i.e., the statement x is None is True).
> I don't understand this. What was the point of the upheaval of converting
> the print command in python 2 into a function in python 3 if as a function
> print() doesn't return anything useful? Surely even the length of the
> formatted string as per C's sprintf() function would be helpful?
>
That's a fair question, or rather 2 fair questions.
There is an explanation of why the change was made at
    https://snarky.ca/why-print-became-a-function-in-python-3/
In brief: (a) the print() function is more flexible and can be used in
expressions
               (b) Python's syntax was simplified by dropping the
special syntax used by the print statement.
sys.stdout.write() does return the number of characters output (you
could use this instead of print() if you need this;
remember to add a '\n' character at the end of  a line).  I guess the option
of making print() do the same either was not considered, or was
rejected, when print was made a function.
Best wishes
Rob Cliffe

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 30/01/23 10:41 pm, Muttley@dastardlyhq.com wrote:
> What was the point of the upheaval of converting
> the print command in python 2 into a function in python 3 if as a function
> print() doesn't return anything useful?

It was made a function because there's no good reason for it
to have special syntax in the language.

Functions don't need to return things to justify their existence,
and in fact the usual convention is that functions whose purpose
is to have an effect just return None.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Tue, 31 Jan 2023 12:57:33 +1300
Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
>On 30/01/23 10:41 pm, Muttley@dastardlyhq.com wrote:
>> What was the point of the upheaval of converting
>> the print command in python 2 into a function in python 3 if as a function
>> print() doesn't return anything useful?
>
>It was made a function because there's no good reason for it
>to have special syntax in the language.

All languages have their ugly corners due to initial design mistakes and/or
constraints. Eg: java with the special behaviour of its string class, C++
with "=0" pure virtual declaration. But they don't dump them and make all old
code suddenly cease to execute.

Pragmatism should always come before language purity.

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 1/31/2023 4:24 AM, Muttley@dastardlyhq.com wrote:
> On Tue, 31 Jan 2023 12:57:33 +1300
> Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
>> On 30/01/23 10:41 pm, Muttley@dastardlyhq.com wrote:
>>> What was the point of the upheaval of converting
>>> the print command in python 2 into a function in python 3 if as a function
>>> print() doesn't return anything useful?
>>
>> It was made a function because there's no good reason for it
>> to have special syntax in the language.
>
> All languages have their ugly corners due to initial design mistakes and/or
> constraints. Eg: java with the special behaviour of its string class, C++
> with "=0" pure virtual declaration. But they don't dump them and make all old
> code suddenly cease to execute.
>
> Pragmatism should always come before language purity.
>

It was more fundamental than that, and not mainly about print():

https://snarky.ca/why-python-3-exists/
--
https://mail.python.org/mailman/listinfo/python-list
RE: evaluation question [ In reply to ]
I think its has been discussed here that many functions are DELIBERATELY
designed to return without returning anything. Earlier languages like Pascal
had explicit ideas that a function that did not return a value was declared
as a "procedure" but many other languages like python make no real
differentiation.

Some functions are designed for a sort of side-effect and often there is
nothing much that needs to be returned or even can be. If a function prints
a dozen items one at a time, should it return nothing, or a copy of the last
item or somehow of all items? Generally nothing looks right. If you want to
return something, fine. Do it explicitly.

Similar arguments have been made about methods that do things like sort the
contents of an object internally and then return nothing. Some would like
the return to be the (now altered) object itself. You can emulate that by
not sorting internally but instead sorted(object) returns a new object that
has been sorted from the old one.

So should or could print return anything? Other languages exist, like R,
that do return (and often ignore) whatever print displayed elsewhere. This
can be of use in many ways such as making it easier to print or store
additional copies without recalculating.

My preference might be to simply allow a local option at the end of a print
statement such as print(..., return=True) or even a way to set a global
option so all print statements can be turned on when you want. But is this
pythonic? In particular, people who want to give type hints now can safely
claim it returns None and would have to modify that so it can optionally
return something like str or None. And, of course, once you change print()
this way, someone else will want the number of characters (or perhaps bytes)
returned instead.

Much of this can be worked around by simply making your own customized print
function which evaluates the arguments to make a string and then calls
print, perhaps with the results pre-calculated, and returns what you wanted.
That is not as easy as it sounds, though as print supports various
arguments like sep= and end= and file= and flush= so a weird but doable idea
is simply to substitute a temporary file for any file= argument and write
the results to a temporary file or something in memory that emulates a file.
You can then read that back in and return what you want after handling the
original print statement with the original arguments, or perhaps just use
your result to any actually specified file or the default.

You can thus create something like what you want and leave the original
print() command alone to do what it was designed to do.

And, in general, people who want a copy of what they print, often use other
python functionality to craft some or all parts of the text they want
printed and only then call print() and thus already may have the ability to
use the text afterwards.

For many purposes, including efficiency, returning nothing makes good sense.
But it is not really the only choice or the right choice and yet, if you
want to use THIS language, it has to be accepted as the documented choice.


-----Original Message-----
From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org> On
Behalf Of Thomas Passin
Sent: Tuesday, January 31, 2023 1:16 PM
To: python-list@python.org
Subject: Re: evaluation question

On 1/31/2023 4:24 AM, Muttley@dastardlyhq.com wrote:
> On Tue, 31 Jan 2023 12:57:33 +1300
> Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
>> On 30/01/23 10:41 pm, Muttley@dastardlyhq.com wrote:
>>> What was the point of the upheaval of converting the print command
>>> in python 2 into a function in python 3 if as a function
>>> print() doesn't return anything useful?
>>
>> It was made a function because there's no good reason for it to have
>> special syntax in the language.
>
> All languages have their ugly corners due to initial design mistakes
> and/or constraints. Eg: java with the special behaviour of its string
> class, C++ with "=0" pure virtual declaration. But they don't dump
> them and make all old code suddenly cease to execute.
>
> Pragmatism should always come before language purity.
>

It was more fundamental than that, and not mainly about print():

https://snarky.ca/why-python-3-exists/
--
https://mail.python.org/mailman/listinfo/python-list

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
Greg Ewing wrote:
> On 30/01/23 10:41 pm, Muttley@dastardlyhq.com wrote:
>> What was the point of the upheaval of converting
>> the print command in python 2 into a function in python 3 if as a
>> function
>> print() doesn't return anything useful?
>
> It was made a function because there's no good reason for it
> to have special syntax in the language.

I think I saw somewhere that making print a function also had something
to do with being able to add extra keyword arguments like sep and end.
The syntax for printing to a specific file already seemed a bit odd with
the print statement, and adding extra arguments would have made it even
more clunky (yeah, I know ">>" is similar to C++ streams, but it looks
out of place in Python).

They couldn't fully make the change from print statement to print
function without breaking backward compatibility for existing code. But
there were other breaking changes being made in Python 3 anyway, so may
as well sort print out while at it and have all the breaking changes at
once.

> Functions don't need to return things to justify their existence,
> and in fact the usual convention is that functions whose purpose
> is to have an effect just return None.

--
Mark.
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
import io

def countprint(*args, **kwargs):
capturekw = {k:v for k,v in kwargs.items() if k != 'file'}
buffer = io.StringIO()
capturekw['file'] = buffer
print(*args,**kwargs)
print(*args,**capturekw)
return len(buffer.getvalue())

def boolprint(*args,active:bool, **kwargs):
if active:
print(*args,**kwargs)

with open("text.txt",'w') as f:
y = countprint(1, 3, 3, sep=',', end='\n\n',file=f)
print(y)
boolprint(3,4,5,sep='/',active=True)
boolprint(7,11,active=False)

From: Python-list <python-list-bounces+gweatherby=uchc.edu@python.org> on behalf of avi.e.gross@gmail.com <avi.e.gross@gmail.com>
Date: Tuesday, January 31, 2023 at 3:01 PM
To: 'Thomas Passin' <list1@tompassin.net>, python-list@python.org <python-list@python.org>
Subject: RE: evaluation question
*** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. ***

I think its has been discussed here that many functions are DELIBERATELY
designed to return without returning anything. Earlier languages like Pascal
had explicit ideas that a function that did not return a value was declared
as a "procedure" but many other languages like python make no real
differentiation.

Some functions are designed for a sort of side-effect and often there is
nothing much that needs to be returned or even can be. If a function prints
a dozen items one at a time, should it return nothing, or a copy of the last
item or somehow of all items? Generally nothing looks right. If you want to
return something, fine. Do it explicitly.

Similar arguments have been made about methods that do things like sort the
contents of an object internally and then return nothing. Some would like
the return to be the (now altered) object itself. You can emulate that by
not sorting internally but instead sorted(object) returns a new object that
has been sorted from the old one.

So should or could print return anything? Other languages exist, like R,
that do return (and often ignore) whatever print displayed elsewhere. This
can be of use in many ways such as making it easier to print or store
additional copies without recalculating.

My preference might be to simply allow a local option at the end of a print
statement such as print(..., return=True) or even a way to set a global
option so all print statements can be turned on when you want. But is this
pythonic? In particular, people who want to give type hints now can safely
claim it returns None and would have to modify that so it can optionally
return something like str or None. And, of course, once you change print()
this way, someone else will want the number of characters (or perhaps bytes)
returned instead.

Much of this can be worked around by simply making your own customized print
function which evaluates the arguments to make a string and then calls
print, perhaps with the results pre-calculated, and returns what you wanted.
That is not as easy as it sounds, though as print supports various
arguments like sep= and end= and file= and flush= so a weird but doable idea
is simply to substitute a temporary file for any file= argument and write
the results to a temporary file or something in memory that emulates a file.
You can then read that back in and return what you want after handling the
original print statement with the original arguments, or perhaps just use
your result to any actually specified file or the default.

You can thus create something like what you want and leave the original
print() command alone to do what it was designed to do.

And, in general, people who want a copy of what they print, often use other
python functionality to craft some or all parts of the text they want
printed and only then call print() and thus already may have the ability to
use the text afterwards.

For many purposes, including efficiency, returning nothing makes good sense.
But it is not really the only choice or the right choice and yet, if you
want to use THIS language, it has to be accepted as the documented choice.


-----Original Message-----
From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org> On
Behalf Of Thomas Passin
Sent: Tuesday, January 31, 2023 1:16 PM
To: python-list@python.org
Subject: Re: evaluation question

On 1/31/2023 4:24 AM, Muttley@dastardlyhq.com wrote:
> On Tue, 31 Jan 2023 12:57:33 +1300
> Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
>> On 30/01/23 10:41 pm, Muttley@dastardlyhq.com wrote:
>>> What was the point of the upheaval of converting the print command
>>> in python 2 into a function in python 3 if as a function
>>> print() doesn't return anything useful?
>>
>> It was made a function because there's no good reason for it to have
>> special syntax in the language.
>
> All languages have their ugly corners due to initial design mistakes
> and/or constraints. Eg: java with the special behaviour of its string
> class, C++ with "=0" pure virtual declaration. But they don't dump
> them and make all old code suddenly cease to execute.
>
> Pragmatism should always come before language purity.
>

It was more fundamental than that, and not mainly about print():

https://urldefense.com/v3/__https://snarky.ca/why-python-3-exists/__;!!Cn_UX_p3!ldtLZeCkbC0gawIJRrbrunA0AqA_btcJ9M1TOlajHrezsXh5AqpuLFCg1mITKq8qvR8f3u-d8K2WF9yGhlD2rfk$<https://urldefense.com/v3/__https:/snarky.ca/why-python-3-exists/__;!!Cn_UX_p3!ldtLZeCkbC0gawIJRrbrunA0AqA_btcJ9M1TOlajHrezsXh5AqpuLFCg1mITKq8qvR8f3u-d8K2WF9yGhlD2rfk$>
--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!ldtLZeCkbC0gawIJRrbrunA0AqA_btcJ9M1TOlajHrezsXh5AqpuLFCg1mITKq8qvR8f3u-d8K2WF9yG5f0h2No$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!ldtLZeCkbC0gawIJRrbrunA0AqA_btcJ9M1TOlajHrezsXh5AqpuLFCg1mITKq8qvR8f3u-d8K2WF9yG5f0h2No$>

--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!ldtLZeCkbC0gawIJRrbrunA0AqA_btcJ9M1TOlajHrezsXh5AqpuLFCg1mITKq8qvR8f3u-d8K2WF9yG5f0h2No$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!ldtLZeCkbC0gawIJRrbrunA0AqA_btcJ9M1TOlajHrezsXh5AqpuLFCg1mITKq8qvR8f3u-d8K2WF9yG5f0h2No$>
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 31/01/23 10:24 pm, Muttley@dastardlyhq.com wrote:
> All languages have their ugly corners due to initial design mistakes and/or
> constraints. Eg: java with the special behaviour of its string class, C++
> with "=0" pure virtual declaration. But they don't dump them and make all old
> code suddenly cease to execute.

No, but it was decided that Python 3 would have to be backwards
incompatible, mainly to sort out the Unicode mess. Given that,
the opportunity was taken to clean up some other mistakes as well.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 1/02/23 7:33 am, Stefan Ram wrote:
> Thomas Passin <list1@tompassin.net> writes:

> Some people say it is a function now so that you can redefine it.

Well, that's one benefit, but I wouldn't say it's the main one.

The point is really that you can do *anything* with it now that
you can do with a regular function -- pass it as an argument,
wrap it with another function, define your own function with a
similar signature for duck-typing purposes, etc.

> It would still be possible to have a special syntax for the outermost
> expression of an expression statement that would allow one to omit
> the parentheses,

That's only one of the syntactic oddities of the old print
statement, thogh. There was also the >> thing, special treatment
of trailing commas, etc.

Also, introducing a paren-less call syntax would be a very big
and controversial change that would be way out of proportion to
the problem.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Wed, 1 Feb 2023 at 10:47, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
> That's only one of the syntactic oddities of the old print
> statement, thogh. There was also the >> thing, special treatment
> of trailing commas, etc.

"Soft space" (the trailing comma behaviour) was an incredibly complex
wart. Glad it's gone.

> Also, introducing a paren-less call syntax would be a very big
> and controversial change that would be way out of proportion to
> the problem.

Oddly enough, that WAS actually proposed recently - by Guido himself -
as a demonstration of the power of the new PEG parser:

https://mail.python.org/archives/list/python-ideas@python.org/thread/NCQX6ZIBREUTLS52VVG3DSZ43OEXJFTT/

(The mailing list archive messes up formatting a bit with REPL
transcripts, thinking they're quoted text.)

The general consensus was "allowing function calls without parens
causes more issues than it solves", with plenty of examples from other
programming languages to prove this - Ruby, while generally a decent
language, shows a rather nasty wart with this particular feature (see
"Ruby allows parens-less function calls" from Steven D'Aprano in that
thread). I don't think it'll ever happen in Python, but it's nice to
know that the parser is flexible enough. It means that other weird
cases, where the intuitive expectation is different, can be better
handled (see eg "with (x as y, a as b):" syntax).

Having print as a function is WAY better than having it as a special
case with lots of warts. And it's so much easier to add extra features
to it; for instance, how would you add a "flush after printing" flag
to Py2's print statement? With a function, it's easy - just print(...,
flush=True).

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 1/31/2023 6:18 PM, Greg Ewing wrote:
> On 1/02/23 7:33 am, Stefan Ram wrote:
>> Thomas Passin <list1@tompassin.net> writes:
>
>>    Some people say it is a function now so that you can redefine it.

Hmm, I didn't write these quotes. Maybe someone got confused by the
depth of the nested replies in this thread. Easy enough to do.

> Well, that's one benefit, but I wouldn't say it's the main one.
>
> The point is really that you can do *anything* with it now that
> you can do with a regular function -- pass it as an argument,
> wrap it with another function, define your own function with a
> similar signature for duck-typing purposes, etc.
>
>>    It would still be possible to have a special syntax for the outermost
>>    expression of an expression statement that would allow one to omit
>>    the parentheses,
>
> That's only one of the syntactic oddities of the old print
> statement, thogh. There was also the >> thing, special treatment
> of trailing commas, etc.
>
> Also, introducing a paren-less call syntax would be a very big
> and controversial change that would be way out of proportion to
> the problem.
>

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 01/02/2023 11.59, Greg Ewing wrote:
> On 31/01/23 10:24 pm, Muttley@dastardlyhq.com wrote:
>> All languages have their ugly corners due to initial design mistakes
>> and/or
>> constraints. Eg: java with the special behaviour of its string class, C++
>> with "=0" pure virtual declaration. But they don't dump them and make
>> all old
>> code suddenly cease to execute.
>
> No, but it was decided that Python 3 would have to be backwards
> incompatible, mainly to sort out the Unicode mess. Given that,
> the opportunity was taken to clean up some other mistakes as well.

+1
and the move to Unicode has opened-up the Python community beyond the
US, to embrace 'the world' - a proposition (still) not well-recognised
by (only) English-speakers/writers/readers.


Even though the proposition has a troll-bait smell to it:-

1 nothing "ceased to execute" and Python 2 was maintained and developed
for quite some time and in-parallel to many Python 3 releases.

2 the only constant in this business is 'change'. I'd rather cope with
an evolution in this language (which we know and love), than one day
realise that it has become dated or inflexible, and have to learn a new,
replacement, language!

--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 1/02/23 1:17 pm, dn wrote:
> 1 nothing "ceased to execute" and Python 2 was maintained and developed
> for quite some time and in-parallel to many Python 3 releases.

And a lot of effort was put into making the transition as easy
as possible, e.g. 2to3, and the features added to 2.7 to make
it easier to write code that would work in both versions.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 2023-01-31, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:

> That's only one of the syntactic oddities of the old print
> statement, thogh. There was also the >> thing, special treatment
> of trailing commas, etc.

In "old" Python I used to use the trailing comma extensively, but I
could never get myself to use the >> thing. I don't know why, but it
just felt wrong.

--
Grant


--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Tue, 31 Jan 2023 21:00:53 +0000
Mark Bourne <nntp.mbourne@spamgourmet.com> wrote:
>Greg Ewing wrote:
>> On 30/01/23 10:41 pm, Muttley@dastardlyhq.com wrote:
>>> What was the point of the upheaval of converting
>>> the print command in python 2 into a function in python 3 if as a
>>> function
>>> print() doesn't return anything useful?
>>
>> It was made a function because there's no good reason for it
>> to have special syntax in the language.
>
>I think I saw somewhere that making print a function also had something
>to do with being able to add extra keyword arguments like sep and end.
>The syntax for printing to a specific file already seemed a bit odd with
>the print statement, and adding extra arguments would have made it even
>more clunky (yeah, I know ">>" is similar to C++ streams, but it looks
>out of place in Python).

Why couldn't they just keep "print" and call the function , oh I dunno,
"printf" ? :)


--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Wed, 1 Feb 2023 11:59:25 +1300
Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
>On 31/01/23 10:24 pm, Muttley@dastardlyhq.com wrote:
>> All languages have their ugly corners due to initial design mistakes and/or
>> constraints. Eg: java with the special behaviour of its string class, C++
>> with "=0" pure virtual declaration. But they don't dump them and make all old
>
>> code suddenly cease to execute.
>
>No, but it was decided that Python 3 would have to be backwards
>incompatible, mainly to sort out the Unicode mess. Given that,
>the opportunity was taken to clean up some other mistakes as well.

Unicode is just a string of bytes. C supports it with a few extra library
functions to get unicode length vs byte length and similar. Its really
not that hard. Rewriting an entire language just to support that sounds a
bit absurd to me but hey ho...


--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Wed, 1 Feb 2023 13:17:33 +1300
dn <PythonList@DancesWithMice.info> wrote:
>On 01/02/2023 11.59, Greg Ewing wrote:
>> On 31/01/23 10:24 pm, Muttley@dastardlyhq.com wrote:
>>> All languages have their ugly corners due to initial design mistakes
>>> and/or
>>> constraints. Eg: java with the special behaviour of its string class, C++
>>> with "=0" pure virtual declaration. But they don't dump them and make
>>> all old
>>> code suddenly cease to execute.
>>
>> No, but it was decided that Python 3 would have to be backwards
>> incompatible, mainly to sort out the Unicode mess. Given that,
>> the opportunity was taken to clean up some other mistakes as well.
>
>+1
>and the move to Unicode has opened-up the Python community beyond the
>US, to embrace 'the world' - a proposition (still) not well-recognised
>by (only) English-speakers/writers/readers.
>
>
>Even though the proposition has a troll-bait smell to it:-
>
>1 nothing "ceased to execute" and Python 2 was maintained and developed
>for quite some time and in-parallel to many Python 3 releases.

MacOS only comes with python3 now. If you have a whole load of python2 code
you want to run you now have to manually install python2 yourself.

>2 the only constant in this business is 'change'. I'd rather cope with
>an evolution in this language (which we know and love), than one day

Its not evolution, its revolution. Evolution retains old functionality.

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Wed, 1 Feb 2023 08:56:40 -0000 (UTC), Muttley wrote:


> Why couldn't they just keep "print" and call the function , oh I dunno,
> "printf" ?

<Venting> Why does every language have to invent their own function to
print to the console that is very similar but not the same as the rest of
the herd?</Venting>

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 2023-02-01 09:00:39 -0000, Muttley@dastardlyhq.com wrote:
> Its not evolution, its revolution. Evolution retains old functionality.

Tell a penguin that it can fly :-)

hp

--
_ | Peter J. Holzer | Story must make more sense than reality.
|_|_) | |
| | | hjp@hjp.at | -- Charles Stross, "Creative writing
__/ | http://www.hjp.at/ | challenge!"
Re: evaluation question [ In reply to ]
On 2023-02-01, Muttley@dastardlyhq.com <Muttley@dastardlyhq.com> wrote:
>
>>No, but it was decided that Python 3 would have to be backwards
>>incompatible, mainly to sort out the Unicode mess. Given that,
>>the opportunity was taken to clean up some other mistakes as well.
>
> Unicode is just a string of bytes.

No it isn't. Certain _encodings_ of Unicode are strings of bytes
(UTF-8, for example).

> C supports it with a few extra library functions to get unicode
> length vs byte length and similar. Its really not that
> hard.

It is, actually.

C (the language) doesn't support Unicode at all. There are, however,
libraries that can be used to deal with it.

> Rewriting an entire language just to support that sounds a bit
> absurd to me but hey ho...

Feel free to maintain your own fork of 2.7 :)

The 2.7->3 incompatibility that created the most work for me was
bytes.
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 2023-02-01, Peter J. Holzer <hjp-python@hjp.at> wrote:
> On 2023-02-01 09:00:39 -0000, Muttley@dastardlyhq.com wrote:
>> Its not evolution, its revolution. Evolution retains old functionality.
>
> Tell a penguin that it can fly :-)

Penguins can fly. They just do it underwater...


--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Thu, 2 Feb 2023 at 04:29, <Muttley@dastardlyhq.com> wrote:
>
> On Wed, 1 Feb 2023 11:59:25 +1300
> Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
> >On 31/01/23 10:24 pm, Muttley@dastardlyhq.com wrote:
> >> All languages have their ugly corners due to initial design mistakes and/or
> >> constraints. Eg: java with the special behaviour of its string class, C++
> >> with "=0" pure virtual declaration. But they don't dump them and make all old
> >
> >> code suddenly cease to execute.
> >
> >No, but it was decided that Python 3 would have to be backwards
> >incompatible, mainly to sort out the Unicode mess. Given that,
> >the opportunity was taken to clean up some other mistakes as well.
>
> Unicode is just a string of bytes. C supports it with a few extra library
> functions to get unicode length vs byte length and similar. Its really
> not that hard. Rewriting an entire language just to support that sounds a
> bit absurd to me but hey ho...
>

No, Unicode is NOT a string of bytes. UTF-8 is a string of bytes, but
Unicode is not.

If you disagree with the way Python has been developed, you're welcome
to fork Python 2.7 and make your own language (but not called Python).
Meanwhile, the rest of us really appreciate the fact that Python
supports Unicode properly, not just as "a string of bytes". Also, be
sure to deal with the technical debt of refusing to ever remove any
feature. I'm curious how many dev hours that costs you.

Incidentally, the bytes->unicode transformation wasn't Python 3's
biggest reason for being. See https://peps.python.org/pep-3100/ for
details.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Thu, 2 Feb 2023 at 04:26, <Muttley@dastardlyhq.com> wrote:
>
> Its not evolution, its revolution. Evolution retains old functionality.
>

By the way, I'd like to see your opinions on eternal retention of old
functionality. Which of these features are you willing to put effort
into supporting?

1) Long integer constants eg 1234L which are the long type rather than
the int type
2) dict.has_key method, doing the same job as "key in dict"
3) The input() function, which automatically evals what was entered at
the keyboard
4) `x` which does the same as repr(x)
5) "from module import *" inside a function

Retaining old functionality is all well and good, but there are
limits, especially when the old functionality is downright wrong
(input vs raw_input). Before you complain about other people's
decisions, find out how many hours of YOUR time you're willing to
invest into a project.

Or alternatively, how many dollars you would spend on it. Let's
pretend that you can pay for as many core Python developers as you
like for USD 150,000 a year each. (See job posting
https://jobs.pyfound.org/apply/TwgMP1b4OV/Security-Developer-In-Residence
for where I got that figure from.) How many are you personally willing
to hire in order to have these features maintained?

It's easy to whine. Much harder to actually do something about it.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 2/1/23 3:59 AM, Muttley@dastardlyhq.com wrote:
> On Wed, 1 Feb 2023 11:59:25 +1300
> Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
>> On 31/01/23 10:24 pm, Muttley@dastardlyhq.com wrote:
>>> All languages have their ugly corners due to initial design mistakes and/or
>>> constraints. Eg: java with the special behaviour of its string class, C++
>>> with "=0" pure virtual declaration. But they don't dump them and make all old
>>> code suddenly cease to execute.
>> No, but it was decided that Python 3 would have to be backwards
>> incompatible, mainly to sort out the Unicode mess. Given that,
>> the opportunity was taken to clean up some other mistakes as well.
> Unicode is just a string of bytes. C supports it with a few extra library
> functions to get unicode length vs byte length and similar. Its really
> not that hard. Rewriting an entire language just to support that sounds a
> bit absurd to me but hey ho...
>
No, Unicode is a string of 21 bit characters. UTF-8 is a representation
that uses bytes, but isn't itself "Unicode".

The key fact is that a "String" variable is indexed not by bytes of
UTF-8 encoding, but by actual characters.

Python3 will store a string as either a sequence of Bytes if the data is
all Latin-1, as a sequence of 16-bit words if the data all fits on th
BMP, and a sequence of 32 bit words if it has a value outside the BMP.

--
Richard Damon

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 2/1/23 12:46 PM, Grant Edwards wrote:
> C (the language) doesn't support Unicode at all. There are, however,
> libraries that can be used to deal with it.

No, it does, but only optionally.

<uchar.h> provides functions that manipulate Unicode "Characters"

The type char32_t will hold Unicode Code Points, and you can define
string literals of that type with

U"string" notation.


--
Richard Damon

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 1 Feb 2023 17:31:02 GMT, Stefan Ram wrote:

> rbowman <bowman@montana.com> writes:
>><Venting> Why does every language have to invent their own function to
>>print to the console that is very similar but not the same as the rest
>>of the herd?</Venting>
>
> Why do there have to be different languages at all?

https://homepages.cwi.nl/~steven/abc/programmers/introduction.html

"Why ABC?
The answer to the question 'Why a new language?' is the same as the answer
to the question 'Why new computers?': because they can help you do the job
better. With the choice between a language where it will take a week to
write a program, and a language where it will take an afternoon, most
people will choose the latter."

That leads to the question of when Van Rossum was looking for a hobby
project, why not extend ABC? Or Pike?

https://pike.lysator.liu.se/about/history/

Then there is the question of how a new language becomes popular. When
Matsumoto developed Ruby it was almost 4 years before there was any
coherent English documentation. How did it get traction?

How about Go? Thompson and Pike hate C++ (with cause) so they went back to
C and reworked it. Then there is C++ itself, which was released before its
time.

There are many more obscure languages when someone saw a need. Then there
are features the propagate like lambdas. Everyone came down with lambda
envy and shoehorned them into the language one way or the other.

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Wed, 1 Feb 2023 18:28:04 +0100
"Peter J. Holzer" <hjp-python@hjp.at> wrote:
>--b2nljkb3mdefsdhx
>Content-Type: text/plain; charset=us-ascii
>Content-Disposition: inline
>Content-Transfer-Encoding: quoted-printable
>
>On 2023-02-01 09:00:39 -0000, Muttley@dastardlyhq.com wrote:
>> Its not evolution, its revolution. Evolution retains old functionality.
>
>Tell a penguin that it can fly :-)

Yeah ok :) But the ancestors of penguins didn't wake up one morning, flap
their wings and fall out the tree, it happened gradually. Python2 syntax
could have been retained for X versions of 3 just as C++ keeps old stuff
until its eventually deprecated them removed.

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Thu, 2 Feb 2023 09:31:46 -0000 (UTC), Muttley wrote:


> Yeah ok But the ancestors of penguins didn't wake up one morning, flap
> their wings and fall out the tree, it happened gradually. Python2 syntax
> could have been retained for X versions of 3 just as C++ keeps old stuff
> until its eventually deprecated them removed.

Isn't that prolonging the agony? I had some 2.7 scripts I had to move to
3. It wasn't that painful and I learned the new syntax. Being lazy if they
still worked I would have kept using 2.7 syntax until someday it really
went away.

MS did it big time with VB .NET. I'm sure there still are people
maintaining and extending old-style VB until it ceases to work altogether.
Then they'll be faced with the same learning curve most people suffered
through 20 years ago.
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Fri, 3 Feb 2023 at 04:48, <Muttley@dastardlyhq.com> wrote:
> Yeah ok :) But the ancestors of penguins didn't wake up one morning, flap
> their wings and fall out the tree, it happened gradually. Python2 syntax
> could have been retained for X versions of 3 just as C++ keeps old stuff
> until its eventually deprecated them removed.

What, you mean Python 2.7 could have continued to be supported until
Python 3.8 (yes, that's not a typo) was released?

It was.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
Muttley@dastardlyhq.com wrote:
> On Wed, 1 Feb 2023 18:28:04 +0100
> "Peter J. Holzer" <hjp-python@hjp.at> wrote:
>> --b2nljkb3mdefsdhx
>> Content-Type: text/plain; charset=us-ascii
>> Content-Disposition: inline
>> Content-Transfer-Encoding: quoted-printable
>>
>> On 2023-02-01 09:00:39 -0000, Muttley@dastardlyhq.com wrote:
>>> Its not evolution, its revolution. Evolution retains old functionality.
>>
>> Tell a penguin that it can fly :-)
>
> Yeah ok :) But the ancestors of penguins didn't wake up one morning, flap
> their wings and fall out the tree, it happened gradually. Python2 syntax
> could have been retained for X versions of 3 just as C++ keeps old stuff
> until its eventually deprecated them removed.

Python 2 *was* retained for X versions of Python 3. From a quick check,
Python 3.0 was released in December 2008 and Python 2 support ended in
January 2020 - by which time Python 3 was up to 3.8 as ChrisA mentioned.
That's about an 11 year transition period, which is hardly sudden!
Python 3 *was* the point at which the features deprecated in Python 2
were removed.

The problem is, a lot seemed to ignore Python 3 for the first 12 years
and then suddenly panic because Python 2 support had ended.

--
Mark.
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 3/02/23 5:09 am, Muttley@dastardlyhq.com wrote:
> What if its 10s of thousands of lines of
> core production code? If the company it belongs to wants to add new Python 3
> features it can't just plug them into the code because it won't run under
> Python 3, they have to do a full overhaul or even complete rewrite and that
> costs a lot of time and money.

A possible strategy in that case would have been to incrementally
rewrite it in such a way that the code would run in both 2.7 and 3.x
(various features were added to 2.7 to make that possible).

When that point is reached, you can then switch to running it with
Python 3 and start using the new features.

Also, if you're a company whose business is totally reliant on some
piece of code, it would be prudent to plan ahead and budget for
rewriting or replacing it at some point.

People seem to think that because code doesn't wear out like
hardware, you don't have to budget for replacing it. But you can't
expect third party software to be maintained forever -- particularly
when, as with Python, the maintenance is mainly being done by
*volunteers*.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Thu, 2 Feb 2023 16:09:09 -0000 (UTC), Muttley wrote:


> What if its not a few scripts? What if its 10s of thousands of lines of
> core production code? If the company it belongs to wants to add new
> Python 3 features it can't just plug them into the code because it won't
> run under Python 3, they have to do a full overhaul or even complete
> rewrite and that costs a lot of time and money.

Tell me about it... Esri is the 500 pound gorilla in the GIS industry.
They haven't been secretive about their roadmap but the tools people have
been using for almost 20 years are going, going, GONE.

Part of that is their scripting language ArcPy moved to 3.8. It's a minor
inconvenience for me to update some old scripts and to develop with 3 but
a lot of firms have those thousands of lines of code they've developed
over the years in ArcPy for GIS data manipulation.

More painful for me is the C++ API is also gone. Legacy sites have a
couple of more years before it's all over. That leaves me with a foot in
both worlds.

> Unfortunately a lot of people who've never worked in large institutions
> with huge code bases don't understand this.

I don't work in a large company but I deal with about 25 years of legacy
code every day. The core functionality is good but the time and money is
spent putting lipstick on a pig.

Technical debt is an industry wide problem.

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 02/02/2023 09:31, Muttley@dastardlyhq.com wrote:
> On Wed, 1 Feb 2023 18:28:04 +0100
> "Peter J. Holzer" <hjp-python@hjp.at> wrote:
>> --b2nljkb3mdefsdhx
>> Content-Type: text/plain; charset=us-ascii
>> Content-Disposition: inline
>> Content-Transfer-Encoding: quoted-printable
>>
>> On 2023-02-01 09:00:39 -0000, Muttley@dastardlyhq.com wrote:
>>> Its not evolution, its revolution. Evolution retains old functionality.
>> Tell a penguin that it can fly :-)
> Yeah ok :) But the ancestors of penguins didn't wake up one morning, flap
> their wings and fall out the tree, it happened gradually. Python2 syntax
> could have been retained for X versions of 3 just as C++ keeps old stuff
> until its eventually deprecated them removed.
Yeah?  So what would this do:
    print ()
In Python 2 this prints an empty tuple.
In Python 3 this is a call to the print function with no arguments,
which prints a blank line.
You can't have it both ways.
In any case, supporting two different syntaxes simultaneously would be
messy and difficult to maintain.
Better a clean break, with Python 2 support continuing for a long time
(as it was).
Best wishes
Rob Cliffe
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Tue, 7 Feb 2023 at 18:49, Rob Cliffe via Python-list
<python-list@python.org> wrote:
>
>
>
> On 02/02/2023 09:31, Muttley@dastardlyhq.com wrote:
> > On Wed, 1 Feb 2023 18:28:04 +0100
> > "Peter J. Holzer" <hjp-python@hjp.at> wrote:
> >> --b2nljkb3mdefsdhx
> >> Content-Type: text/plain; charset=us-ascii
> >> Content-Disposition: inline
> >> Content-Transfer-Encoding: quoted-printable
> >>
> >> On 2023-02-01 09:00:39 -0000, Muttley@dastardlyhq.com wrote:
> >>> Its not evolution, its revolution. Evolution retains old functionality.
> >> Tell a penguin that it can fly :-)
> > Yeah ok :) But the ancestors of penguins didn't wake up one morning, flap
> > their wings and fall out the tree, it happened gradually. Python2 syntax
> > could have been retained for X versions of 3 just as C++ keeps old stuff
> > until its eventually deprecated them removed.
> Yeah? So what would this do:
> print ()
> In Python 2 this prints an empty tuple.
> In Python 3 this is a call to the print function with no arguments,
> which prints a blank line.
> You can't have it both ways.
> In any case, supporting two different syntaxes simultaneously would be
> messy and difficult to maintain.

There are two solutions to this. The most obvious is "from __future__
import print_function", which gives you the full power and flexibility
of Py3 in anything back as far as 2.6; the other is to always pass a
single string argument to print:

print("")
print("spam %d ham %d" % (spam, ham))

This will work in pretty much ANY version of Python [1] and doesn't
require any sort of per-module configuration.

The idea that old syntax should be retained is only part of the story.
While it's definitely important to not break old code unnecessarily,
it is far more important to ensure that there's *some way* to write
code that works across multiple versions. That's what we have here:
even with the breaking changes, there was usually a way to make your
code run identically on multiple versions. Sometimes this means a
compatibility shim at the top, like "try: raw_input; except NameError:
raw_input = input", and sometimes it means following a discipline like
putting b"..." for all strings that need to be bytes. But there always
needs to be a way.

ChrisA

[1] This is the part where someone points out to me that it wouldn't
work in Python 1.3 or something
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 07/02/2023 08:15, Chris Angelico wrote:
> On Tue, 7 Feb 2023 at 18:49, Rob Cliffe via Python-list
> <python-list@python.org> wrote:
>>
>>
>> On 02/02/2023 09:31, Muttley@dastardlyhq.com wrote:
>>> On Wed, 1 Feb 2023 18:28:04 +0100
>>> "Peter J. Holzer" <hjp-python@hjp.at> wrote:
>>>> --b2nljkb3mdefsdhx
>>>> Content-Type: text/plain; charset=us-ascii
>>>> Content-Disposition: inline
>>>> Content-Transfer-Encoding: quoted-printable
>>>>
>>>> On 2023-02-01 09:00:39 -0000, Muttley@dastardlyhq.com wrote:
>>>>> Its not evolution, its revolution. Evolution retains old functionality.
>>>> Tell a penguin that it can fly :-)
>>> Yeah ok :) But the ancestors of penguins didn't wake up one morning, flap
>>> their wings and fall out the tree, it happened gradually. Python2 syntax
>>> could have been retained for X versions of 3 just as C++ keeps old stuff
>>> until its eventually deprecated them removed.
>> Yeah? So what would this do:
>> print ()
>> In Python 2 this prints an empty tuple.
>> In Python 3 this is a call to the print function with no arguments,
>> which prints a blank line.
>> You can't have it both ways.
>> In any case, supporting two different syntaxes simultaneously would be
>> messy and difficult to maintain.
> There are two solutions to this. The most obvious is "from __future__
> import print_function", which gives you the full power and flexibility
> of Py3 in anything back as far as 2.6; the other is to always pass a
> single string argument to print:
>
> print("")
> print("spam %d ham %d" % (spam, ham))
>
> This will work in pretty much ANY version of Python [1] and doesn't
> require any sort of per-module configuration.
>
> The idea that old syntax should be retained is only part of the story.
> While it's definitely important to not break old code unnecessarily,
> it is far more important to ensure that there's *some way* to write
> code that works across multiple versions. That's what we have here:
> even with the breaking changes, there was usually a way to make your
> code run identically on multiple versions. Sometimes this means a
> compatibility shim at the top, like "try: raw_input; except NameError:
> raw_input = input", and sometimes it means following a discipline like
> putting b"..." for all strings that need to be bytes. But there always
> needs to be a way.
>
> ChrisA
>
> [1] This is the part where someone points out to me that it wouldn't
> work in Python 1.3 or something
You are quite right Chris, and indeed I have used both solutions in my
own code to keep 2-3 compatibility.
I was just pointing out that continuing to support Python 2 syntax in
Python 3 was not an option.
Best wishes
Rob Cliffe
--
https://mail.python.org/mailman/listinfo/python-list
RE: evaluation question [ In reply to ]
Ok I understand


Sent from Mail<https://go.microsoft.com/fwlink/?LinkId=550986> for Windows

From: Rob Cliffe via Python-list<mailto:python-list@python.org>
Sent: Tuesday, February 7, 2023 6:54 PM
To: Chris Angelico<mailto:rosuav@gmail.com>; python-list@python.org<mailto:python-list@python.org>
Subject: Re: evaluation question



On 07/02/2023 08:15, Chris Angelico wrote:
> On Tue, 7 Feb 2023 at 18:49, Rob Cliffe via Python-list
> <python-list@python.org> wrote:
>>
>>
>> On 02/02/2023 09:31, Muttley@dastardlyhq.com wrote:
>>> On Wed, 1 Feb 2023 18:28:04 +0100
>>> "Peter J. Holzer" <hjp-python@hjp.at> wrote:
>>>> --b2nljkb3mdefsdhx
>>>> Content-Type: text/plain; charset=us-ascii
>>>> Content-Disposition: inline
>>>> Content-Transfer-Encoding: quoted-printable
>>>>
>>>> On 2023-02-01 09:00:39 -0000, Muttley@dastardlyhq.com wrote:
>>>>> Its not evolution, its revolution. Evolution retains old functionality.
>>>> Tell a penguin that it can fly :-)
>>> Yeah ok :) But the ancestors of penguins didn't wake up one morning, flap
>>> their wings and fall out the tree, it happened gradually. Python2 syntax
>>> could have been retained for X versions of 3 just as C++ keeps old stuff
>>> until its eventually deprecated them removed.
>> Yeah? So what would this do:
>> print ()
>> In Python 2 this prints an empty tuple.
>> In Python 3 this is a call to the print function with no arguments,
>> which prints a blank line.
>> You can't have it both ways.
>> In any case, supporting two different syntaxes simultaneously would be
>> messy and difficult to maintain.
> There are two solutions to this. The most obvious is "from __future__
> import print_function", which gives you the full power and flexibility
> of Py3 in anything back as far as 2.6; the other is to always pass a
> single string argument to print:
>
> print("")
> print("spam %d ham %d" % (spam, ham))
>
> This will work in pretty much ANY version of Python [1] and doesn't
> require any sort of per-module configuration.
>
> The idea that old syntax should be retained is only part of the story.
> While it's definitely important to not break old code unnecessarily,
> it is far more important to ensure that there's *some way* to write
> code that works across multiple versions. That's what we have here:
> even with the breaking changes, there was usually a way to make your
> code run identically on multiple versions. Sometimes this means a
> compatibility shim at the top, like "try: raw_input; except NameError:
> raw_input = input", and sometimes it means following a discipline like
> putting b"..." for all strings that need to be bytes. But there always
> needs to be a way.
>
> ChrisA
>
> [1] This is the part where someone points out to me that it wouldn't
> work in Python 1.3 or something
You are quite right Chris, and indeed I have used both solutions in my
own code to keep 2-3 compatibility.
I was just pointing out that continuing to support Python 2 syntax in
Python 3 was not an option.
Best wishes
Rob Cliffe
--
https://mail.python.org/mailman/listinfo/python-list

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Mon, Jan 30, 2023 at 09:41:03AM -0000, Muttley@dastardlyhq.com wrote:
> >Because print() returns nothing (i.e., the statement x is None is True).
>
> I don't understand this. What was the point of the upheaval of converting
> the print command in python 2 into a function in python 3 if as a function
> print() doesn't return anything useful? Surely even the length of the
> formatted string as per C's sprintf() function would be helpful?

Python is far from the only language that allows functions to return
nothing explicit. Statically typed languages typically use the void
keyword or something similar to indicate this, and dynamically typed
languages often just don't explicitly return anything. [.Some
languages, like Perl, just implicitly return the value of the last
expression, or something of the sort, but some do not.] In Pascal, in
fact, there are two different types of subroutines to distinguish
between those things: functions return a value, and procedures do not.
Modern languages commonly don't provide this distinction because by
and large it is unnecessary.

Typically the reason NOT to return a value is that the function is
designed to DO something, rather than to calculate some value.
Examples might be updating the appearance of a UI widget, printing
some information to the screen, or twiddling some bits in a register
(i.e. in-place update of a value). They don't need to return anything
because the "output" is whatever was done. In some languages it might
be typical to return a status indicating success or failure, but in
many languages this is unnecessary; status may be returned via a
parameter provided for the purpose, or in many languages, success can
be assumed, whereas failure will raise an exception.

If it's the case that you simply want to know the length of the string
that will be printed, you can, rather than expecting the I/O function
to tell that to you, figure it out for yourself ahead of time, e.g.
instead of:

username = "John Smith"
job = "Python programmer"

# this doesn't work as desired
len = print(f"{username} has occupation {job}.")
print(len)
...

You would do this instead:

message = f"{username} has the occupation {job}."
message_length = len(message)
print(message)
print(message_length)
...

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Sat, 11 Feb 2023 at 07:36, Python <python@bladeshadow.org> wrote:
> If it's the case that you simply want to know the length of the string
> that will be printed, you can, rather than expecting the I/O function
> to tell that to you, figure it out for yourself ahead of time, e.g.
> instead of:
>
> username = "John Smith"
> job = "Python programmer"
>
> # this doesn't work as desired
> len = print(f"{username} has occupation {job}.")
> print(len)
> ...
>
> You would do this instead:
>
> message = f"{username} has the occupation {job}."
> message_length = len(message)
> print(message)
> print(message_length)
> ...
>

It's worth noting WHY output functions often return a byte count. It's
primarily for use with nonblocking I/O, with something like this:

buffer = b".............."
buffer = buffer[os.write(fd, buffer):]

It's extremely important to be able to do this sort of thing, but not
with the print function, which has a quite different job.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Sat, Feb 11, 2023 at 08:30:22AM +1100, Chris Angelico wrote:
> On Sat, 11 Feb 2023 at 07:36, Python <python@bladeshadow.org> wrote:
> > You would do this instead:
> >
> > message = f"{username} has the occupation {job}."
> > message_length = len(message)
> > print(message)
> > print(message_length)
> > ...
> >
>
> It's worth noting WHY output functions often return a byte count. It's
> primarily for use with nonblocking I/O, with something like this:
>
> buffer = b".............."
> buffer = buffer[os.write(fd, buffer):]
>
> It's extremely important to be able to do this sort of thing, but not
> with the print function, which has a quite different job.

I would agree with this only partially. Your case applies to
os.write(), which is essentially just a wrapper around the write()
system call, which has that sort of property... though it applies also
to I/O in blocking mode, particularly on network sockets, where the
number of bytes you asked to write (or read) may not all have been
transferred, necessitating trying in a loop.

However, Python's print() function is more analogous to C's printf(),
which returns the number of characters converted for an entirely
different reason... It's precisely so that you'll know what the length
of the string that was converted is. This is most useful with the
*snprintf() variants where you're actually concerned about overrunning
the buffer you've provided for the output string, so you can realloc()
the buffer if it was indeed too small, but it is also useful in the
context of, say, a routine to format text according to the size of
your terminal. In that context it really has nothing to do with
blocking I/O or socket behavior.

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On 2/10/2023 4:55 PM, Python wrote:
> However, Python's print() function is more analogous to C's printf(),
> which returns the number of characters converted for an entirely
> different reason... It's precisely so that you'll know what the length
> of the string that was converted is. This is most useful with the
> *snprintf() variants where you're actually concerned about overrunning
> the buffer you've provided for the output string, so you can realloc()
> the buffer if it was indeed too small, but it is also useful in the
> context of, say, a routine to format text according to the size of
> your terminal. In that context it really has nothing to do with
> blocking I/O or socket behavior.

But none of that applies to the Python print() function. There are no
buffers to overrun, no reason to know the length of the printed string,
no re-allocating of a buffer. It's certainly possible that one might
want to know the actual physical length of a displayed string - perhaps
to display it on a graphic - but now we're getting into font metrics and
such things, and we'll be doing something more active than displaying on
a terminal via stdout.

I don't know why the print() function doesn't return anything, but I'm
fine with it. I've never felt that I needed to know.
--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Sat, 11 Feb 2023 at 10:07, Thomas Passin <list1@tompassin.net> wrote:
>
> On 2/10/2023 4:55 PM, Python wrote:
> > However, Python's print() function is more analogous to C's printf(),
> > which returns the number of characters converted for an entirely
> > different reason... It's precisely so that you'll know what the length
> > of the string that was converted is. This is most useful with the
> > *snprintf() variants where you're actually concerned about overrunning
> > the buffer you've provided for the output string, so you can realloc()
> > the buffer if it was indeed too small, but it is also useful in the
> > context of, say, a routine to format text according to the size of
> > your terminal. In that context it really has nothing to do with
> > blocking I/O or socket behavior.
>
> But none of that applies to the Python print() function. There are no
> buffers to overrun, no reason to know the length of the printed string,
> no re-allocating of a buffer. It's certainly possible that one might
> want to know the actual physical length of a displayed string - perhaps
> to display it on a graphic - but now we're getting into font metrics and
> such things, and we'll be doing something more active than displaying on
> a terminal via stdout.

It's sometimes possible to have that go to stdout (maybe you want to
do columnar text or something), but yeah, you'll generally do that by
formatting first, then doing the measurement, then displaying.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
RE: evaluation question [ In reply to ]
There are no doubt many situations someone wants to know how long something
will be when printed but often at lower levels.

In variable-width fonts, for example, the number of characters does not
really line up precisely with how many characters. Some encodings use a
varying number of bytes and, again, the width of the output varies.

So for people who want to make 2-D formatted output like tables, or who want
to wrap lines longer than N characters, you more often let some deeper
software accept your data and decide on formatting it internally and either
print it at once, when done calculating, or in the case of some old-style
terminals, use something like the curses package that may use escape
sequences to update the screen more efficiently in various ways.

If someone wants more control over what they print, rather than asking the
print() function to return something that is mostly going to be ignored,
they can do the things others have already suggested here. You can make your
message parts in advance and measure their length or anything else before
you print. Or make a wrapper that does something for you before calling
print, perhaps only for common cases and then returns the length to you
after printing.

I wonder if the next request will be for print() to know what your output
device is and other current settings so it return the width your text takes
up in pixels in the current font/size ...

I add a tidbit that many ways of printing allow you to specify the width you
want something printed in such as you want a floating point value with so
many digits after the decimal point in a zero or space padded field on the
left. So there are ways to calculate in advance for many common cases as to
how long each part will be if you specify it. Besides, I am not really sure
if "print" even knows easily how many characters it is putting out as it
chews away on the many things in your request and calls dunder methods in
objects so they display themselves and so on. I assume it can be made to
keep track, albeit I can imagine printing out an APL program with lots of
overwritten characters where the number of bytes sent is way more than the
number of spaces in the output.

Why are we even still talking about this? The answer to the question of why
print() does not return anything, let alone the number of characters
printed, is BECAUSE.


-----Original Message-----
From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org> On
Behalf Of Python
Sent: Friday, February 10, 2023 4:56 PM
To: python-list@python.org
Subject: Re: evaluation question

On Sat, Feb 11, 2023 at 08:30:22AM +1100, Chris Angelico wrote:
> On Sat, 11 Feb 2023 at 07:36, Python <python@bladeshadow.org> wrote:
> > You would do this instead:
> >
> > message = f"{username} has the occupation {job}."
> > message_length = len(message)
> > print(message)
> > print(message_length)
> > ...
> >
>
> It's worth noting WHY output functions often return a byte count. It's
> primarily for use with nonblocking I/O, with something like this:
>
> buffer = b".............."
> buffer = buffer[os.write(fd, buffer):]
>
> It's extremely important to be able to do this sort of thing, but not
> with the print function, which has a quite different job.

I would agree with this only partially. Your case applies to os.write(),
which is essentially just a wrapper around the write() system call, which
has that sort of property... though it applies also to I/O in blocking mode,
particularly on network sockets, where the number of bytes you asked to
write (or read) may not all have been transferred, necessitating trying in a
loop.

However, Python's print() function is more analogous to C's printf(), which
returns the number of characters converted for an entirely different
reason... It's precisely so that you'll know what the length of the string
that was converted is. This is most useful with the
*snprintf() variants where you're actually concerned about overrunning the
buffer you've provided for the output string, so you can realloc() the
buffer if it was indeed too small, but it is also useful in the context of,
say, a routine to format text according to the size of your terminal. In
that context it really has nothing to do with blocking I/O or socket
behavior.

--
https://mail.python.org/mailman/listinfo/python-list

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
On Fri, Feb 10, 2023 at 05:48:53PM -0500, Thomas Passin wrote:
> On 2/10/2023 4:55 PM, Python wrote:
> > However, Python's print() function is more analogous to C's printf(),
> > which returns the number of characters converted for an entirely
> > different reason... It's precisely so that you'll know what the length
> > of the string that was converted is. This is most useful with the
> > *snprintf() variants where you're actually concerned about overrunning
> > the buffer you've provided for the output string, so you can realloc()
> > the buffer if it was indeed too small, but it is also useful in the
> > context of, say, a routine to format text according to the size of
> > your terminal. In that context it really has nothing to do with
> > blocking I/O or socket behavior.
>
> But none of that applies to the Python print() function. There are no
> buffers to overrun, no reason to know the length of the printed string, no
> re-allocating of a buffer.

Indeed. But the OP originally compared print to printf, and I was
specifically addressing Chris' point about why I/O functions return
the number of bytes written, which was relevant to, but maybe a bit of
tangent to the original post.

> I don't know why the print() function doesn't return anything

You do though! :) You actually just explained why yourself... it's
because it just doesn't need to. But FWIW, I wasn't addressing this
point, because it had already been adequately covered in the thread.

There's good reason why Python's print and C's printf work
differently. In languages like C it makes sense that printf returns
the length of the string. printf is the means of all three of:

- formatting the string
- counting its length
- actually outputting the string to stdout (albeit indirectly).

This sort of breaks the rule of, "do one thing, and do it well," but
it does so in the name of efficiency. You might or might not want to
actually know the length of the formatted string, depending on what
you're doing with it. But the printf function basically needs to
calculate it anyway so that it can tell the underlying system calls
how many bytes to write (or tell stdio how many bytes it is adding to
its buffers, or whatever), and then stuffing that length in a register
to be returned to the caller is roughly free (it's probably using the
register that it's going to return already to do the counting), and
the caller can ignore it if it wants to. C aims to be as efficient as
possible so this is a good strategy.

Unlike C[*], since Python can already separate the formatting and
length calculation from sending the data to stdout (I demonstrated how
in my first post in the thread), it has no need for print to return
the length. As I mentioned in my earlier post, if Python encounters
an error condition it will raise an exception--which C can't do--so
there's no reason to return a status either. What else would it
return? Nothing else would really make sense.

-=-=-=-
* In C you could sprintf the string into a buffer, which would return
its length, and then call printf on the buffer, but that would be much
less efficient and a bit silly... UNLESS you actually needed to know
the length of the string beforehand, e.g. to calculate where to put
line breaks in a text justification routine, or something.

--
https://mail.python.org/mailman/listinfo/python-list
Re: evaluation question [ In reply to ]
?Why are we even still talking about this??

Because humans are social creatures and some contributors to the list like to discuss things in depth.


From: Python-list <python-list-bounces+gweatherby=uchc.edu@python.org> on behalf of avi.e.gross@gmail.com <avi.e.gross@gmail.com>
Date: Friday, February 10, 2023 at 6:19 PM
To: python-list@python.org <python-list@python.org>
Subject: RE: evaluation question
*** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. ***

There are no doubt many situations someone wants to know how long something
will be when printed but often at lower levels.

In variable-width fonts, for example, the number of characters does not
really line up precisely with how many characters. Some encodings use a
varying number of bytes and, again, the width of the output varies.

So for people who want to make 2-D formatted output like tables, or who want
to wrap lines longer than N characters, you more often let some deeper
software accept your data and decide on formatting it internally and either
print it at once, when done calculating, or in the case of some old-style
terminals, use something like the curses package that may use escape
sequences to update the screen more efficiently in various ways.

If someone wants more control over what they print, rather than asking the
print() function to return something that is mostly going to be ignored,
they can do the things others have already suggested here. You can make your
message parts in advance and measure their length or anything else before
you print. Or make a wrapper that does something for you before calling
print, perhaps only for common cases and then returns the length to you
after printing.

I wonder if the next request will be for print() to know what your output
device is and other current settings so it return the width your text takes
up in pixels in the current font/size ...

I add a tidbit that many ways of printing allow you to specify the width you
want something printed in such as you want a floating point value with so
many digits after the decimal point in a zero or space padded field on the
left. So there are ways to calculate in advance for many common cases as to
how long each part will be if you specify it. Besides, I am not really sure
if "print" even knows easily how many characters it is putting out as it
chews away on the many things in your request and calls dunder methods in
objects so they display themselves and so on. I assume it can be made to
keep track, albeit I can imagine printing out an APL program with lots of
overwritten characters where the number of bytes sent is way more than the
number of spaces in the output.

Why are we even still talking about this? The answer to the question of why
print() does not return anything, let alone the number of characters
printed, is BECAUSE.


-----Original Message-----
From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org> On
Behalf Of Python
Sent: Friday, February 10, 2023 4:56 PM
To: python-list@python.org
Subject: Re: evaluation question

On Sat, Feb 11, 2023 at 08:30:22AM +1100, Chris Angelico wrote:
> On Sat, 11 Feb 2023 at 07:36, Python <python@bladeshadow.org> wrote:
> > You would do this instead:
> >
> > message = f"{username} has the occupation {job}."
> > message_length = len(message)
> > print(message)
> > print(message_length)
> > ...
> >
>
> It's worth noting WHY output functions often return a byte count. It's
> primarily for use with nonblocking I/O, with something like this:
>
> buffer = b".............."
> buffer = buffer[os.write(fd, buffer):]
>
> It's extremely important to be able to do this sort of thing, but not
> with the print function, which has a quite different job.

I would agree with this only partially. Your case applies to os.write(),
which is essentially just a wrapper around the write() system call, which
has that sort of property... though it applies also to I/O in blocking mode,
particularly on network sockets, where the number of bytes you asked to
write (or read) may not all have been transferred, necessitating trying in a
loop.

However, Python's print() function is more analogous to C's printf(), which
returns the number of characters converted for an entirely different
reason... It's precisely so that you'll know what the length of the string
that was converted is. This is most useful with the
*snprintf() variants where you're actually concerned about overrunning the
buffer you've provided for the output string, so you can realloc() the
buffer if it was indeed too small, but it is also useful in the context of,
say, a routine to format text according to the size of your terminal. In
that context it really has nothing to do with blocking I/O or socket
behavior.

--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!nyKmKANNzMqWDt2IGH9-Vv63_bioBGOYeokJy5GupmZVZIelplk15rvc_5NNbt6afc9yukh8y5X5mZXDVgr_PhY$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!nyKmKANNzMqWDt2IGH9-Vv63_bioBGOYeokJy5GupmZVZIelplk15rvc_5NNbt6afc9yukh8y5X5mZXDVgr_PhY$>

--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!nyKmKANNzMqWDt2IGH9-Vv63_bioBGOYeokJy5GupmZVZIelplk15rvc_5NNbt6afc9yukh8y5X5mZXDVgr_PhY$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!nyKmKANNzMqWDt2IGH9-Vv63_bioBGOYeokJy5GupmZVZIelplk15rvc_5NNbt6afc9yukh8y5X5mZXDVgr_PhY$>
--
https://mail.python.org/mailman/listinfo/python-list
RE: evaluation question [ In reply to ]
Weatherby,

Of course you are right and people can, and do, discuss whatever they feel like.

My question is a bit more about asking if I am missing something here as my personal view is that we are not really exploring in more depth or breadth and are getting fairly repetitive as if in a typical SF time loop. How does one break out?

Languages often change and people do come and go so some topics can often be re-opened. This though is a somewhat focused forum and it is legitimate to ask if a conversation might best be taken elsewhere for now. The main focus is, at least in theory, aspects of python and mostly about the core as compared to very specific modules, let alone those nobody here has ever even used. Within that, it is fair at times to compare something in python to other languages or ask about perceived bugs or about possible future enhancements. We could discuss if "YIELD FROM" is just syntactic sugar as it often can be done with just the naked YIELD statement, or whether it really allows you to do innovative things, as an example.

But I think where this conversation has gone is fairly simple. The question was why print() does not return the number of characters printed. The answers boiled down to that this was not the design chosen and is mostly consistent with how python handles similar functions that return nothing when the change is largely "internal" in a sense. In addition, plenty of us have suggested alternate ways to get what the OP asked for, and also pointed out there are other things that someone may have wanted instead or in addition, including the actual number of bytes generated for encodings other than vanilla ASCII, or pixels if the text was rendered on a screen using variable width fonts and so on.

Some of the above already counted, in my mind, as adding depth or breadth to the original question. But if the conversation degrades to two or more sides largely talking past each other and not accepting what the other says, then perhaps a natural ending point has been reached. Call it a draw, albeit maybe a forfeit.

So, as part of my process, I am now stuck on hearing many questions as valid and others as not productive. I don't mean just here, but in many areas of my life. The answer is that historically, and in other ways, python took a specific path. Others took other paths. But once locked into this path, you run into goals of trying to remain consistent and not have new releases break older software or at least take time to deprecate it and give people time to adjust.

I have seen huge growing pains due to growth. An example is languages that have added features, such as promises and their variants and used them for many purposes such as allowing asynchronous execution using multiple methods or evaluating things in a more lazy way so they are done just in time. Some end up with some simple function call being augmented with quite a few additional functions with slightly different names and often different arguments and ways they are called that mostly should no longer be mixed with other variants of the function. You need compatibility with the old while allowing the new and then the newer and newest.

Had the language been built anew from scratch, it might be simpler and also more complex, as they would skip the older versions and pretty much use the shinier new version all the time, even as it often introduces many costs where they are not needed.

So it can be very valid to ask questions as long as you also LISTEN to the answers and try to accept them as aspects of reality. Yes, python could have had a different design and perhaps someday may have a different design. But that is not happening TODAY so for today, accept what is and accept advice on how you might get something like what you want when, and if, you need it. The goal often is to get the job done, not to do it the way you insist it has to be done.

At some point, unless someone has more to say with some new twist, it does become a bit annoying.

So let me say something slightly new now. I have been reading about interesting uses of the python WITH statement and how it works. Some of the examples are creating an object with dunder methods that get invoked on entry and exit that can do all kinds of things. One is the ability to modify a list in a way that can be rolled back if there is an error and it is quite simple. You make a copy of the original list on entry. Things are then done to the copy. And if you exit properly, you copy the modified list back on top of the original list. Errors that result simply unwind the serious of transactions by leaving the original list untouched.

Another example has your output stream redirected within the WITH and then put back in place after. What this allows, among many things, is for everything printed to be desrever. Now clearly, such a technique could also be used to capture what is going to be printed, and count how many bytes or characters it produced and make the result available after you exit the region. Heck, if fed a paragraph of text, it could not only print it but create one or more objects containing a detailed analysis including guessing what language it is in, translating it to English, pointing out spelling and grammar errors, and mailing you a copy! You can imagine quite a few side effects of calling print() but again, why would you put the functionality within print() versus in a function you wrote that does all that as well as calling print()?

But even assuming you code that properly and rewrite all your code as something like:

with capture:
print(...)

# use chars_written_within_width as a variable created within that holds what you want.


Is that really any better than several other ways we have suggested would work such as creating an f-string independently and then printing it which would handle quite a few use cases?

If others wish to keep debating this topic or enhancing it, fine. I am not judging but simply expressing the personal opinion that even if I might have more to add, I am not motivated to do so any longer. Then again, I may soon lose the motivation to be part of this forum and take up other hobbies ????


-----Original Message-----
From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org> On Behalf Of Weatherby,Gerard
Sent: Monday, February 13, 2023 10:16 AM
To: python-list@python.org
Subject: Re: evaluation question

“Why are we even still talking about this?”

Because humans are social creatures and some contributors to the list like to discuss things in depth.


From: Python-list <python-list-bounces+gweatherby=uchc.edu@python.org> on behalf of avi.e.gross@gmail.com <avi.e.gross@gmail.com>
Date: Friday, February 10, 2023 at 6:19 PM
To: python-list@python.org <python-list@python.org>
Subject: RE: evaluation question
*** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. ***

There are no doubt many situations someone wants to know how long something will be when printed but often at lower levels.

In variable-width fonts, for example, the number of characters does not really line up precisely with how many characters. Some encodings use a varying number of bytes and, again, the width of the output varies.

So for people who want to make 2-D formatted output like tables, or who want to wrap lines longer than N characters, you more often let some deeper software accept your data and decide on formatting it internally and either print it at once, when done calculating, or in the case of some old-style terminals, use something like the curses package that may use escape sequences to update the screen more efficiently in various ways.

If someone wants more control over what they print, rather than asking the
print() function to return something that is mostly going to be ignored, they can do the things others have already suggested here. You can make your message parts in advance and measure their length or anything else before you print. Or make a wrapper that does something for you before calling print, perhaps only for common cases and then returns the length to you after printing.

I wonder if the next request will be for print() to know what your output device is and other current settings so it return the width your text takes up in pixels in the current font/size ...

I add a tidbit that many ways of printing allow you to specify the width you want something printed in such as you want a floating point value with so many digits after the decimal point in a zero or space padded field on the left. So there are ways to calculate in advance for many common cases as to how long each part will be if you specify it. Besides, I am not really sure if "print" even knows easily how many characters it is putting out as it chews away on the many things in your request and calls dunder methods in objects so they display themselves and so on. I assume it can be made to keep track, albeit I can imagine printing out an APL program with lots of overwritten characters where the number of bytes sent is way more than the number of spaces in the output.

Why are we even still talking about this? The answer to the question of why
print() does not return anything, let alone the number of characters printed, is BECAUSE.


-----Original Message-----
From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org> On Behalf Of Python
Sent: Friday, February 10, 2023 4:56 PM
To: python-list@python.org
Subject: Re: evaluation question

On Sat, Feb 11, 2023 at 08:30:22AM +1100, Chris Angelico wrote:
> On Sat, 11 Feb 2023 at 07:36, Python <python@bladeshadow.org> wrote:
> > You would do this instead:
> >
> > message = f"{username} has the occupation {job}."
> > message_length = len(message)
> > print(message)
> > print(message_length)
> > ...
> >
>
> It's worth noting WHY output functions often return a byte count. It's
> primarily for use with nonblocking I/O, with something like this:
>
> buffer = b".............."
> buffer = buffer[os.write(fd, buffer):]
>
> It's extremely important to be able to do this sort of thing, but not
> with the print function, which has a quite different job.

I would agree with this only partially. Your case applies to os.write(), which is essentially just a wrapper around the write() system call, which has that sort of property... though it applies also to I/O in blocking mode, particularly on network sockets, where the number of bytes you asked to write (or read) may not all have been transferred, necessitating trying in a loop.

However, Python's print() function is more analogous to C's printf(), which returns the number of characters converted for an entirely different reason... It's precisely so that you'll know what the length of the string that was converted is. This is most useful with the
*snprintf() variants where you're actually concerned about overrunning the buffer you've provided for the output string, so you can realloc() the buffer if it was indeed too small, but it is also useful in the context of, say, a routine to format text according to the size of your terminal. In that context it really has nothing to do with blocking I/O or socket behavior.

--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!nyKmKANNzMqWDt2IGH9-Vv63_bioBGOYeokJy5GupmZVZIelplk15rvc_5NNbt6afc9yukh8y5X5mZXDVgr_PhY$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!nyKmKANNzMqWDt2IGH9-Vv63_bioBGOYeokJy5GupmZVZIelplk15rvc_5NNbt6afc9yukh8y5X5mZXDVgr_PhY$>

--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!nyKmKANNzMqWDt2IGH9-Vv63_bioBGOYeokJy5GupmZVZIelplk15rvc_5NNbt6afc9yukh8y5X5mZXDVgr_PhY$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!nyKmKANNzMqWDt2IGH9-Vv63_bioBGOYeokJy5GupmZVZIelplk15rvc_5NNbt6afc9yukh8y5X5mZXDVgr_PhY$>
--
https://mail.python.org/mailman/listinfo/python-list

--
https://mail.python.org/mailman/listinfo/python-list