Re: [Tutor] Python-list thread: int vs. float

2017-02-12 Thread eryk sun
On Sat, Feb 11, 2017 at 8:53 PM, boB Stepp  wrote:
>
> I suspect Eryk had set a normal 's' as an identifier for the character
> code sequence that produces the non-ASCII output, but forgot to show
> us that step.  But I could be mistaken.

Sorry, I forgot to show the assignment of the string "௧꘢୩" to the variable s.

> Today I am working in Windows 7, not Linux Mint.  Of course when I
> attempted to copy and paste the non-ASCII sequence from Gmail into
> cmd.exe I got 3 rectangular boxes on the paste line, indicating
> cmd.exe could not translate those characters.

If you're running python.exe, it either inherits or allocates a
console, which is hosted by an instance of conhost.exe. At most you're
inheriting a console from cmd.exe. That's the extent of its
involvement. Think of conhost.exe as a terminal window, like GNOME
Terminal, etc. cmd.exe and powershell.exe are shells that use standard
I/O, much like Python's REPL -- or like running bash in a Unix
terminal.

The console window can handle characters in the basic multilingual
plane (BMP). Python 3.6 uses the console's wide-character (Unicode)
API, so it should have no problem reading the string "௧꘢୩" if typed or
pasted into the console. For example, if it's assigned to `s`, then
ascii(s) should show the correct \u literals:

>>> ascii(s)
"'\\u0be7\\ua622\\u0b69'"

Unfortunately, for rendering text the Windows console has limited font
support. It requires a strictly monospace font, among other criteria.
It won't switch automatically to other fonts when the current font
doesn't have a glyph for a character. It just displays an empty box
glyph. In Windows 7 a good font choice for the console window is
Consolas. It has pretty good coverage for Western languages, but not
for any of the characters in "௧꘢୩".

If you copy the empty-box glyphs from the console window to the
clipboard, it's actually copying the Unicode characters, which can be
pasted into a window that has better font support, such as notepad. So
in 3.6 this is just a superficial rendering issue that can be
addressed by using programs such as ConEmu that replace the standard
console window (it hides the console and hooks the API to write to its
own window).
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python-list thread: int vs. float

