سؤال

هل هناك وظيفة موجودة في Numpy ستخبرني ما إذا كانت القيمة إما نوعًا رقميًا أو صفيفًا numpy؟ أنا أكتب بعض رمز معالجة البيانات التي تحتاج إلى التعامل مع الأرقام في عدة تمثيلات مختلفة (عن طريق "الرقم" أعني أي تمثيل لكمية رقمية يمكن معالجتها باستخدام مشغلي الحساب القياسي ، +، -، *، /، * *).

بعض الأمثلة على السلوك الذي أبحث عنه

>>> is_numeric(5)
True
>>> is_numeric(123.345)
True
>>> is_numeric('123.345')
False
>>> is_numeric(decimal.Decimal('123.345'))
True
>>> is_numeric(True)
False
>>> is_numeric([1, 2, 3])
False
>>> is_numeric([1, '2', 3])
False
>>> a = numpy.array([1, 2.3, 4.5, 6.7, 8.9])
>>> is_numeric(a)
True
>>> is_numeric(a[0])
True
>>> is_numeric(a[1])
True
>>> is_numeric(numpy.array([numpy.array([1]), numpy.array([2])])
True
>>> is_numeric(numpy.array(['1'])
False

إذا لم تكن هناك وظيفة من هذا القبيل ، فأنا أعلم أنه لا ينبغي أن يكون من الصعب كتابة واحدة ، شيء مثل

isinstance(n, (int, float, decimal.Decimal, numpy.number, numpy.ndarray))

ولكن هل هناك أنواع رقمية أخرى يجب أن أدرجها في القائمة؟

هل كانت مفيدة؟

المحلول

كما أجاب الآخرون ، يمكن أن يكون هناك أنواع رقمية أخرى إلى جانب تلك التي ذكرتها. تتمثل إحدى الطرق في التحقق بشكل صريح من القدرات التي تريدها ، مع شيء مثل

# Python 2
def is_numeric(obj):
    attrs = ['__add__', '__sub__', '__mul__', '__div__', '__pow__']
    return all(hasattr(obj, attr) for attr in attrs)

# Python 3
def is_numeric(obj):
    attrs = ['__add__', '__sub__', '__mul__', '__truediv__', '__pow__']
    return all(hasattr(obj, attr) for attr in attrs)

هذا يعمل لجميع الأمثلة الخاصة بك باستثناء آخر واحد ، numpy.array(['1']). هذا بسبب numpy.ndarray لديه الطرق الخاصة للعمليات الرقمية ولكنه يرفع Typeerror إذا حاولت استخدامها بشكل غير لائق مع صفائف السلسلة أو الكائنات. يمكنك إضافة شيك صريح لهذا مثل

 ... and not (isinstance(obj, ndarray) and obj.dtype.kind in 'OSU')

قد يكون هذا جيدًا بما فيه الكفاية.

لكن ... لا يمكنك أن تكون أبدًا 100% تأكد من أن شخصًا ما لن يحدد نوعًا آخر بنفس السلوك ، لذا فإن الطريقة الأكثر مضمونًا هي محاولة إجراء حساب ومسك بالاستثناء ، شيء مثل

def is_numeric_paranoid(obj):
    try:
        obj+obj, obj-obj, obj*obj, obj**obj, obj/obj
    except ZeroDivisionError:
        return True
    except Exception:
        return False
    else:
        return True

ولكن بناءً على عدد المرات التي تخطط فيها لاستخدامها باستخدامه ومع ما هي الوسيطات ، قد لا يكون هذا عمليًا (يمكن أن يكون بطيئًا ، على سبيل المثال مع المصفوفات الكبيرة).

نصائح أخرى

بشكل عام ، تتمثل الطريقة المرنة والسريعة والثني للتعامل مع أنواع غير معروفة فقط في القيام ببعض العمليات عليها والاستثناء من أنواع غير صالحة.

try:
    a = 5+'5'
except TypeError:
    print "Oops"

يبدو لي أن هذا النهج أسهل من إخراج بعض الوظائف لتحديد اليقين المطلق.

أيضا ، نومبي لديه numpy.isreal وغيرها من الوظائف المماثلة (numpy.is + يجب أن تسردها علامة التبويب).

لديهم جميعًا حالات ركنية ممتعة ولكن واحدة من تلك قد تكون مفيدة.

لك is_numeric غير محدد. انظر تعليقاتي على سؤالك.

يمكن أن تكون الأنواع العددية الأخرى: long, complex, fractions.Fraction, numpy.bool_, numpy.ubyte, ...

operator.isNumberType() عائدات True لأرقام بيثون و numpy.array.

منذ Python 2.6 يمكنك استخدام isinstance(d, numbers.Number) بدلا من الانخفاض operator.isNumberType().

بشكل عام ، من الأفضل التحقق من قدرات الكائن (على سبيل المثال ، سواء كان يمكنك إضافة عدد صحيح إليه) وليس نوعه.

isinstance(numpy.int32(4), numbers.Number) عائدات False, ، لذلك هذا لا يعمل تماما. operator.isNumberType() هل يعمل على جميع المتغيرات من الأرقام numpy ، بما في ذلك numpy.array([1]).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top