Python 変数の型を確認する最良の (慣用的な) 方法は何ですか?[重複]

StackOverflow https://stackoverflow.com/questions/378927

  •  22-08-2019
  •  | 
  •  

質問

この質問にはすでに答えがあります:

Python の変数が文字列なのか辞書なのかを知る必要があります。次のコードに何か問題がありますか?

if type(x) == type(str()):
    do_something_with_a_string(x)
elif type(x) == type(dict()):
    do_somethting_with_a_dict(x)
else:
    raise ValueError

アップデート:私は訪問者の答えを受け入れました(ただし、誰かが理由を説明したら考えを変えるでしょう) isinstance よりも優先されます type(x) is).

しかし、多くの場合、if/elif/else シリーズよりも dict を (case ステートメントとして) 使用する方がクリーンであることを思い出させてくれた、nakedfanatic に感謝します。

私の使用例について詳しく説明します。変数が文字列の場合は、それをリストに入れる必要があります。辞書の場合は、一意の値のリストが必要です。私が思いついたのは次のとおりです。

def value_list(x):
    cases = {str: lambda t: [t],
             dict: lambda t: list(set(t.values()))}
    try:
        return cases[type(x)](x)
    except KeyError:
        return None

もし isinstance が好ましいのですが、これはどのように書きますか value_list() 関数?

役に立ちましたか?

解決

誰かがあなたの関数にUnicode文字列を渡す場合、

はどうなりますか?または辞書から派生したクラス?あるいは辞書のようなインターフェースを実装するクラス?次のコードは、最初の2つのケースをカバーしています。あなたは、Python 2.6を使用している場合は、 collections.Mapping の代わりに使用することもできます ABCのPEPするとしてdictのます。

def value_list(x):
    if isinstance(x, dict):
        return list(set(x.values()))
    elif isinstance(x, basestring):
        return [x]
    else:
        return None

他のヒント

type(dict())は「新しい辞書を作成し、次にその型が何であるかを見つける」と言います。それはちょうど、「辞書」と言って迅速です。 あなただけの種類を確認したい場合でも、より多くの慣用的な方法がisinstance(x, dict)です。

注、そのisinstanceも含むサブクラス(おかげダスティンの)

class D(dict):
    pass

d = D()
print("type(d) is dict", type(d) is dict)  # -> False
print("isinstance (d, dict)", isinstance(d, dict))  # -> True

の名前で組み込みのPythonで型を構築しています:

>>> s = "hallo"
>>> type(s) is str
True
>>> s = {}
>>> type(s) is dict
True

ところでの演算子であることに注意。しかし、それは重要だ変数の型はあまりないようなタイプのチェックは(あなたがそれそれをコールする場合)は通常、のtry-除く句で型固有のテストをラップすることによって行われていますが、特定の操作を行うことができるかどうかこれとか何かます。

それは基本的にあなたがこれまでのdictまたはstrのサブクラスでそれを使用するための特殊なケースにあなたの古いコードを持っていないことを意味しており、スーパークラスだとあなたがオブジェクトインスタンスを比較するとき、それはまた、Trueとして評価されるため、

でisinstanceは種類以上preferrableです。

 >>> class a_dict(dict):
 ...     pass
 ... 
 >>> type(a_dict()) == type(dict())
 False
 >>> isinstance(a_dict(), dict)
 True
 >>> 

もちろん、あなたがこの動作を望んでいないだろうが、それらは、あなたがそれをしたいですか状況よりもはるかに少ない共通-hopefully-されている状況があるかもしれません。

私はダックタイピングのアプローチのために行くだろうと思う - 「それはアヒルのように歩き場合、それはアヒル、そのアヒルのように鳴きます」。この方法は、あなたは、文字列がUnicodeまたはASCIIであれば心配する必要はないでしょう。

ここで私は何をするかです。

In [53]: s='somestring'

In [54]: u=u'someunicodestring'

In [55]: d={}

In [56]: for each in s,u,d:
    if hasattr(each, 'keys'):
        print list(set(each.values()))
    elif hasattr(each, 'lower'):
        print [each]
    else:
        print "error"
   ....:         
   ....:         
['somestring']
[u'someunicodestring']
[]

ここでの専門家はダック・タイピングの使用法のこのタイプにコメントを歓迎しており、私はそれを使用していたが、最近はその背後に正確な概念を導入し、それについて非常に興奮していました。だから私は行うには行き過ぎのthatsかどうかを知りたいと思います。

私は実際に

を行うことが好ましいかもしれないと思います
if isinstance(x, str):
    do_something_with_a_string(x)
elif isinstance(x, dict):
    do_somethting_with_a_dict(x)
else:
    raise ValueError

2つの代替形式は、あなたのコードに応じて、1つまたは他のは、おそらくそれさえもより良いと考えられています。一つは、あなたが飛躍する前に見ていないことです。

try:
  one, two = tupleOrValue
except TypeError:
  one = tupleOrValue
  two = None

他のアプローチは、グイドからのものであり、よりオープンが終了し、あなたのコードを残し関数のオーバーロードの形である。

http://www.artima.com/weblogs/viewpost.jsp?スレッド= 155514

これは動作するはずです - ので、いや、あなたのコードは何も問題はありません。しかし、それはまた、辞書で行うことができます:

{type(str()): do_something_with_a_string,
 type(dict()): do_something_with_a_dict}.get(type(x), errorhandler)()

もう少し簡潔で神託あなたは言わないだろう?

<時間>

編集..聞き入れAvisserのアドバイス、コードはこのように動作します、と立派に見えます:

{str: do_something_with_a_string,
 dict: do_something_with_a_dict}.get(type(x), errorhandler)()

あなたはです。TypeCheckをチェックアウトすることができます。 http://pypi.python.org/pypi/typecheckする

Python用型チェックモジュール

このパッケージには、Pythonの関数、メソッド、および発電機のための強力な実行時の型チェック機能を提供します。言語へのカスタムプリプロセッサまたは変更を必要とせずに、です。TypeCheckパッケージは、プログラマーや品質保証エンジニアは自分のコードからの入力、および出力についての正確な表明を行うことができます。

私は別のアプローチを使用してきた。

from inspect import getmro
if (type([]) in getmro(obj.__class__)):
    # This is a list, or a subclass of...
elif (type{}) in getmro(obj.__class__)):
    # This one is a dict, or ...
私はこれを使用した理由

私は思い出すことができない代わりでisinstanceの、しかし...

*sigh*

いいえ、Pythonで型チェックの引数は必要ありません。それは には決してあり 必要に応じています。

あなたのコードは、文字列または辞書オブジェクトのいずれかを受け入れる場合、

、あなたのデザインが壊れてます。

あなたはすでにオブジェクトの種類がわからない場合という事実から来ています 独自のプログラムで、あなたはすでに何か間違ったことをやってます。

型チェックは、コードの再利用を痛いとパフォーマンスが低下します。その機能を有します 渡されたオブジェクトの種類に応じて異なることをされ実行 バグが発生しやすいと理解し、維持するために難しく振る舞いを持っています。

次の正気のオプションがあります:

1)の値のユニークなリストにdictsを変換する関数のunique_valuesを作成します:

def unique_values(some_dict):
    return list(set(some_dict.values()))

あなたの関数は、渡された引数が常にリストであると仮定してください。そのように、あなたが関数に文字列を渡す必要がある場合は、あなただけ行います:

myfunction([some_string])

あなたはそれを辞書を渡す必要がある場合は、あなたが実行します。

myfunction(unique_values(some_dict))

それはあなたの最良の選択肢だ、それは、きれいな理解と保守が容易です。誰でも immediatellyコードを読むことは何が起こっているのかを理解し、あなたはありません です。TypeCheckします。

2)二つの関数、文字列のリストを受け付け1と受け入れるものを作ります dicts。あなたは1つが最も便利で、内部的に他のを呼び出すことができます 道(myfunction_dictは、文字列のリストを作成し、myfunction_list呼び出すことができます)。

どのような場合には、 のです。TypeCheckません。それは完全に不必要であり、唯一持っています 欠点。代わりに、あなたがです。TypeCheckする必要はありません方法であなたのコードをリファクタリング。 あなたは、両方の短期および長期的には、そうすることで利益を得るだけます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top