Hướng dẫn python check if castable to int - kiểm tra python nếu có thể chuyển sang int

Bạn biết đấy, tôi đã tìm thấy (và tôi đã thử nghiệm điều này nhiều lần) mà cố gắng/ngoại trừ không thực hiện tốt tất cả, vì bất kỳ lý do gì. Tôi thường xuyên thử một số cách để làm mọi việc và tôi không nghĩ rằng tôi đã từng tìm thấy một phương pháp sử dụng thử/ngoại trừ để thực hiện tốt nhất trong số những người được thử nghiệm, thực tế có vẻ như đối với tôi, những phương pháp đó thường đến gần với Tệ nhất, nếu không phải là tồi tệ nhất. Không phải trong mọi trường hợp, nhưng trong nhiều trường hợp. Tôi biết rất nhiều người nói đó là cách "Pythonic", nhưng đó là một lĩnh vực mà tôi chia tay với họ. Đối với tôi, nó không rất hiệu quả cũng không rất thanh lịch, vì vậy, tôi có xu hướng chỉ sử dụng nó để bẫy và báo cáo lỗi.

Tôi sẽ nắm bắt được rằng PHP, Perl, Ruby, C, và thậm chí vỏ sò kỳ dị cũng có các chức năng đơn giản để kiểm tra một chuỗi cho số nguyên, nhưng do siêng năng trong việc xác minh các giả định đó đã thúc đẩy tôi! Rõ ràng sự thiếu thốn này là một bệnh tật phổ biến.

Đây là một bản chỉnh sửa nhanh chóng và bẩn thỉu của bài viết của Bruno:

import sys, time, re

g_intRegex = re.compile(r"^([+-]?[1-9]\d*|0)$")

testvals = [
    # integers
    0, 1, -1, 1.0, -1.0,
    '0', '0.','0.0', '1', '-1', '+1', '1.0', '-1.0', '+1.0', '06',
    # non-integers
    'abc 123',
    1.1, -1.1, '1.1', '-1.1', '+1.1',
    '1.1.1', '1.1.0', '1.0.1', '1.0.0',
    '1.0.', '1..0', '1..',
    '0.0.', '0..0', '0..',
    'one', object(), (1,2,3), [1,2,3], {'one':'two'},
    # with spaces
    ' 0 ', ' 0.', ' .0','.01 '
]

def isInt_try(v):
    try:     i = int(v)
    except:  return False
    return True

def isInt_str(v):
    v = str(v).strip()
    return v=='0' or (v if v.find('..') > -1 else v.lstrip('-+').rstrip('0').rstrip('.')).isdigit()

def isInt_re(v):
    import re
    if not hasattr(isInt_re, 'intRegex'):
        isInt_re.intRegex = re.compile(r"^([+-]?[1-9]\d*|0)$")
    return isInt_re.intRegex.match(str(v).strip()) is not None

def isInt_re2(v):
    return g_intRegex.match(str(v).strip()) is not None

def check_int(s):
    s = str(s)
    if s[0] in ('-', '+'):
        return s[1:].isdigit()
    return s.isdigit()    


def timeFunc(func, times):
    t1 = time.time()
    for n in range(times):
        for v in testvals: 
            r = func(v)
    t2 = time.time()
    return t2 - t1

def testFuncs(funcs):
    for func in funcs:
        sys.stdout.write( "\t%s\t|" % func.__name__)
    print()
    for v in testvals:
        if type(v) == type(''):
            sys.stdout.write("'%s'" % v)
        else:
            sys.stdout.write("%s" % str(v))
        for func in funcs:
            sys.stdout.write( "\t\t%s\t|" % func(v))
        sys.stdout.write("\r\n") 

if __name__ == '__main__':
    print()
    print("tests..")
    testFuncs((isInt_try, isInt_str, isInt_re, isInt_re2, check_int))
    print()

    print("timings..")
    print("isInt_try:   %6.4f" % timeFunc(isInt_try, 10000))
    print("isInt_str:   %6.4f" % timeFunc(isInt_str, 10000)) 
    print("isInt_re:    %6.4f" % timeFunc(isInt_re, 10000))
    print("isInt_re2:   %6.4f" % timeFunc(isInt_re2, 10000))
    print("check_int:   %6.4f" % timeFunc(check_int, 10000))

Dưới đây là kết quả so sánh hiệu suất:

timings..
isInt_try:   0.6426
isInt_str:   0.7382
isInt_re:    1.1156
isInt_re2:   0.5344
check_int:   0.3452

Một phương pháp C có thể quét nó một lần qua, và được thực hiện. Một phương pháp C quét chuỗi một lần qua sẽ là điều đúng đắn, tôi nghĩ vậy.

