Python Forum
Inconsistency in Python programming language?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Inconsistency in Python programming language?
#21
adt Wrote:can it be presumed that at present there is no built in function in python that can return True for a string like "4.5" ?
There is no such function. The easiest way to check if a string represents a float is to call the float() function and catch the potential ValueError.
Reply
#22
Easy enough to write -
def is_it_a_duck(str):
    try :
        foo = float(str)
        return True
    except :
        return False

print(is_it_a_duck("4.5"))
This returns true for things that float. OK it catches all exceptions, not just Value, but it works for the task at hand...
Reply
#23
Microsoft VBA has a Val function with the syntax: Val(string)

It returns the numbers contained in a string as a numeric value of appropriate type. The required string argument is any valid string expression.

The Val function stops reading the string at the first character it can't recognize as part of a number. Blanks, tabs, and linefeed characters get stripped from the argument.

This function can be helpful in extracting numerical data from textual records. Some samples are placed below:

# Caution: Not Python: It Is Microsoft VBA Code:
? Val("45")
 45 
? Val("4.5")
 4.5 
? Val("4.5ABC")
 4.5 
? Val("ABCD")
 0 
? Val("AB45")
 0 
? Val("   2  45  7  ")
 2457
? Val("    2   4   .   5   7   ")
 24.57
Would there be any objection if a similar built-in function were to get incorporated in python too ?
A.D.Tejpal
Reply
#24
adt Wrote:Would there be any objection if a similar built-in function were to get incorporated in python too ?
I don't have an objection but I'm not in charge of the contents of the standard library. Why do you need the function to be built-in? You can very well design a separate library that contains this. Here is an example, I don't say it's the best way to do it, a pure regex implementation may be better.
import ast
import re
from tokenize import generate_tokens, NUMBER
import io

def func(s):
    t = re.sub(r'\s+', '', s)
    f = io.StringIO(t)
    for tok in generate_tokens(f.readline):
        if tok[0] == NUMBER:
            return ast.literal_eval(tok[1])
        return 0
    return 0
        
    
if __name__ == '__main__':
    sample = [
        ("45", 45),
        ("4.5", 4.5),
        ("4.5ABC", 4.5),
        ("ABCD", 0),
        ("AB45", 0),
        ("   2  45  7  ", 2457),
        ("    2   4   .   5   7   ", 24.57),
        ]
    for inp, out in sample:
        assert out == func(inp)
It won't work with complex numbers however. Also it needs to be changed if there is a sign + or - in front of the number. How does the Val function handle a sign?
Reply
#25
(Oct-06-2019, 06:16 AM)Gribouillis Wrote: How does the Val function handle a sign?

Val function handles the signs smoothly, for example:
Val("+4.5") returns 4.5 while Val("-4.5") returns -4.5
A.D.Tejpal
Reply
#26
What about ++++45 or -+54 ? Here is a corrected version
def func(s):
    t = re.sub(r'\s+', '', s)
    f = io.StringIO(t)
    for tok in generate_tokens(f.readline):
        if tok[1] in ('-', '+'):
            continue
        if tok[0] == NUMBER:
            return ast.literal_eval(t[:tok[3][1]])
        return 0
    return 0
Reply
#27
(Oct-06-2019, 06:51 AM)Gribouillis Wrote: What about ++++45 or -+54 ? Here is a corrected version

Glad to inform that your revised function works nicely, giving correct results for all our test strings, even if carrying + sign. However, with negative signed string, it still gives AssertionError.

For "++++45" & " -+54", VBA's Val() function returns 0 in both cases.

It is seen that for pure number strings, even if signed, python's built-in eval() function provides results similar to those by VBA's Val() function. For example:

print(eval("45"))
#>>>45
print(eval("+4.5"))
#>>>4.5
print(eval("-4.5"))
#>>>-4.5
However, for mixed strings like "4.5ABC" or " 2 45 7 ", eval() throws error.
A.D.Tejpal
Reply
#28
@adt, It's better to use ast.literal_eval as it is safer compared to eval
from the docs:
Quote:Safely evaluate an expression node or a string containing a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and None.

This can be used for safely evaluating strings containing Python values from untrusted sources without the need to parse the values oneself. It is not capable of evaluating arbitrarily complex expressions, for example involving operators or indexing.
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#29
Here is a new version. You don't need to import the io module.
def func(s):
    t = re.sub(r'\s+', '', s)
    sign = True
    for tok in generate_tokens(iter([t, '']).__next__):
        if sign and tok[1] in ('-', '+'):
            sign = False
            continue
        if tok[0] == NUMBER:
            return ast.literal_eval(t[:tok[3][1]])
        return 0
    return 0
If there is still an error, please give full bug report!
Reply
#30
(Oct-06-2019, 08:51 AM)buran Wrote: It's better to use ast.literal_eval as it is safer compared to eval

Thanks buran, for your kind suggestion. Noted for future use.

It is seen that ast.literal_eval() too, throws error in case of mixed strings.

(Oct-06-2019, 08:56 AM)Gribouillis Wrote: If there is still an error, please give full bug report!

Test results for the latest version of func() are placed below:

import ast
import re
from tokenize import generate_tokens, NUMBER
#import io

def func(s):
    t = re.sub(r'\s+', '', s)
    sign = True
    for tok in generate_tokens(iter([t, '']).__next__):
        if sign and tok[1] in ('-', '+'):
            sign = False
            continue
        if tok[0] == NUMBER:
            return ast.literal_eval(t[:tok[3][1]])
        return 0
    return 0
     
if __name__ == '__main__':
    sample = [
        ("45", 45),
        ("4.5", 4.5),
        ("4.5ABC", 4.5),
        ("ABCD", 0),
        ("AB45", 0),
        ("   2  45  7  ", 2457),
        ("    2   4   .   5   7   ", 24.57),
        ("+4.5", 4.5),
        ("-4.5", 4.5),   # AssertionError (see Error Box)
        ]
    for inp, out in sample:
        assert out == func(inp)
        print(func(inp))
Output:
45 4.5 4.5 0 0 2457 24.57 4.5
Error For Last String "-4.5"
Error:
Traceback (most recent call last): File "J:\AdtPython-Practice\00-RoughTesting.py", line 92, in <module> assert out == func(inp) AssertionError
A.D.Tejpal
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Programming robots using Python OscarBoots 5 3,460 Oct-31-2021, 09:38 AM
Last Post: Larz60+
  logo language code into python aayushi98 2 67,299 Jan-26-2021, 09:02 PM
Last Post: Serafim
  Programming Difficult math in Python Huntern 6 4,767 Oct-17-2019, 06:32 AM
Last Post: Huntern
  Terms describing Python Programming language leodavinci1990 3 2,732 Aug-12-2019, 02:48 PM
Last Post: leodavinci1990
  Please help a newbie choose which programming language to learn. yeto 2 3,503 Feb-25-2019, 12:56 AM
Last Post: yeto
  Python Programming Projects for Beginners jack_sparrow007 3 3,331 Dec-26-2018, 07:52 PM
Last Post: micseydel
  How to get image from WolframAlpha by using Python language manhnt 1 2,694 Oct-27-2018, 02:07 PM
Last Post: Larz60+
  Programming Python as a MS Windows app? Brian123 8 4,256 Oct-17-2018, 10:26 PM
Last Post: Brian123
  Help with Python programming mediaos 5 3,759 Aug-08-2018, 01:02 PM
Last Post: Larz60+
  How to make the python default language be 3.6 instead of 2.7 sylas 4 6,835 Jul-06-2018, 06:11 AM
Last Post: sylas

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020