文字列がintを表すかどうかを、try / exceptを使用せずに確認するにはどうすればよいですか?


466

かどうかを伝えるためにどのような方法がある文字列が(例えば、整数を表し'3''-17'ではなく、'3.14'または'asfasfas'メカニズム以外のtry /を使用しない)は?

is_int('3.14') = False
is_int('-7')   = True

23
なぜ両方ともこれを「難しい方法」で行おうとしているのですか?try / exceptの何が問題になっていますか?
S.Lott、2009

5
はい、try / exceptの何が問題になっていますか?許可よりも許しを求める方が良いです。
mk12 09/09/14

53
私はなぜこの単純なことがtry / exceptを必要とするのでしょうか?例外システムは複雑な獣ですが、これは単純な問題です。
Aivar 2011

13
@AivarはFUDの拡散を停止します。単一のtry / exceptブロックは「複雑」に近づくことすらありません。
トリプティク

47
ただし、実際にはFUDではありません。1行のライナーを使用する代わりに、効果的に4行のコードを記述し、何かが爆発し、その例外をキャッチしてデフォルトを実行することを期待します。
andersonvom 2013年

回答:


398

try/exceptsをあちこちで使用することに本当にイライラしている場合は、ヘルパー関数を作成してください:

def RepresentsInt(s):
    try: 
        int(s)
        return True
    except ValueError:
        return False

>>> print RepresentsInt("+123")
True
>>> print RepresentsInt("10.0")
False

Pythonが整数と見なすすべての文字列を正確にカバーするために、コードはさらに多くなるでしょう。私はこれについてただpythonicであると言います。


124
複雑なメカニズムで単純な問題を解決するのはpythonicですか?関数「int」内に記述されたintを検出するアルゴリズムがあります-これがブール関数として公開されていない理由はわかりません。
Aivar 2011

79
@Aivar:この5行の関数は複雑なメカニズムではありません。
トリプティク

34
例外:>>> print RepresentsInt(10.0) True >>> print RepresentsInt(10.06) True
Dannid

5
Pythonが文字列をintと見なすと、プログラムもそうなるという意味では、「pythonic」だと思います。Pythonが変更された場合、プログラムも変更され、1行のコードも変更されません。その中にはいくつかの価値があります。状況によっては正しいことかもしれません。
Shavais 2014年

57
なぜこれが受け入れられた答えなのか、または賛成票が多いのかはわかりません。これは、OPが求めているものとは正反対です。
FearlessFuture

755

あなたが使うことができる正の整数で.isdigit

>>> '16'.isdigit()
True

ただし、負の整数では機能しません。次のことを試してみてください:

>>> s = '-17'
>>> s.startswith('-') and s[1:].isdigit()
True

これは、この意味でのキャスト'16.0'と同様の形式では機能しませんint

編集

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

6
これは、追加の特別なケースがないと「+17」を処理しません。
Bryan Oakley

1
両方のケースをテストする必要があります:ラムダs:s.isdigit()または(s.startswith( '-')およびs [1:]。isdigit())
rob

4
@ロベルト:もちろんそうすべきです!そして、あなたはそうすることができると確信しています!
SilentGhost 2009

22
注:u'²'.isdigit()trueですがint(u'²')、ValueError が発生します。u.isdecimal()代わりに使用してください。str.isdigit()ロケールに依存するのPython 2である
JFSは、

4
check_int('')が返される代わりに例外が発生しますFalse
wordbug

97

ご存知のように、何らかの理由でtry / exceptがそれほどうまく機能しないことがわかりました(そしてこれを何度もテストしました)。私は頻繁にいくつかの方法を試しますが、try / exceptを使用してテストされたものの中で最高のパフォーマンスを発揮するメソッドを見つけたことはないと思います。実際、これらのメソッドは通常、最悪の場合、最悪の場合。すべての場合ではなく、多くの場合。多くの人がそれを「Pythonic」のやり方だと言っているのを知っていますが、それは私が彼らと別れる場所の1つです。私には、それは非常に高性能でもエレガントでもないので、エラーのトラップとレポートにのみ使用する傾向があります。

PHP、perl、ruby、C、さらにはおかしなシェルにも整数文字列の文字列をテストするための単純な関数があることを不満に思っていましたが、これらの仮定を検証するためのデューデリジェンスは私をつまずきました!どうやらこの欠如はよくある病気です。

これがブルーノの投稿の素早い汚い編集です。

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))

パフォーマンスの比較結果は次のとおりです。

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

ACメソッドは一度だけスキャンして実行できます。文字列を1回スキャンするCメソッドは、正しいことだと思います。

編集:

上記のコードを更新して、Python 3.5で動作し、現在最も投票されている回答のcheck_int関数を含め、整数フードのテストで見つけることができる現在最も人気のある正規表現を使用します。この正規表現は、「abc 123」のような文字列を拒否します。テスト値として「abc 123」を追加しました。

この時点で、tryメソッド、人気のあるcheck_int関数、および整数フードのテストで最も人気のある正規表現を含め、テストされた関数がどれもないことは、私にとって非常に興味深いことです。テスト値(まあ、正しい答えが何であるかによって異なります。以下のテスト結果を参照してください)。

組み込みのint()関数は、浮動小数点数が最初に文字列に変換されない限り、浮動小数点数の小数部を暗黙的に切り捨て、10進数の前の整数部を返します。

check_int()関数は、0.0や1.0(技術的には整数)などの値に対してfalseを返し、'06 'のような値に対してtrueを返します。

現在の(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   |
    <obj..>         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   |

ちょうど今、私はこの関数を追加してみました:

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

check_int(0.3486)とほぼ同じように機能し、1.0と0.0、+ 1.0と0、.0などの値に対してtrueを返します。しかし、06の場合もtrueを返すので、毒を選んでくださいね。


おそらくそれの一部は、整数自体が少し恣意的であるという事実から来ています。プログラミングシステムは、それが常に10進表記であると想定するという贅沢を利用することはできません。0x4dfは、ある場所では有効な整数であり、0891は他の場所ではありません。これらの種類のチェックでUnicodeが与えられた場合、何が発生する可能性があるのか​​と思うと怖いです。
PlexQ 2012年

3
タイミングの+1。この例外的なビジネス全体が、このような単純な質問に対してはエレガントではないことに同意します。このような一般的な問題には、
組み込みの

9
このスレッドは基本的に休止状態ですが、実行時間を考慮すると+1になります。行の長さは必ずしも根本的な複雑さを示しているわけではありません。確かに、try / exceptはシンプルに見える(そして読みやすい、これも重要です)かもしれません、コストのかかる操作です。私は、設定階層は常に次のようになるはずだと主張します。1.読みやすい明示的なソリューション(SilentGhostのソリューション)。2.読みやすい暗黙の解(Triptych's)。3. 3つはありません。
エリックハンフリー

1
そのような一見重要ではないトピックに関する詳細な調査に感謝します。私は、isInt_str()、pythonicを使用するかどうかを説明します。私を悩ませているのは、v.find( '..')の意味について何も見つけていないことです。それはある種の特別な検索構文ですか、数値文字列のエッジケースですか?
JackLeEmmerdeur 2015

3
はい、少し古いですが、それでも本当に適切で適切な分析です。Python 3.5 tryではより効率的です:isInt_try:0.6552 / isInt_str:0.6396 / isInt_re:1.0296 / isInt_re2:0.5168。
デイブ

40

str.isdigit() トリックを行う必要があります。

例:

str.isdigit("23") ## True
str.isdigit("abc") ## False
str.isdigit("23.4") ## False

編集:@BuzzMoschettiが指摘したように、この方法はマイナス数(たとえば、「-23」)では失敗します。input_numが0未満になる可能性がある場合は、str.isdigit()を適用する前にre.sub(regex_search、regex_replace、contents)を使用してください。例えば:

import re
input_num = "-23"
input_num = re.sub("^-", "", input_num) ## "^" indicates to remove the first "-" only
str.isdigit(input_num) ## True

1
-23はfalseを生成するためです。
バズモシェッティ

1
@BuzzMoschetti正解です。修正する簡単な方法は、str.isdigit()を適用する前にre.replace(regex_search、regex_replace、contents)によってマイナス記号を削除することです
Catbuilts

27

正規表現を使用します。

import re
def RepresentsInt(s):
    return re.match(r"[-+]?\d+$", s) is not None

小数も受け入れる必要がある場合:

def RepresentsInt(s):
    return re.match(r"[-+]?\d+(\.0*)?$", s) is not None

これを頻繁に行う場合にパフォーマンスを向上させるには、を使用して正規表現を1回だけコンパイルしre.compile()ます。


19
+1:これは、try / exceptと比較すると、恐ろしく複雑で高価であることを示しています。
S.Lott、2009

2
これは本質的に、@ SilentGhostが提供する「isnumeric」ソリューションのより遅いカスタムバージョンだと思います。
グレッグ

@Greg:@SilentGhostは標識を正しくカバーしないため、このバージョンは実際に機能します。
S.Lott、2009

1
@ S.Lott:確かに、SOに投稿できる人なら誰でも私の例を拡張して標識をカバーすることができます。
SilentGhost 2009

2
正規表現は、存在する中で最も複雑であいまいなものに関するものです。上記の簡単なチェックのほうがはるかに明確であることがわかります。
PlexQ 2012年

18

適切なRegExソリューションは、Greg HewgillとNowellのアイデアを組み合わせますが、グローバル変数を使用しません。これを行うには、メソッドに属性を付加します。また、メソッドにインポートを配置することは不快であることを知っていますが、私がしようとしているのは、http://peak.telecommunity.com/DevCenter/Importing#lazy-importsのような「遅延モジュール」効果です。

編集:これまでのところ私のお気に入りのテクニックは、Stringオブジェクトのメソッドのみを使用することです。

#!/usr/bin/env python

# Uses exclusively methods of the String object
def isInteger(i):
    i = str(i)
    return i=='0' or (i if i.find('..') > -1 else i.lstrip('-+').rstrip('0').rstrip('.')).isdigit()

# Uses re module for regex
def isIntegre(i):
    import re
    if not hasattr(isIntegre, '_re'):
        print("I compile only once. Remove this line when you are confident in that.")
        isIntegre._re = re.compile(r"[-+]?\d+(\.0*)?$")
    return isIntegre._re.match(str(i)) is not None

# When executed directly run Unit Tests
if __name__ == '__main__':
    for obj in [
                # integers
                0, 1, -1, 1.0, -1.0,
                '0', '0.','0.0', '1', '-1', '+1', '1.0', '-1.0', '+1.0',
                # non-integers
                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'}
            ]:
        # Notice the integre uses 're' (intended to be humorous)
        integer = ('an integer' if isInteger(obj) else 'NOT an integer')
        integre = ('an integre' if isIntegre(obj) else 'NOT an integre')
        # Make strings look like strings in the output
        if isinstance(obj, str):
            obj = ("'%s'" % (obj,))
        print("%30s is %14s is %14s" % (obj, integer, integre))

そして、クラスの冒険好きではないメンバーのために、ここに出力があります:

I compile only once. Remove this line when you are confident in that.
                             0 is     an integer is     an integre
                             1 is     an integer is     an integre
                            -1 is     an integer is     an integre
                           1.0 is     an integer is     an integre
                          -1.0 is     an integer is     an integre
                           '0' is     an integer is     an integre
                          '0.' is     an integer is     an integre
                         '0.0' is     an integer is     an integre
                           '1' is     an integer is     an integre
                          '-1' is     an integer is     an integre
                          '+1' is     an integer is     an integre
                         '1.0' is     an integer is     an integre
                        '-1.0' is     an integer is     an integre
                        '+1.0' is     an integer is     an integre
                           1.1 is NOT an integer is NOT an integre
                          -1.1 is NOT an integer is NOT an integre
                         '1.1' is NOT an integer is NOT an integre
                        '-1.1' is NOT an integer is NOT an integre
                        '+1.1' is NOT an integer is NOT an integre
                       '1.1.1' is NOT an integer is NOT an integre
                       '1.1.0' is NOT an integer is NOT an integre
                       '1.0.1' is NOT an integer is NOT an integre
                       '1.0.0' is NOT an integer is NOT an integre
                        '1.0.' is NOT an integer is NOT an integre
                        '1..0' is NOT an integer is NOT an integre
                         '1..' is NOT an integer is NOT an integre
                        '0.0.' is NOT an integer is NOT an integre
                        '0..0' is NOT an integer is NOT an integre
                         '0..' is NOT an integer is NOT an integre
                         'one' is NOT an integer is NOT an integre
<object object at 0x103b7d0a0> is NOT an integer is NOT an integre
                     (1, 2, 3) is NOT an integer is NOT an integre
                     [1, 2, 3] is NOT an integer is NOT an integre
                {'one': 'two'} is NOT an integer is NOT an integre

4
私のテストスイートはやり過ぎだということに同意します。私はそれを書いたときに私のコードが機能することを証明したいです。しかし、私のisInteger関数はやり過ぎだと思いますか?確かに違います。
Bruno Bronosky、2011

1
コメントなしで反対票を獲得しました。人とは何ですか?ミレニアル世代が「いいね」を「開封確認」として使用していることを理解しています。しかし、彼らは現在、「私が選択した方法ではない」マーカーとして反対票を使用していますか?多分彼らはそれがあなた自身の評判から2ポイントを差し引いて回答を反対票投票することに気付かないでしょう。SO / SEは、誤った情報によってのみ投票を拒否することを奨励するためにそれを行います。その場合は、コメントを残していただければ幸いです。
ブルーノブロノスキー

5
>>> "+7".lstrip("-+").isdigit()
True
>>> "-7".lstrip("-+").isdigit()
True
>>> "7".lstrip("-+").isdigit()
True
>>> "13.4".lstrip("-+").isdigit()
False

したがって、関数は次のようになります。

def is_int(val):
   return val[1].isdigit() and val.lstrip("-+").isdigit()

1
is_int( "2")はIndexErrorを発生させます。
anttikoo 2013

4

Greg Hewgillのアプローチにはいくつかのコンポーネントがありませんでした。文字列の先頭のみに一致する先頭の "^"と、事前にreをコンパイルしています。ただし、このアプローチでは、次のような試みを回避できます。

import re
INT_RE = re.compile(r"^[-]?\d+$")
def RepresentsInt(s):
    return INT_RE.match(str(s)) is not None

なぜあなたがトライを避けようとしているのか興味があります。


1
スタイルの問題。"try / except"は、通常のプログラムフローではなく、実際のエラーでのみ使用する必要があると思います。
Adam Matan

2
@Udi Pasmon:Pythonは、「通常の」プログラムフローを除いて、try / exceptをかなり頻繁に使用します。たとえば、すべてのイテレータは発生した例外で停止します。
S.Lott、2009

3
-1:正規表現をコンパイルするヒントは正しいですが、他の点ではGregを批評するのは間違っています。re.match は文字列の先頭と一致するため、パターン内の^は実際には冗長です。(これは、re.searchを使用する場合とは異なります)。
ThomasH 2009

S.Lott-これはPythonで妥当なフローと見なされますか?これは他の言語とどう違うのですか?おそらく、別の質問に値するでしょう。
Adam Matan

1
Pythonでのtry / exceptの多用については、SOで説明しています。「[python] except」を検索してみてください
S.Lott

4

私はいつもこれをしなければならず、try / exceptパターンを使用するのは穏やかですが明らかに非合理的な嫌悪があります。私はこれを使います:

all([xi in '1234567890' for xi in x])

負の数は受け入れられないため、マイナス記号(ある場合)を1つ取り除き、結果が0〜9の数字で構成されているかどうかを確認できます。

all([xi in '1234567890' for xi in x.replace('-', '', 1)])

入力が文字列かどうかわからない場合は、xをstr()に渡すこともできます。

all([xi in '1234567890' for xi in str(x).replace('-', '', 1)])

これがバラバラになる少なくとも2つの(エッジ?)ケースがあります。

  1. さまざまな科学表記や指数表記(1.2E3、10 ^ 3など)では機能しません-どちらもFalseを返します。私は他の回答はどちらか、これを収容するとは思わない、とさえ以来のPython 3.8は、矛盾した意見を持ってtype(1E2)います<class 'float'>のに対しtype(10^2)提供します<class 'int'>
  2. 空の文字列を入力するとTrueになります。

したがって、すべての入力に対して機能するわけではありませんが、科学表記法、指数表記法、および空の文字列を除外できるFalse場合、xが整数ではなく、xが整数であるTrue場合に返されるOK 1行チェックです。

それがpythonicかどうかはわかりませんが、1行で、コードの動作は比較的明確です。


try / exceptは誰かの芝生の上を歩く(試してみる)ようで、その後気づいたときに怒る(例外)場合は謝罪(例外を処理)しますが、私のall(xi in '1234567890' for xi in x])パターンは芝生の上を歩く許可を求めるようなものです。私は許可を求める人であることに興奮していませんが、ここにいます。
mRotten

3

おもう

s.startswith('-') and s[1:].isdigit()

次のように書き換えた方がよいでしょう:

s.replace('-', '').isdigit()

s [1:]も新しい文字列を作成するため

しかし、はるかに良い解決策は

s.lstrip('+-').isdigit()

3
何を推測replaceしますか?また、これは5-2、たとえばを誤って受け入れます。
Ry-

次の場合にIndexErrorをスローしますs='-'
Anti Earth

s = '-'; s.replace( '-'、 '').isdigit()-> False
Savchenko

2

Shavaisの投稿は本当に気に入りましたが、テストケースをもう1つ追加しました(組み込みのisdigit()関数)。

def isInt_loop(v):
    v = str(v).strip()
    # swapping '0123456789' for '9876543210' makes nominal difference (might have because '1' is toward the beginning of the string)
    numbers = '0123456789'
    for i in v:
        if i not in numbers:
            return False
    return True

def isInt_Digit(v):
    v = str(v).strip()
    return v.isdigit()

そして、それは残りの時代を著しく一貫して打ち負かしています:

timings..
isInt_try:   0.4628
isInt_str:   0.3556
isInt_re:    0.4889
isInt_re2:   0.2726
isInt_loop:   0.1842
isInt_Digit:   0.1577

通常の2.7 Pythonを使用:

$ python --version
Python 2.7.10

私が追加した2つのテストケース(isInt_loopとisInt_digit)はまったく同じテストケースに合格します(どちらも符号なし整数のみを受け入れます)が、組み込みのisdigitとは対照的に、文字列の実装(isInt_loop)を変更する方が賢いと考えました()関数なので、実行時間にわずかな違いはありますが、含めました。(そしてどちらの方法も他のすべてのものを大幅に上回っていますが、余分なものは処理しません: "./+/-")

また、2012年(現在は2018年)にShavaisが実行したのと同じテストで、正規表現(isInt_re2メソッド)が文字列比較を上回ったことに注目するのは興味深いことでした。正規表現ライブラリが改善されたのでしょうか?


1

これはおそらく、私の意見では、これにアプローチするための最も簡単でPython的な方法です。私はこの解決策を見ませんでした、そしてそれは基本的に正規表現のものと同じですが、正規表現なしです。

def is_int(test):
    import string
    return not (set(test) - set(string.digits))

set(input_string) == set(string.digits)我々はスキップ場合は'-+ '初めに及び.0E-1最後に。
jfs 2014年

1

エラーを発生させずに解析する関数を次に示します。None失敗した場合に返される明らかなケースを処理します(CPythonではデフォルトで最大2000の「-/ +」記号を処理します!):

#!/usr/bin/env python

def get_int(number):
    splits = number.split('.')
    if len(splits) > 2:
        # too many splits
        return None
    if len(splits) == 2 and splits[1]:
        # handle decimal part recursively :-)
        if get_int(splits[1]) != 0:
            return None

    int_part = splits[0].lstrip("+")
    if int_part.startswith('-'):
        # handle minus sign recursively :-)
        return get_int(int_part[1:]) * -1
    # successful 'and' returns last truth-y value (cast is always valid)
    return int_part.isdigit() and int(int_part)

いくつかのテスト:

tests = ["0", "0.0", "0.1", "1", "1.1", "1.0", "-1", "-1.1", "-1.0", "-0", "--0", "---3", '.3', '--3.', "+13", "+-1.00", "--+123", "-0.000"]

for t in tests:
    print "get_int(%s) = %s" % (t, get_int(str(t)))

結果:

get_int(0) = 0
get_int(0.0) = 0
get_int(0.1) = None
get_int(1) = 1
get_int(1.1) = None
get_int(1.0) = 1
get_int(-1) = -1
get_int(-1.1) = None
get_int(-1.0) = -1
get_int(-0) = 0
get_int(--0) = 0
get_int(---3) = -3
get_int(.3) = None
get_int(--3.) = 3
get_int(+13) = 13
get_int(+-1.00) = -1
get_int(--+123) = 123
get_int(-0.000) = 0

あなたのニーズのためにあなたは使うことができます:

def int_predicate(number):
     return get_int(number) is not None

1

私は以下を提案します:

import ast

def is_int(s):
    return isinstance(ast.literal_eval(s), int)

ドキュメントから:

式ノードまたはPythonリテラルまたはコンテナー表示を含む文字列を安全に評価します。提供される文字列またはノードは、文字列、バイト、数値、タプル、リスト、辞書、セット、ブール値、およびNoneのPythonリテラル構造のみで構成されます。

ValueErrorPythonリテラルを構成しないものに対して呼び出されると、例外が発生することに注意してください。質問はtry / exceptなしの解決策を求めていたので、私はそのための小林丸タイプの解決策を持っています:

from ast import literal_eval
from contextlib import suppress

def is_int(s):
    with suppress(ValueError):
        return isinstance(literal_eval(s), int)
    return False

¯\ _(ツ)_ /¯


0

intをまったく使用しない可能性が1つあります。文字列が数値を表していない場合を除き、例外を発生させないでください。

float(number)==float(number)//1

それは、浮動小数点が受け入れる任意の種類の文字列、正、負、エンジニアリング表記で機能するはずです...


0

try / exceptには時間のペナルティがあるため、質問は速度に関連していると思います。

 テストデータ

まず、200個の文字列、100個の失敗した文字列、100個の数値文字列のリストを作成しました。

from random import shuffle
numbers = [u'+1'] * 100
nonumbers = [u'1abc'] * 100
testlist = numbers + nonumbers
shuffle(testlist)
testlist = np.array(testlist)

 numpyソリューション(配列とUnicodeでのみ機能します)

np.core.defchararray.isnumericは、Unicode文字列でも機能しますnp.core.defchararray.isnumeric(u'+12')が、配列を返します。したがって、何千もの変換を行う必要があり、データが欠落している、または数値以外のデータがある場合は、これが優れたソリューションです。

import numpy as np
%timeit np.core.defchararray.isnumeric(testlist)
10000 loops, best of 3: 27.9 µs per loop # 200 numbers per loop

試す/除く

def check_num(s):
  try:
    int(s)
    return True
  except:
    return False

def check_list(l):
  return [check_num(e) for e in l]

%timeit check_list(testlist)
1000 loops, best of 3: 217 µs per loop # 200 numbers per loop

numpyソリューションははるかに速いようです。


0

小文字のASCII数字のみを受け入れる場合は、次のテストを行ってください。

Python 3.7以降: (u.isdecimal() and u.isascii())

Python <= 3.6: (u.isdecimal() and u == str(int(u)))

他の回答では、.isdigit()またはを使用することをお勧めします.isdecimal()が、どちらにも'٢'u'\u0662')などの上位ユニコード文字が含まれています。

u = u'\u0662'     # '٢'
u.isdigit()       # True
u.isdecimal()     # True
u.isascii()       # False (Python 3.7+ only)
u == str(int(u))  # False

これは負の値や空白で埋められた値を処理しませんint()。これらはどちらもによって適切に処理されます。
ShadowRanger

-6

ええと。これを試してください:

def int_check(a):
    if int(a) == a:
        return True
    else:
        return False

これは、数値ではない文字列を入力しない場合に機能します。

また、(数字のチェック部分を置くのを忘れていました。)文字列が数字かどうかをチェックする関数があります。str.isdigit()です。次に例を示します。

a = 2
a.isdigit()

a.isdigit()を呼び出すと、Trueが返されます。


2割り当てられた値を引用符で囲む必要があると思いますa
ルークウッドワード

1
なぜこのトップアンサーではないのですか?それは質問に正確に答えます。
バッタ

6
-1質問:「Try / Exceptを使用せずに、文字列がintを表すかどうかを確認しますか?」@Caroline Alexiou
jfs 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.