EDIT:

Tôi đã cập nhật mã ở trên để làm việc trong Python 3.5 và để bao gồm chức năng Check_int từ câu trả lời hiện tại được bỏ phiếu nhiều nhất và để sử dụng Regex phổ biến nhất hiện tại mà tôi có thể tìm thấy để kiểm tra số nguyên. Regex này từ chối các chuỗi như 'ABC 123'. Tôi đã thêm 'ABC 123' làm giá trị thử nghiệm.

Tôi rất thú vị khi lưu ý, tại thời điểm này, không có chức năng nào được thử nghiệm, bao gồm phương pháp thử, hàm Check_int phổ biến và Regex phổ biến nhất để kiểm tra số nguyên, trả về các câu trả lời chính xác cho tất cả Giá trị kiểm tra (tốt, tùy thuộc vào những gì bạn nghĩ rằng câu trả lời chính xác là; xem kết quả kiểm tra bên dưới).

Hàm int () tích hợp âm thầm cắt phần phân số của số điểm nổi và trả về phần số nguyên trước số thập phân, trừ khi số điểm nổi được chuyển đổi thành một chuỗi.

Hàm Check_int () trả về sai cho các giá trị như 0,0 và 1.0 (về mặt kỹ thuật là số nguyên) và trả về đúng cho các giá trị như '06'.

Dưới đây là kết quả kiểm tra hiện tại (Python 3.5):

              isInt_try |       isInt_str       |       isInt_re        |       isInt_re2       |   check_int   |
0               True    |               True    |               True    |               True    |       True    |
1               True    |               True    |               True    |               True    |       True    |
-1              True    |               True    |               True    |               True    |       True    |
1.0             True    |               True    |               False   |               False   |       False   |
-1.0            True    |               True    |               False   |               False   |       False   |
'0'             True    |               True    |               True    |               True    |       True    |
'0.'            False   |               True    |               False   |               False   |       False   |
'0.0'           False   |               True    |               False   |               False   |       False   |
'1'             True    |               True    |               True    |               True    |       True    |
'-1'            True    |               True    |               True    |               True    |       True    |
'+1'            True    |               True    |               True    |               True    |       True    |
'1.0'           False   |               True    |               False   |               False   |       False   |
'-1.0'          False   |               True    |               False   |               False   |       False   |
'+1.0'          False   |               True    |               False   |               False   |       False   |
'06'            True    |               True    |               False   |               False   |       True    |
'abc 123'       False   |               False   |               False   |               False   |       False   |
1.1             True    |               False   |               False   |               False   |       False   |
-1.1            True    |               False   |               False   |               False   |       False   |
'1.1'           False   |               False   |               False   |               False   |       False   |
'-1.1'          False   |               False   |               False   |               False   |       False   |
'+1.1'          False   |               False   |               False   |               False   |       False   |
'1.1.1'         False   |               False   |               False   |               False   |       False   |
'1.1.0'         False   |               False   |               False   |               False   |       False   |
'1.0.1'         False   |               False   |               False   |               False   |       False   |
'1.0.0'         False   |               False   |               False   |               False   |       False   |
'1.0.'          False   |               False   |               False   |               False   |       False   |
'1..0'          False   |               False   |               False   |               False   |       False   |
'1..'           False   |               False   |               False   |               False   |       False   |
'0.0.'          False   |               False   |               False   |               False   |       False   |
'0..0'          False   |               False   |               False   |               False   |       False   |
'0..'           False   |               False   |               False   |               False   |       False   |
'one'           False   |               False   |               False   |               False   |       False   |
         False   |               False   |               False   |               False   |       False   |
(1, 2, 3)       False   |               False   |               False   |               False   |       False   |
[1, 2, 3]       False   |               False   |               False   |               False   |       False   |
{'one': 'two'}  False   |               False   |               False   |               False   |       False   |
' 0 '           True    |               True    |               True    |               True    |       False   |
' 0.'           False   |               True    |               False   |               False   |       False   |
' .0'           False   |               False   |               False   |               False   |       False   |
'.01 '          False   |               False   |               False   |               False   |       False   |

Chỉ bây giờ tôi đã thử thêm chức năng này:

def isInt_float(s):
    try:
        return float(str(s)).is_integer()
    except:
        return False

Nó thực hiện gần như cũng như Check_int (0.3486) và nó trả về đúng cho các giá trị như 1.0 và 0.0 và +1.0 và 0. và .0, v.v. Nhưng nó cũng trả về đúng cho '06', vì vậy. Chọn chất độc của bạn, tôi đoán.