57

次のようなことをしている古い Python コードを見つけました。

if type(var) is type(1):
   ...

予想どおり、pep8この推奨される の使用法について文句を言いisinstance()ます。

さて、問題は、numbersモジュールが Python 2.6 で追加され、Python 2.5+ で動作するコードを記述する必要があることです。

だからif isinstance(var, Numbers.number)解決策ではありません。

この場合、適切な解決策はどれでしょうか?

4

3 に答える 3

116

typesPython 2 では、次のモジュールを使用できます。

>>> import types
>>> var = 1
>>> NumberTypes = (types.IntType, types.LongType, types.FloatType, types.ComplexType)
>>> isinstance(var, NumberTypes)
True

複数の型に対してテストするためのタプルの使用に注意してください。

内部では、 などIntTypeの単なるエイリアスです。int

>>> isinstance(var, (int, long, float, complex))
True

このcomplex型では、Python が複素数をサポートするようにコンパイルされている必要があります。これを防ぎたい場合は、try/except ブロックを使用します。

>>> try:
...     NumberTypes = (types.IntType, types.LongType, types.FloatType, types.ComplexType)
... except AttributeError:
...     # No support for complex numbers compiled
...     NumberTypes = (types.IntType, types.LongType, types.FloatType)
...

または、型を直接使用するだけの場合:

>>> try:
...     NumberTypes = (int, long, float, complex)
... except NameError:
...     # No support for complex numbers compiled
...     NumberTypes = (int, long, float)
...

Python 3typesでは、標準の型エイリアスがなくなり、常に有効になり、 vsの違いcomplexがなくなったため、Python 3 では常に次を使用します。longint

NumberTypes = (int, float, complex)

最後になりましたが、numbers.Numbers抽象基本型(Python 2.6 の新機能) を使用して、上記の型から直接派生しないカスタム数値型もサポートできます。

>>> import numbers
>>> isinstance(var, numbers.Number)
True

このチェックでは、オブジェクトも返さTrueれます。decimal.Decimal()fractions.Fraction()

complexこのモジュールは、型が有効になっていることを前提としています。そうでない場合は、インポート エラーが発生します。

于 2012-06-26T09:57:53.337 に答える
21

Python 2 は、数値intfloatlongおよびの 4 つのタイプをサポートし、3complexpython 3.xサポートします: intfloatおよびcomplex

>>> num = 10
>>> if isinstance(num, (int, float, long, complex)): #use tuple if checking against multiple types
      print('yes it is a number')

yes it is a number
>>> isinstance(num, float)   
False
>>> isinstance(num, int)
True
>>> a = complex(1, 2)
>>> isinstance(a, complex)
True
于 2012-06-26T09:57:21.190 に答える
4

ダックタイピングでこれを使用しているものによっては、より良いアプローチになる可能性があります (確か に一般的に 推奨されています)。Martijn Pieters のアプローチの問題点は、リストから特定の種類の数値が常に失われることです。私の頭の上からあなたのコードは動作しません: sympy 有理数、任意精度の整数、および複素数の実装。

1 つの代替方法は、次のような関数を作成することです。

def is_number(thing):
    try:
        thing + 1
        return True
    except TypeError:
        return False

このコードは、数値の適切な実装で機能するはずです。もちろん、大きなマイナス面もあります: 多くの非数値の不当な実装でも機能します (つまり、プラス演算子がオーバーロードされ、整数を受け入れる場合)。

もう 1 つの方法 (何かが数値かどうかを知る必要がある理由によって異なります) は、それが数値であると仮定することです。そうでない場合は、コードのどのビットでも数値が必要な場合にエラーがスローされます。

これらのアプローチが常に優れていると言っているわけではありません (一部の人とは異なります...) 検討する価値があるというだけです。

于 2013-10-03T12:42:57.030 に答える