كيف يمكنني معرفة ما اذا كانت السلسلة عبارة عن عدد (تعويم)?
-
20-08-2019 - |
سؤال
ما هي أفضل طريقة لمعرفة ما إذا كانت سلسلة يمكن أن تكون ممثلة في الثعبان ؟
وظيفة لدي حاليا الآن هو:
def is_number(s):
try:
float(s)
return True
except ValueError:
return False
والتي ليس فقط هو قبيح و بطيئة ، يبدو عالي الكعب.ومع ذلك لم أجد طريقة أفضل لأن الدعوة float
في دالة الرئيسي هو أسوأ من ذلك.
المحلول
والتي ليس فقط هو قبيح و بطيئة
كنت النزاع على حد سواء.
باستخدام التعابير المنطقية أو غيرها من سلسلة تحليل الأسلوب سيكون أقبح و أبطأ.
أنا لست متأكدا من أن ذلك يمكن أن يكون أسرع مما سبق.ويدعو وظيفة والعوائد.حاول/Catch لا يعرض الكثير من النفقات العامة لأن الاستثناء الأكثر شيوعا هو القبض بدون عملية بحث واسعة النطاق من إطارات المكدس.
القضية هي أن أي الرقمية تحويل وظيفة لديها نوعين من النتائج
- عدد ، إذا كان عدد صالحة
- رمز الحالة (على سبيل المثال ، عن طريق errno) أو استثناء لإظهار أنه لا يوجد رقم صحيح يمكن أن يكون تحليل.
ج (كمثال) الخارقة حول هذه عدد من الطرق.بيثون يضع بوضوح و صراحة.
أعتقد أن الكود الخاص بك للقيام بذلك هو الكمال.
نصائح أخرى
في حال كنت تبحث عن تحليل الإيجابي (غير موقعة) الأعداد الصحيحة بدلا من العوامات ، يمكنك استخدام isdigit()
وظيفة سلسلة الكائنات.
>>> a = "03523"
>>> a.isdigit()
True
>>> b = "963spam"
>>> b.isdigit()
False
سلسلة الطرق - isdigit()
: Python2, Python3
هناك أيضا شيء على سلاسل Unicode التي أنا لم تكن مألوفة جدا مع Unicode - هو عشري/عشري
TL;DR أفضل حل هو s.replace('.','',1).isdigit()
فعلت بعض المعايير مقارنة مناهج مختلفة
def is_number_tryexcept(s):
""" Returns True is string is a number. """
try:
float(s)
return True
except ValueError:
return False
import re
def is_number_regex(s):
""" Returns True is string is a number. """
if re.match("^\d+?\.\d+?$", s) is None:
return s.isdigit()
return True
def is_number_repl_isdigit(s):
""" Returns True is string is a number. """
return s.replace('.','',1).isdigit()
إذا كانت السلسلة غير عدد ، باستثناء كتلة بطيئة جدا.ولكن الأهم من ذلك أن نحاول-ما عدا الأسلوب هو النهج الوحيد الذي يعالج العلمية الرموز بشكل صحيح.
funcs = [
is_number_tryexcept,
is_number_regex,
is_number_repl_isdigit
]
a_float = '.1234'
print('Float notation ".1234" is not supported by:')
for f in funcs:
if not f(a_float):
print('\t -', f.__name__)
تطفو التدوين ".1234" غير معتمد من قبل:
- is_number_regex
scientific1 = '1.000000e+50'
scientific2 = '1e50'
print('Scientific notation "1.000000e+50" is not supported by:')
for f in funcs:
if not f(scientific1):
print('\t -', f.__name__)
print('Scientific notation "1e50" is not supported by:')
for f in funcs:
if not f(scientific2):
print('\t -', f.__name__)
العلمي "1.000000 e+50" غير معتمد من قبل:
- is_number_regex
- is_number_repl_isdigit
العلمي "1e50" غير معتمد من قبل:
- is_number_regex
- is_number_repl_isdigit
تحرير:إن نتائج المؤشر
import timeit
test_cases = ['1.12345', '1.12.345', 'abc12345', '12345']
times_n = {f.__name__:[] for f in funcs}
for t in test_cases:
for f in funcs:
f = f.__name__
times_n[f].append(min(timeit.Timer('%s(t)' %f,
'from __main__ import %s, t' %f)
.repeat(repeat=3, number=1000000)))
حيث تم اختبار الوظائف التالية
from re import match as re_match
from re import compile as re_compile
def is_number_tryexcept(s):
""" Returns True is string is a number. """
try:
float(s)
return True
except ValueError:
return False
def is_number_regex(s):
""" Returns True is string is a number. """
if re_match("^\d+?\.\d+?$", s) is None:
return s.isdigit()
return True
comp = re_compile("^\d+?\.\d+?$")
def compiled_regex(s):
""" Returns True is string is a number. """
if comp.match(s) is None:
return s.isdigit()
return True
def is_number_repl_isdigit(s):
""" Returns True is string is a number. """
return s.replace('.','',1).isdigit()
وهناك استثناء واحد التي قد تريد أن تأخذ بعين الاعتبار ما يلي: سلسلة 'نان'
إذا كنت تريد is_number للعودة كاذبة عن "نان" هذا الرمز لن يعمل كما بيثون تحولها إلى تمثيلها من الرقم الذي ليس عدد (نقاش حول قضايا الهوية):
>>> float('NaN')
nan
وعلى خلاف ذلك، وأود أن الواقع أشكركم على قطعة من التعليمات البرمجية أنا الآن استخدام على نطاق واسع. :)
وG.
وماذا عن هذا:
'3.14'.replace('.','',1).isdigit()
والذي سيعود صحيح فقط إذا كان هناك واحد أو لا ''. في سلسلة من الأرقام.
'3.14.5'.replace('.','',1).isdigit()
وسيعود كاذبة
وتحرير: فقط رأيت تعليق آخر ...
إضافة .replace(badstuff,'',maxnum_badstuff)
لحالات أخرى يمكن القيام به. إذا كنت تمر الملح والتوابل لا التعسفية (المرجع: XKCD # 974 ) هذا سوف تفعل ما يرام: P
وتحديث بعد ألفي أشار خارج لا تحتاج إلى التحقق من وجود تعويم بشكل منفصل كما مقابض المعقدة على حد سواء:
def is_number(s):
try:
complex(s) # for int, long, float and complex
except ValueError:
return False
return True
وقال سابقا: هل بعض الحالات النادرة قد تحتاج أيضا إلى التحقق من وجود الأعداد المركبة (مثل 1 + 2I)، والتي لا يمكن أن يمثله تعويم:
def is_number(s):
try:
float(s) # for int, long and float
except ValueError:
try:
complex(s) # for complex
except ValueError:
return False
return True
ما هو قبيح وبطيئة فحسب، يبدو عالي الكعب.
اقتباس فقرة>وقد يستغرق بعض التعود، ولكن هذه هي الطريقة pythonic للقيام بذلك. وكما سبق أن ذكرنا، والبدائل أسوأ. ولكن هناك ميزة واحدة أخرى للقيام بهذه الأمور بهذه الطريقة: تعدد الأشكال
والفكرة المركزية وراء الكتابة بطة هي أن "إذا كان يمشي ويتحدث وكأنه بطة، ثم انها بطة". ماذا لو قررت أنك تحتاج إلى فئة فرعية سلسلة بحيث يمكنك تغيير كيفية تحديد إذا كان هناك شيء يمكن تحويلها إلى تعويم؟ أو ما إذا كنت ترغب في اختبار بعض كائن آخر تماما؟ يمكنك أن تفعل هذه الأشياء دون الحاجة إلى تغيير رمز أعلاه.
لغات أخرى حل هذه المشاكل باستخدام الواجهات. أنا انقاذ تحليل الحل الذي هو أفضل لموضوع آخر. نقطة، على الرغم من أن الثعبان هو بالتأكيد على الجانب بطة الكتابة من المعادلة، وربما كنت ذاهب الى ان تعتاد على بناء جملة مثل هذا إذا كنت تخطط للقيام الكثير البرمجة في بايثون (ولكن هذا لا يعني عليك أن ترغب في ذلك بطبيعة الحال).
وشيء آخر قد ترغب في أن تأخذ في الاعتبار: بيثون سريع جدا في رمي واصطياد الاستثناءات مقارنة مع الكثير من لغات أخرى (30X أسرع من صافي على سبيل المثال). هيك، واللغة نفسها حتى يلقي استثناءات على التواصل غير استثنائية، وشروط البرنامج العادي (في كل مرة كنت تستخدم لحلقة). وهكذا، وأود أن لا تقلق كثيرا بشأن جوانب أداء هذا الرمز حتى لاحظت وجود مشكلة كبيرة.
لint
استخدام هذا:
>>> "1221323".isdigit()
True
ولكن لfloat
نحن بحاجة الى بعض الحيل ؛-). كل عدد تعويم ديه نقطة واحدة ...
>>> "12.34".isdigit()
False
>>> "12.34".replace('.','',1).isdigit()
True
>>> "12.3.4".replace('.','',1).isdigit()
False
وأيضا للأرقام السالبة فقط إضافة lstrip()
:
>>> '-12'.lstrip('-')
'12'
ونحن الآن الحصول على وسيلة عالمية:
>>> '-12.34'.lstrip('-').replace('.','',1).isdigit()
True
>>> '.-234'.lstrip('-').replace('.','',1).isdigit()
False
مجرد تقليد C#
في C# هناك نوعان من الوظائف المختلفة التي تتعامل مع تحليل القيم العددية:
- تطفو.تحليل()
- تطفو.TryParse()
تطفو.تحليل():
def parse(string):
try:
return float(string)
except Exception:
throw TypeError
ملاحظة:إذا كنت أتساءل لماذا أنا غيرت استثناء إلى TypeError, هنا الوثائق.
تطفو.try_parse():
def try_parse(string, fail=None):
try:
return float(string)
except Exception:
return fail;
ملاحظة:كنت لا ترغب في العودة منطقية 'False' لأن هذا لا يزال نوع القيمة.ليس هناك ما هو أفضل لأنه يدل على الفشل.بالطبع, إذا كنت تريد شيئا مختلفا يمكنك تغيير تفشل المعلمة إلى ما تريد.
تمديد تطفو لتشمل 'تحليل()' و 'try_parse()' سوف تحتاج إلى monkeypatch على 'تعويم' الطبقة لإضافة هذه الأساليب.
إذا كنت تريد الاحترام موجود مسبقا وظائف الرمز يجب أن يكون شيئا مثل:
def monkey_patch():
if(!hasattr(float, 'parse')):
float.parse = parse
if(!hasattr(float, 'try_parse')):
float.try_parse = try_parse
وي:أنا شخصيا أفضل أن أسميها القرد اللكم لأنه يشعر وكأنه أنا إساءة استخدام اللغة عندما أفعل هذا ولكن YMMV.
الاستخدام:
float.parse('giggity') // throws TypeException
float.parse('54.3') // returns the scalar value 54.3
float.tryParse('twank') // returns None
float.tryParse('32.2') // returns the scalar value 32.2
و حكيم عظيم Pythonas قال الرسولي Sharpisus, "يمكنك أن تفعل أي شيء يمكنني القيام به على نحو أفضل ؛ أستطيع أن أفعل أي شيء أفضل مما كنت."
سلاسل من غير أرقام ، try: except:
هو في الواقع أبطأ من التعبيرات العادية.سلاسل من أرقام صالح, regex أبطأ.لذا الطريقة المناسبة يعتمد على المدخلات الخاصة بك.
إذا وجدت أن كنت في الأداء ربط ، يمكنك استخدام طرف ثالث جديدة تسمى وحدة fastnumbers التي توفر وظيفة تسمى isfloat.الكشف الكامل ، أنا صاحب البلاغ.وأدرجت النتائج في المواعيد أدناه.
from __future__ import print_function
import timeit
prep_base = '''\
x = 'invalid'
y = '5402'
z = '4.754e3'
'''
prep_try_method = '''\
def is_number_try(val):
try:
float(val)
return True
except ValueError:
return False
'''
prep_re_method = '''\
import re
float_match = re.compile(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$').match
def is_number_re(val):
return bool(float_match(val))
'''
fn_method = '''\
from fastnumbers import isfloat
'''
print('Try with non-number strings', timeit.timeit('is_number_try(x)',
prep_base + prep_try_method), 'seconds')
print('Try with integer strings', timeit.timeit('is_number_try(y)',
prep_base + prep_try_method), 'seconds')
print('Try with float strings', timeit.timeit('is_number_try(z)',
prep_base + prep_try_method), 'seconds')
print()
print('Regex with non-number strings', timeit.timeit('is_number_re(x)',
prep_base + prep_re_method), 'seconds')
print('Regex with integer strings', timeit.timeit('is_number_re(y)',
prep_base + prep_re_method), 'seconds')
print('Regex with float strings', timeit.timeit('is_number_re(z)',
prep_base + prep_re_method), 'seconds')
print()
print('fastnumbers with non-number strings', timeit.timeit('isfloat(x)',
prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with integer strings', timeit.timeit('isfloat(y)',
prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with float strings', timeit.timeit('isfloat(z)',
prep_base + 'from fastnumbers import isfloat'), 'seconds')
print()
Try with non-number strings 2.39108395576 seconds
Try with integer strings 0.375686168671 seconds
Try with float strings 0.369210958481 seconds
Regex with non-number strings 0.748660802841 seconds
Regex with integer strings 1.02021503448 seconds
Regex with float strings 1.08564686775 seconds
fastnumbers with non-number strings 0.174362897873 seconds
fastnumbers with integer strings 0.179651021957 seconds
fastnumbers with float strings 0.20222902298 seconds
كما ترون
try: except:
كان سريع المدخلات الرقمية ولكن بطيئة جدا على إدخال غير صالح- regex فعالة جدا عند الإدخال غير صالح
fastnumbers
يفوز في كل الحالات
وأعرف أن هذا هو القديم خاصة ولكن أود أن أضيف إجابة أعتقد تغطي المعلومات الناقصة من أعلى صوت الإجابة التي يمكن أن تكون ذات قيمة للغاية لأي الذين يجدون هذا:
لكل من الطرق التالية ربطها مع العد إذا كنت بحاجة إلى أي مدخلات ليكون مقبولا. (على افتراض اننا نستخدم تعريفات الصوتية من الأعداد الصحيحة بدلا من 0-255، الخ.)
وx.isdigit()
يعمل بشكل جيد لفحص إذا كان x هو عدد صحيح.
وx.replace('-','').isdigit()
يعمل بشكل جيد لفحص إذا كان x سلبي (راجع - في المركز الأول).
وx.replace('.','').isdigit()
يعمل بشكل جيد لفحص إذا كان x عشري.
وx.replace(':','').isdigit()
يعمل بشكل جيد لفحص إذا كان x هو النسبة.
وx.replace('/','',1).isdigit()
يعمل بشكل جيد لفحص إذا كان x هو جزء بسيط.
والصب لتعويم واصطياد ValueError ربما هو أسرع وسيلة، منذ تعويم () يقصد خصيصا لذلك. وأي شيء آخر يتطلب سلسلة تحليل (التعابير المنطقية، الخ) من المرجح أن تكون أبطأ يرجع ذلك إلى حقيقة أنها ليست ضبطها لهذه العملية. بلدي $ 0.02.
ويمكنك استخدام سلاسل Unicode، لديهم طريقة لفعل ما تريد:
>>> s = u"345"
>>> s.isnumeric()
True
وأو:
>>> s = "345"
>>> u = unicode(s)
>>> u.isnumeric()
True
هذا الجواب يوفر دليل خطوة بخطوة وجود وظيفة مع الأمثلة تجد السلسلة:
- عدد صحيح موجب
- الإيجابية/السلبية - صحيح/تعويم
- كيفية تجاهل "نان" (وليس عدد) سلاسل حين التحقق من الرقم ؟
تحقق إذا سلسلة إيجابية صحيح
يمكنك استخدام str.isdigit()
للتحقق من ما إذا كان إعطاء السلسلة إيجابية عدد صحيح.
نتائج العينات:
# For digit
>>> '1'.isdigit()
True
>>> '1'.isalpha()
False
تحقق سلسلة إيجابية/سلبية - صحيح/تعويم
str.isdigit()
يعود False
إذا كانت السلسلة هو السلبية عدد أو عدد عشري في عدد.على سبيل المثال:
# returns `False` for float
>>> '123.3'.isdigit()
False
# returns `False` for negative number
>>> '-123'.isdigit()
False
إذا كنت ترغب في أيضا التحقق من السلبية الاعداد الصحيحه ، float
, ثم يمكنك كتابة دالة مخصصة للتحقق من أنها:
def is_number(n):
try:
float(n) # Type-casting the string to `float`.
# If string is not a valid `float`,
# it'll raise `ValueError` exception
except ValueError:
return False
return True
عينة تشغيل:
>>> is_number('123') # positive integer number
True
>>> is_number('123.4') # positive float number
True
>>> is_number('-123') # negative integer number
True
>>> is_number('-123.4') # negative `float` number
True
>>> is_number('abc') # `False` for "some random" string
False
تجاهل "نان" (وليس عدد) سلاسل حين التحقق من عدد
المهام المذكورة أعلاه سوف يعود True
ل "نان" (وليس عدد) السلسلة لأن الثعبان هو صالح تطفو تمثل ليس عددا.على سبيل المثال:
>>> is_number('NaN')
True
من أجل التحقق من ما إذا كان الرقم "نان" ، يمكنك استخدام math.isnan()
كما:
>>> import math
>>> nan_num = float('nan')
>>> math.isnan(nan_num)
True
أو إذا كنت لا ترغب في استيراد مكتبة إضافية للتحقق من ذلك ، ثم يمكنك ببساطة التحقق من ذلك عن طريق مقارنتها مع نفسه باستخدام ==
.الثعبان يعود False
عندما nan
تطفو بالمقارنة مع نفسها.على سبيل المثال:
# `nan_num` variable is taken from above example
>>> nan_num == nan_num
False
ومن ثم فوق وظيفة is_number
يمكن تحديث العودة False
بالنسبة "NaN"
كما:
def is_number(n):
is_number = True
try:
num = float(n)
# check for "nan" floats
is_number = num == num # or use `math.isnan(num)`
except ValueError:
is_number = False
return is_number
عينة تشغيل:
>>> is_number('Nan') # not a number "Nan" string
False
>>> is_number('nan') # not a number string "nan" with all lower cased
False
>>> is_number('123') # positive integer
True
>>> is_number('-123') # negative integer
True
>>> is_number('-1.12') # negative `float`
True
>>> is_number('abc') # "some random" string
False
PS:كل عملية لكل الاختيار اعتمادا على نوع وعدد يأتي مع النفقات الإضافية.اختيار إصدار is_number
الوظيفة التي تناسب الاحتياجات الخاصة بك.
وأردت أن أرى الأسلوب الذي هو أسرع. عموما أعطيت أفضل وأكثر اتساقا النتائج وفقا لوظيفة check_replace
. وبالنظر إلى نتائج أسرع من قبل وظيفة check_exception
، ولكن فقط إذا لم يكن هناك استثناء النار - يعني رمزها هو الأكثر كفاءة، ولكن النفقات العامة من إلقاء استثناء هو كبير جدا
تجدر الإشارة إلى أن التحقق من يلقي الناجح هو الأسلوب الوحيد الذي غير دقيقة، على سبيل المثال، وهذا يعمل مع check_exception
إلا أن وظائف الاختبار الأخريين عودة كاذبة لتعويم صحيح:
huge_number = float('1e+100')
وهنا هو رمز القياسي:
import time, re, random, string
ITERATIONS = 10000000
class Timer:
def __enter__(self):
self.start = time.clock()
return self
def __exit__(self, *args):
self.end = time.clock()
self.interval = self.end - self.start
def check_regexp(x):
return re.compile("^\d*\.?\d*$").match(x) is not None
def check_replace(x):
return x.replace('.','',1).isdigit()
def check_exception(s):
try:
float(s)
return True
except ValueError:
return False
to_check = [check_regexp, check_replace, check_exception]
print('preparing data...')
good_numbers = [
str(random.random() / random.random())
for x in range(ITERATIONS)]
bad_numbers = ['.' + x for x in good_numbers]
strings = [
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(1,10)))
for x in range(ITERATIONS)]
print('running test...')
for func in to_check:
with Timer() as t:
for x in good_numbers:
res = func(x)
print('%s with good floats: %s' % (func.__name__, t.interval))
with Timer() as t:
for x in bad_numbers:
res = func(x)
print('%s with bad floats: %s' % (func.__name__, t.interval))
with Timer() as t:
for x in strings:
res = func(x)
print('%s with strings: %s' % (func.__name__, t.interval))
وفيما يلي النتائج مع بيثون 2.7.10 على 2017 ماك بوك برو 13:
check_regexp with good floats: 12.688639
check_regexp with bad floats: 11.624862
check_regexp with strings: 11.349414
check_replace with good floats: 4.419841
check_replace with bad floats: 4.294909
check_replace with strings: 4.086358
check_exception with good floats: 3.276668
check_exception with bad floats: 13.843092
check_exception with strings: 15.786169
وفيما يلي النتائج مع بايثون 3.6.5 على 2017 ماك بوك برو 13:
check_regexp with good floats: 13.472906000000009
check_regexp with bad floats: 12.977665000000016
check_regexp with strings: 12.417542999999995
check_replace with good floats: 6.011045999999993
check_replace with bad floats: 4.849356
check_replace with strings: 4.282754000000011
check_exception with good floats: 6.039081999999979
check_exception with bad floats: 9.322753000000006
check_exception with strings: 9.952595000000002
وفيما يلي النتائج مع PyPy 2.7.13 على 2017 ماك بوك برو 13:
check_regexp with good floats: 2.693217
check_regexp with bad floats: 2.744819
check_regexp with strings: 2.532414
check_replace with good floats: 0.604367
check_replace with bad floats: 0.538169
check_replace with strings: 0.598664
check_exception with good floats: 1.944103
check_exception with bad floats: 2.449182
check_exception with strings: 2.200056
وذلك لوضع كل ذلك معا، والتحقق من نان، واللانهاية والأعداد المركبة (على ما يبدو تم تحديد أنها مع ي، وليس أنا، أي 1 + 2J) أنه يؤدي إلى:
def is_number(s):
try:
n=str(float(s))
if n == "nan" or n=="inf" or n=="-inf" : return False
except ValueError:
try:
complex(s) # for complex
except ValueError:
return False
return True
فعلت بعض اختبار سرعة.دعنا نقول أنه إذا كانت السلسلة على الأرجح أن يكون عدد حاول/باستثناء استراتيجية أسرع وقت ممكن.إذا كانت السلسلة هو لا يحتمل أن يكون عدد و كنت مهتما في صحيح فحص قيمته إلى القيام ببعض اختبار (isdigit بالإضافة إلى عنوان '-').إذا كنت ترغب في التحقق من تعويم عدد, لديك لاستخدام حاول/باستثناء رمز whitout الهروب.
وأنا في حاجة إلى تحديد ما إذا كان سلسلة يلقي إلى أنواع أساسية (تعويم، الباحث، شارع، منطقي). بعد عدم العثور على أي شيء على الانترنت أنا خلقت هذا:
def str_to_type (s):
""" Get possible cast type for a string
Parameters
----------
s : string
Returns
-------
float,int,str,bool : type
Depending on what it can be cast to
"""
try:
f = float(s)
if "." not in s:
return int
return float
except ValueError:
value = s.upper()
if value == "TRUE" or value == "FALSE":
return bool
return type(s)
مثال
str_to_type("true") # bool
str_to_type("6.0") # float
str_to_type("6") # int
str_to_type("6abc") # str
str_to_type(u"6abc") # unicode
ويمكنك التقاط نوع واستخدامه
s = "6.0"
type_ = str_to_type(s) # float
f = type_(s)
المدخلات قد تكون على النحو التالي:
a="50"
b=50
c=50.1
d="50.1"
1-العامة الإدخال:
المدخلات من هذه الوظيفة يمكن أن تكون كل شيء!
يرى ما إذا كان متغير رقمية.السلاسل الرقمية تتكون من اختياري تسجيل أي عدد من الأرقام ، الاختياري عشري جزء اختياري الأسية الجزء.وبالتالي +0123.45e6 صالحة قيمة رقمية.الست عشري (على سبيل المثال0xf4c3b00c) الثنائية (مثل0b10100111001) التدوين هو غير مسموح به.
is_numeric وظيفة
import ast
import numbers
def is_numeric(obj):
if isinstance(obj, numbers.Number):
return True
elif isinstance(obj, str):
nodes = list(ast.walk(ast.parse(obj)))[1:]
if not isinstance(nodes[0], ast.Expr):
return False
if not isinstance(nodes[-1], ast.Num):
return False
nodes = nodes[1:-1]
for i in range(len(nodes)):
#if used + or - in digit :
if i % 2 == 0:
if not isinstance(nodes[i], ast.UnaryOp):
return False
else:
if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
return False
return True
else:
return False
الاختبار:
>>> is_numeric("54")
True
>>> is_numeric("54.545")
True
>>> is_numeric("0x45")
True
is_float وظيفة
يرى ما إذا كان المتغير هو تعويم.تطفو سلاسل تتكون من اختياري علامة ، أي عدد من الأرقام ...
import ast
def is_float(obj):
if isinstance(obj, float):
return True
if isinstance(obj, int):
return False
elif isinstance(obj, str):
nodes = list(ast.walk(ast.parse(obj)))[1:]
if not isinstance(nodes[0], ast.Expr):
return False
if not isinstance(nodes[-1], ast.Num):
return False
if not isinstance(nodes[-1].n, float):
return False
nodes = nodes[1:-1]
for i in range(len(nodes)):
if i % 2 == 0:
if not isinstance(nodes[i], ast.UnaryOp):
return False
else:
if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
return False
return True
else:
return False
الاختبار:
>>> is_float("5.4")
True
>>> is_float("5")
False
>>> is_float(5)
False
>>> is_float("5")
False
>>> is_float("+5.4")
True
ما هو ast?
2 - إذا كنت على ثقة من أن متغير المحتوى سلسلة:
استخدام str.isdigit() طريقة
>>> a=454
>>> a.isdigit()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'isdigit'
>>> a="454"
>>> a.isdigit()
True
3-إدخال العددية:
كشف الباحث القيمة:
>>> isinstance("54", int)
False
>>> isinstance(54, int)
True
>>>
الكشف عن تعويم:
>>> isinstance("45.1", float)
False
>>> isinstance(45.1, float)
True
ويشير ريان
<اقتباس فقرة>إذا كنت ترغب في عودة خطأ لنان والمشاة، تغيير الخط إلى x = تعويم (ق)؛ عودة (خ == خ) و (س - 1 = س). هذا يجب إرجاع صحيح لجميع يطفو إلا المشاة ونان
اقتباس فقرة> ولكن هذا لا تعمل تماما، وذلك لأن ليطفو كبيرة بما فيه الكفاية، x-1 == x
يعود صحيحا. على سبيل المثال، 2.0**54 - 1 == 2.0**54
وأعتقد أن الحل الخاص بك على ما يرام.
وأما وقد قلت ذلك، هناك الكثير من الكراهية التعبير العادي نحو هذه الإجابات التي أعتقد أنها غير مبررة، regexps يمكن أن تكون نظيفة بشكل معقول وصحيح وسريع. انها حقا يتوقف على ما كنت تحاول القيام به. كان السؤال الأصلي كيف يمكنك أن "معرفة ما اذا كان سلسلة يمكن أن تكون ممثلة على النحو عدد (تعويم)" (وفقا لقبك). يفترض كنت تريد استخدام قيمة رقمية / تعويم بمجرد التحقق من صحته، وفي هذه الحالة محاولة الخاص بك / باستثناء يجعل الكثير من معانيها. ولكن إذا، لسبب ما، كنت ترغب فقط للتحقق من أن <م> سلسلة م> هو رقم م> ثم باستخدام التعابير المنطقية أيضا يعمل بشكل جيد، ولكن من الصعب الحصول صحيحة. وأعتقد أن معظم الإجابات التعبير العادي حتى الآن، على سبيل المثال، لا تحليل السلاسل بدون جزءا صحيحا (مثل "0.7") وهو تعويم بقدر ما تشعر بالقلق الثعبان بشكل صحيح. وهذا صعب قليلا للتحقق من في التعابير المنطقية واحد حيث لا يشترط الجزء الكسري. لقد شملت اثنين من التعابير المنطقية لإظهار هذا.
فإنه لا يثير مسألة مثيرة للاهتمام على ما "عددا" هو. هل تشمل "المشع" التي هي سارية المفعول كما تعويم في بيثون؟ أو هل تشمل الأرقام التي هي "الأرقام" ولكن ربما لا يمكن تمثيلها في بيثون (مثل أرقام التي هي أكبر من الحد الأقصى تعويم).
وهناك أيضا الغموض في كيفية تحليل الأرقام. على سبيل المثال، ماذا عن "--20"؟ هل هذا "الرقم"؟ هذا هو وسيلة قانونية لتمثيل "20"؟ بيثون سيتيح لك ان تفعل "فار = --20" وتعيينه إلى 20 (على الرغم حقا هذا هو لأنه يعامل على أنه تعبير)، ولكن تعويم. ( "- 20") لا تعمل
وعلى أي حال، من دون مزيد من المعلومات، وهنا التعابير المنطقية التي أعتقد أنه يغطي كل [إينتس] ويطفو كما الثعبان يوزع لهم م>.
# Doesn't properly handle floats missing the integer part, such as ".7"
SIMPLE_FLOAT_REGEXP = re.compile(r'^[-+]?[0-9]+\.?[0-9]+([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56" # sign (-)
# integer (12)
# mantissa (34)
# exponent (E+56)
# Should handle all floats
FLOAT_REGEXP = re.compile(r'^[-+]?([0-9]+|[0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56" # sign (-)
# integer (12)
# OR
# int/mantissa (12.34)
# exponent (E+56)
def is_float(str):
return True if FLOAT_REGEXP.match(str) else False
وبعض القيم النموذجية الاختبار:
True <- +42
True <- +42.42
False <- +42.42.22
True <- +42.42e22
True <- +42.42E-22
False <- +42.42e-22.8
True <- .42
False <- 42nope
وأود أيضا أن تستخدم وظيفة التي ذكرتها، ولكن سرعان ما لاحظت أن سلاسل باسم "نان"، "المشاة" وانها الاختلاف تعتبر العدد. لذلك أنا أقترح عليك نسخة محسنة من وظيفة الخاص بك، والتي سيعود كاذبة على هذه النوع من المدخلات ولن تفشل المتغيرات "1E3":
def is_float(text):
try:
float(text)
# check for nan/infinity etc.
if text.isalpha():
return False
return True
except ValueError:
return False
import re
def is_number(num):
pattern = re.compile(r'^[-+]?[-0-9]\d*\.\d*|[-+]?\.?[0-9]\d*$')
result = pattern.match(num)
if result:
return True
else:
return False
>>>: is_number('1')
True
>>>: is_number('111')
True
>>>: is_number('11.1')
True
>>>: is_number('-11.1')
True
>>>: is_number('inf')
False
>>>: is_number('-inf')
False
وهذا الرمز يعالج الدعاة، يطفو، وصحيحة، من دون استخدام التعابير المنطقية.
return True if str1.lstrip('-').replace('.','',1).isdigit() or float(str1) else False
وهنا لي طريقة بسيطة للقيام بذلك. دعنا نقول أنني حلقات من خلال بعض الجمل وأريد أن إضافتها إلى مجموعة إذا كانت تتحول إلى أن تكون الأرقام.
try:
myvar.append( float(string_to_check) )
except:
continue
واستبدال myvar.apppend مع أي عملية تريد القيام به مع السلسلة إذا اتضح أن هناك عددا. والفكرة هي أن محاولة استخدام عملية تعويم () واستخدام الخطأ عاد لتحديد ما إذا كان أو لم يكن السلسلة عددا.
ويمكنك تعميم تقنية استثناء بطريقة مفيدة عن طريق إعادة القيم أكثر فائدة من الصواب والخطأ. على سبيل المثال هذه الوظيفة يضع نقلت جولة سلاسل ولكن يترك الأرقام وحدها. الذي هو بالضبط ما كنت بحاجة لتصفية سريعة وقذرة لكسب بعض التعريفات المتغيرة للR.
import sys
def fix_quotes(s):
try:
float(s)
return s
except ValueError:
return '"{0}"'.format(s)
for line in sys.stdin:
input = line.split()
print input[0], '<- c(', ','.join(fix_quotes(c) for c in input[1:]), ')'
وكنت أعمل على المشكلة التي دفعتني لهذا الموضوع، وهي كيفية تحويل مجموعة من البيانات إلى سلاسل والأرقام في الطريقة الأكثر بديهية. أدركت بعد قراءة التعليمات البرمجية الأصلية التي ما احتاجه كان مختلفا بطريقتين:
1 - أردت نتيجة صحيحا إذا مثلت سلسلة عدد صحيح
2 - كنت أرغب في عدد أو نتيجة سلسلة التمسك في بنية بيانات
ولذا فإنني تكييفها رمز الأصلي لإنتاج هذه المشتقات:
def string_or_number(s):
try:
z = int(s)
return z
except ValueError:
try:
z = float(s)
return z
except ValueError:
return s
وجرب هذا.
def is_number(var):
try:
if var == int(var):
return True
except Exception:
return False
وظيفة مساعد العضو:
def if_ok(fn, string):
try:
return fn(string)
except Exception as e:
return None
ثم
if_ok(int, my_str) or if_ok(float, my_str) or if_ok(complex, my_str)
is_number = lambda s: any([if_ok(fn, s) for fn in (int, float, complex)])
استخدم التالية أنه يتعامل مع جميع الحالات: -
import re
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' , '2.3')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' , '2.')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' , '.3')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' , '2.3sd')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' , '2.3')