2017-02-11 Thread boB Stepp
On Sat, Feb 11, 2017 at 7:08 PM, Steven D'Aprano  wrote:
> On Sat, Feb 11, 2017 at 02:28:42PM -0600, boB Stepp wrote:
>
>> Back in the main Python list thread, Marko Rauhamaa suggested
>> (https://mail.python.org/pipermail/python-list/2017-February/719322.html):
>>
>> "
>> ...
>> Haven't been following the discussion, but this should be simply:
>>
>>ast.literal_eval("...")
>> ...
>> "
>>
>> This looks like it may do the trick quite concisely:
>
> Nope. Not even close. The problem is that you have to accept ints and
> floats, but reject anything else, and literal_eval does not do that.
>
> py> import ast
> py> ast.literal_eval('[1, {}, None, "s", 2.4j, ()]')
> [1, {}, None, 's', 2.4j, ()]

My intent was to follow up with
type(ast.literal_eval(string_input_from_user)) and if that does not
come out 'int' or 'float', then it can be rejected as invalid input
from the user.  In your example type() would return a list, which
would be invalid input for the OP's case.  Of course this seems like
swatting a gnat with a sledge hammer, but it still seems that the
combination of checking the return of
type(ast.literal_eval(user_input)) does the job since everything that
is not float or int can be rejected as invalid input, and the float
case can get its special error message.

Or am I missing something?

boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python-list thread: int vs. float

2017-02-11 Thread Steven D'Aprano
On Sat, Feb 11, 2017 at 09:10:04AM -0800, Alex Kleider wrote:

> What your 's' represents seems quite different to 'mine.'
> There must be something else going on.
> ???

I think there's an easy explanation for that, which is that eryksun 
probably just created a variable "s" but didn't show the code for that.

Unfortunately copying and pasting Unicode characters from email to the 
Python interpreter may not always work, as that depends on how well at 
least four software components deal with Unicode:

- the email program
- the copy/paste clipboard manager
- the console/terminal
- the Python interpreter

The second last one is particularly problematic under Windows.


When clarity is more important than brevity, the best way to insert 
Unicode characters into a string is to use the '\N{name}' form:

s = '\N{TAMIL DIGIT ONE}\N{VAI DIGIT TWO}\N{ORIYA DIGIT THREE}'

Since that's pure ASCII, you can copy and paste it easily even in the 
most poorly-configured system.


> Also of interest (at least to me) was the 'magic' you demonstrated in 
> the print function parameter list; my efforts to figure it out:
> >>>word = "Hello"
> >>>print((c for c in word))
>  at 0xb71d125c>
> >>>print(*(c for c in word))
> H e l l o
> >>>print(*(c for c in word), sep='')
> Hello

Indeed: the leading * is just the systax for argument unpacking. If you 
have a sequence:

seq = [1, 2, 3, 4]

and unpack it:

print(*seq)

then what the print function sees is:

print(1, 2, 3, 4)


It works with any iterable, not just lists or tuples: also strings, 
generator expressions, and more.



-- 
Steve
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python-list thread: int vs. float

2017-02-11 Thread Steven D'Aprano
On Sat, Feb 11, 2017 at 02:28:42PM -0600, boB Stepp wrote:

> Back in the main Python list thread, Marko Rauhamaa suggested
> (https://mail.python.org/pipermail/python-list/2017-February/719322.html):
> 
> "
> ...
> Haven't been following the discussion, but this should be simply:
> 
>ast.literal_eval("...")
> ...
> "
> 
> This looks like it may do the trick quite concisely:

Nope. Not even close. The problem is that you have to accept ints and 
floats, but reject anything else, and literal_eval does not do that.

py> import ast
py> ast.literal_eval('[1, {}, None, "s", 2.4j, ()]')
[1, {}, None, 's', 2.4j, ()]


literal_eval will parse and evaluate anything that looks like one of:

- int
- float
- string
- bool (True or False)
- None
- complex (e.g. -3.5+4.5j)
- tuple
- list
- dict
- set


so it does *far* more than what the OP requires.

[...]
> That statement about potentially changing with each Python release
> bothers me.  Should I be bothered?

No. In this case, you are parsing a string, and the ast module itself 
parses it to an Abstract Syntax Tree before evaluating literals, so it 
doesn't matter if the AST is different from one version to the next.

You should only care if you generated an AST in (say) Python 3.5, saved 
it in a data file, then read it back in to Python 3.6 and tried to 
evaluate it. That may not succeed.



-- 
Steve
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python-list thread: int vs. float

2017-02-11 Thread boB Stepp
On Sat, Feb 11, 2017 at 2:06 AM, Steven D'Aprano  wrote:
> On Fri, Feb 10, 2017 at 07:59:04PM -0600, boB Stepp wrote:
>
>> He cannot figure out how to reliably tell if the user's input is an
>> integer, float or neither.  So I thought I would come up with my
>> solution, which currently is:
>>
>> py3: def ck_input():
>> ... value_to_ck = input('Enter a number:')
>> ... try:
>> ... value = int(value_to_ck)
>> ... print('You have entered an integer.')
>> ... except ValueError:
>> ... try:
>> ... value = float(value_to_ck)
>> ... print('You have entered a float.')
>> ... except ValueError:
>> ... print('You have failed to enter a numerical value.')
>> ...

> The only not-so-good part of this is that you have mixed user-interface
> and internal calculation. Better:
>
>
> def to_number(string):
> """Convert string to either an int or a float, or raise ValueError."""
> try:
> return int(string)
> except ValueError:
> return float(string)
>
>
> def check_input():
> value_to_ck = input('Enter a number: ')
> try:
> value = to_number(value_to_ck)
> except ValueError:
> print('You have failed to enter a numerical value.')
> return
> if isinstance(value, float):
> print('You have entered a float.')
> else:
> print('You have entered an int.')
>
>
> This gives you nice separation between the function that interacts with
> the user, and the function that does the actual conversion.

Ah!  I am glad I asked the questions.  There is a difference between
intellectually understanding what I should do and reliably
implementing it in my regular coding practice.  This is one such
instance, probably of many unfortunately.  I knew something was
bothering me about this.  I did not like nesting try...except
two-deep.  Now that you have shown the way, I see what was nagging at
me.  Thanks, Steve!

boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python-list thread: int vs. float

2017-02-11 Thread boB Stepp
On Sat, Feb 11, 2017 at 11:10 AM, Alex Kleider  wrote:
> On 2017-02-11 00:36, eryk sun wrote:
>>

>> Note that Python 3 uses the Unicode database to determine the decimal
>> value of characters, if any. It's not limited to the ASCII decimal
>> digits 0-9. For example:
>>
>> >>> s
>> '௧꘢୩'
>> >>> int(s)
>> 123
>> >>> print(*(unicodedata.name(c) for c in s), sep='\n')
>> TAMIL DIGIT ONE
>> VAI DIGIT TWO
>> ORIYA DIGIT THREE
>
>
> ???
> alex@X301n3:~$ python3
> Python 3.4.3 (default, Nov 17 2016, 01:11:57)
> [GCC 4.8.4] on linux
> Type "help", "copyright", "credits" or "license" for more information.

 s
>
> Traceback (most recent call last):
>   File "", line 1, in 
> NameError: name 's' is not defined


> What your 's' represents seems quite different to 'mine.'
> There must be something else going on.

I suspect Eryk had set a normal 's' as an identifier for the character
code sequence that produces the non-ASCII output, but forgot to show
us that step.  But I could be mistaken.

Today I am working in Windows 7, not Linux Mint.  Of course when I
attempted to copy and paste the non-ASCII sequence from Gmail into
cmd.exe I got 3 rectangular boxes on the paste line, indicating
cmd.exe could not translate those characters.  However, if I paste
them into IDLE or gvim, things are translated correctly:

Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900
64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> s
Traceback (most recent call last):
  File "", line 1, in 
s
NameError: name 's' is not defined
>>> '௧꘢୩'
'௧꘢୩'
>>>

I think that this demonstrates that 's' is just an identifier pointing
to the non-ASCII character sequence, but that the actual characters
can be copied and pasted *if* the editor or environment you paste
those characters into is setup to translate those characters.

boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python-list thread: int vs. float

2017-02-11 Thread boB Stepp
On Sat, Feb 11, 2017 at 11:10 AM, Alex Kleider  wrote:

> Also of interest (at least to me) was the 'magic' you demonstrated in the
> print function parameter list; my efforts to figure it out:

Isn't this just argument unpacking?  Thus the necessary "*".

 word = "Hello"
 print((c for c in word))

Need print(*(c...)) to unpack the sequence arguments.

>  at 0xb71d125c>

 print(*(c for c in word))
>
> H e l l o

Spaces because of the default setting for sep argument for print() as
you demonstrate next.

 print(*(c for c in word), sep='')
>
> Hello


-- 
boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python-list thread: int vs. float

2017-02-11 Thread boB Stepp
On Fri, Feb 10, 2017 at 7:59 PM, boB Stepp  wrote:
> I have been following the thread "int vs. float"
> (https://mail.python.org/pipermail/python-list/2017-February/719287.html)
> on the main list.  A search for the OP on the Tutor archive came up
> negative, so I am hoping he is not following Tutor tonight (Or anytime
> prior to the due date for his homework!).  The central part of
> adam14711993's question is:
>
> "What I cannot figure out is how to write it so that if my user input
> is, for example, 1.5, the program will result with: Sorry, you can
> only order whole packages.
>
> "I understand that because I am starting out by assigning my
> number_purchases_str to be an int, when the user enters a float that
> is a conflict and will crash."
>
> He cannot figure out how to reliably tell if the user's input is an
> integer, float or neither.

Back in the main Python list thread, Marko Rauhamaa suggested
(https://mail.python.org/pipermail/python-list/2017-February/719322.html):

"
...
Haven't been following the discussion, but this should be simply:

   ast.literal_eval("...")
...
"

This looks like it may do the trick quite concisely:

py3: import ast
py3: ast.literal_eval('5')
5
py3: ast.literal_eval('5.0')
5.0
py3: type(ast.literal_eval('5'))

py3: type(ast.literal_eval('5.0'))


It appears to reliably parse string input as to whether it is an
integer or float.  However, if the input is a non-numerical string:

py3: ast.literal_eval('a')
Traceback (most recent call last):
  File "", line 1, in 
  File "C:\Program Files\Python35\lib\ast.py", line 84, in literal_eval
return _convert(node_or_string)
  File "C:\Program Files\Python35\lib\ast.py", line 83, in _convert
raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: <_ast.Name object at 0x02C9D860>

But that seems okay, as in the OP's original problem spec, he just
needed a way to determine integer, float or other non-acceptable
input.  This seems to do this quite directly.  I am not familiar with
"abstract syntax trees" (Python has so much very interesting stuff!).
I am concerned about this paragraph at the beginning of the docs on it
(https://docs.python.org/3/library/ast.html?highlight=ast.literal_eval#module-ast):

"The ast module helps Python applications to process trees of the
Python abstract syntax grammar. The abstract syntax itself might
change with each Python release; this module helps to find out
programmatically what the current grammar looks like."

That statement about potentially changing with each Python release
bothers me.  Should I be bothered?  The link to ast.literal_eval():
https://docs.python.org/3/library/ast.html?highlight=ast.literal_eval#ast.literal_eval

What are the gotchas or other negatives from this approach?

boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python-list thread: int vs. float

2017-02-11 Thread Alex Kleider

On 2017-02-11 00:36, eryk sun wrote:
On Sat, Feb 11, 2017 at 8:06 AM, Steven D'Aprano  
wrote:

Valid digits for integers include 0 through 9 in decimal


Note that Python 3 uses the Unicode database to determine the decimal
value of characters, if any. It's not limited to the ASCII decimal
digits 0-9. For example:

>>> s
'௧꘢୩'
>>> int(s)
123
>>> print(*(unicodedata.name(c) for c in s), sep='\n')
TAMIL DIGIT ONE
VAI DIGIT TWO
ORIYA DIGIT THREE


???
alex@X301n3:~$ python3
Python 3.4.3 (default, Nov 17 2016, 01:11:57)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.

s

Traceback (most recent call last):
  File "", line 1, in 
NameError: name 's' is not defined




What your 's' represents seems quite different to 'mine.'
There must be something else going on.
???

Also of interest (at least to me) was the 'magic' you demonstrated in 
the print function parameter list; my efforts to figure it out:

word = "Hello"
print((c for c in word))

 at 0xb71d125c>

print(*(c for c in word))

H e l l o

print(*(c for c in word), sep='')

Hello



___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python-list thread: int vs. float

2017-02-11 Thread eryk sun
On Sat, Feb 11, 2017 at 8:06 AM, Steven D'Aprano  wrote:
> Valid digits for integers include 0 through 9 in decimal

Note that Python 3 uses the Unicode database to determine the decimal
value of characters, if any. It's not limited to the ASCII decimal
digits 0-9. For example:

>>> s
'௧꘢୩'
>>> int(s)
123
>>> print(*(unicodedata.name(c) for c in s), sep='\n')
TAMIL DIGIT ONE
VAI DIGIT TWO
ORIYA DIGIT THREE
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python-list thread: int vs. float

2017-02-11 Thread Steven D'Aprano
On Fri, Feb 10, 2017 at 07:59:04PM -0600, boB Stepp wrote:

> He cannot figure out how to reliably tell if the user's input is an
> integer, float or neither.  So I thought I would come up with my
> solution, which currently is:
> 
> py3: def ck_input():
> ... value_to_ck = input('Enter a number:')
> ... try:
> ... value = int(value_to_ck)
> ... print('You have entered an integer.')
> ... except ValueError:
> ... try:
> ... value = float(value_to_ck)
> ... print('You have entered a float.')
> ... except ValueError:
> ... print('You have failed to enter a numerical value.')
> ...
[...]
> This is all well and good.  I am not trying to elicit an "Atta boy,
> boB!" here. ~(:>)) 

Nevertheless, atta boy boB! 

The only not-so-good part of this is that you have mixed user-interface 
and internal calculation. Better:


def to_number(string):
"""Convert string to either an int or a float, or raise ValueError."""
try:
return int(string)
except ValueError:
return float(string)


def check_input():
value_to_ck = input('Enter a number: ')
try:
value = to_number(value_to_ck)
except ValueError:
print('You have failed to enter a numerical value.')
return
if isinstance(value, float):
print('You have entered a float.')
else:
print('You have entered an int.')


This gives you nice separation between the function that interacts with 
the user, and the function that does the actual conversion.



> Instead, I am wondering if there is something in
> Python's wonderful cornucopia of programming stuff that can simplify
> this type of check.

The most reliable and foolproof way of checking if something is a valid 
int is to ask int to convert it, and see if it fails.

Likewise for floats, where the format is *very* complex. Any of these, 
and many more, should be accepted:

1.2345
+1.2345
-1.2345e0
123.45e+20
123.45E-20
.123
-.123
+.123e-12
123.
inf
+inf
-inf
NaN

Getting all the gory details right of what is and isn't allowed may be 
tricky, but that's okay, because float() already understands how to do 
it for you.


> As you might guess from my earlier post this
> evening, I have been playing around with "type()" and "isinstance()",
> but if I try something like:
> 
> py3: isinstance(int('5.0'))
> Traceback (most recent call last):
>   File "", line 1, in 
> ValueError: invalid literal for int() with base 10: '5.0'

The problem here is that int('5.0') raises an exception because '.' is 
not a valid digit for integers, so it fails before isinstance() gets a 
chance to run.

Valid digits for integers include 0 through 9 in decimal, plus no more 
than one leading + or - sign, and whitespace (space, tabs, newlines) 
before or after the string. If you specify the base, the set of valid 
digits will change, e.g. int(string, 16) will allow 0 through 9 plus A 
through F in lower and upper case.

But whatever base you choose, '.' is not a valid digit.



-- 
Steve
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] Python-list thread: int vs. float

2017-02-10 Thread boB Stepp
I have been following the thread "int vs. float"
(https://mail.python.org/pipermail/python-list/2017-February/719287.html)
on the main list.  A search for the OP on the Tutor archive came up
negative, so I am hoping he is not following Tutor tonight (Or anytime
prior to the due date for his homework!).  The central part of
adam14711993's question is:

"What I cannot figure out is how to write it so that if my user input
is, for example, 1.5, the program will result with: Sorry, you can
only order whole packages.

"I understand that because I am starting out by assigning my
number_purchases_str to be an int, when the user enters a float that
is a conflict and will crash."

He cannot figure out how to reliably tell if the user's input is an
integer, float or neither.  So I thought I would come up with my
solution, which currently is:

py3: def ck_input():
... value_to_ck = input('Enter a number:')
... try:
... value = int(value_to_ck)
... print('You have entered an integer.')
... except ValueError:
... try:
... value = float(value_to_ck)
... print('You have entered a float.')
... except ValueError:
... print('You have failed to enter a numerical value.')
...

(Yes, I know I am not doing anything with the variable, "value", but
if I were to actually implement this in the future, I am sure I would
find a use for it.  So I left it as is for the moment.)

My quick checks are:

py3: ck_input()
Enter a number:5
You have entered an integer.
py3: ck_input()
Enter a number:5.0
You have entered a float.
py3: ck_input()
Enter a number:'5'
You have failed to enter a numerical value.

This is all well and good.  I am not trying to elicit an "Atta boy,
boB!" here. ~(:>)) Instead, I am wondering if there is something in
Python's wonderful cornucopia of programming stuff that can simplify
this type of check.  As you might guess from my earlier post this
evening, I have been playing around with "type()" and "isinstance()",
but if I try something like:

py3: isinstance(int('5.0'))
Traceback (most recent call last):
  File "", line 1, in 
ValueError: invalid literal for int() with base 10: '5.0'

I get the ValueError I make use of in my function above.

So, is there any easier way to do this check?  If not, can my function
be improved to make it a bit less lengthy, but still eminently
readable?

TIA!
-- 
boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor