Pythonでnullオブジェクトをどうやって参照するのですか?
Pythonでは、 'null'オブジェクトはシングルトンNone
です。
「なし」をチェックする最も良い方法は、恒等演算子is
を使うことです。
if foo is None:
...
None
、Pythonのnull?Pythonにはnull
はありませんが、代わりにNone
があります。すでに述べたように、何かに値としてNone
が与えられていることをテストする最も正確な方法は、2つの変数が同じオブジェクトを参照していることをテストするis
identity演算子を使うことです。
>>> foo is None
True
>>> foo = 'bar'
>>> foo is None
False
None
は1つしか存在できませんNone
はクラスNoneType
の唯一のインスタンスであり、そのクラスをインスタンス化しようとするさらなる試みは同じオブジェクトを返します。これはNone
をシングルトンにします。 Pythonを初めて使う人は、NoneType
に言及するエラーメッセージをよく見て、それが何であるか疑問に思います。私たちの個人的な見解では、これらのメッセージは単に名前でNone
に言及することができますが、すぐにわかるように、None
はあいまいさの余地がほとんどないためです。 TypeError
がこれを実行できない、または実行できないことを示すNoneType
メッセージが表示された場合は、それができない方法で使用されているのは単にNone
であることを確認してください。
また、None
は組み込み定数です。Pythonを起動するとすぐに、モジュール、クラス、関数のどこからでも使用できるようになります。対照的にNoneType
はそうではありません、あなたはそのクラスのためにNone
を問い合わせることによってそれへの参照を最初に得る必要があるでしょう。
>>> NoneType
NameError: name 'NoneType' is not defined
>>> type(None)
NoneType
None
の一意性はPythonの恒等関数id()
で確認できます。オブジェクトに割り当てられた一意の番号を返します。各オブジェクトには1つあります。 2つの変数のIDが同じ場合、それらは実際には同じオブジェクトを指します。
>>> NoneType = type(None)
>>> id(None)
10748000
>>> my_none = NoneType()
>>> id(my_none)
10748000
>>> another_none = NoneType()
>>> id(another_none)
10748000
>>> def function_that_does_nothing(): pass
>>> return_value = function_that_does_nothing()
>>> id(return_value)
10748000
None
は上書きできません非常に古いバージョンのPython(2.4以前)では、None
を再割り当てすることは可能でしたが、もうそうすることはできません。クラス属性としてでも、関数の範囲内でも。
# In Python 2.7
>>> class SomeClass(object):
... def my_fnc(self):
... self.None = 'foo'
SyntaxError: cannot assign to None
>>> def my_fnc():
None = 'foo'
SyntaxError: cannot assign to None
# In Python 3.5
>>> class SomeClass:
... def my_fnc(self):
... self.None = 'foo'
SyntaxError: invalid syntax
>>> def my_fnc():
None = 'foo'
SyntaxError: cannot assign to keyword
したがって、すべてのNone
参照は同じであると仮定しても安全です。 "カスタム" None
はありません。
None
をテストするには、is
演算子を使用します。コードを書くとき、 なし のようにテストしたくなるかもしれません。
if value==None:
pass
またはこのような虚偽をテストする
if not value:
pass
あなたはその意味を理解する必要があります、そしてなぜそれがしばしば明白であることが良い考えであるか。
None
かどうかをテストするなぜこれをするのか
value is None
のではなく
value==None
最初のものは以下と同等です。
id(value)==id(None)
式value==None
は実際にはこのように適用されますが
value.__eq__(None)
値が本当にNone
であれば、あなたはあなたが期待したものを得るでしょう。
>>> nothing = function_that_does_nothing()
>>> nothing.__eq__(None)
True
ほとんどの場合、結果は同じになりますが、__eq__()
メソッドはクラス内でオーバーライドされて特別な動作を提供する可能性があるため、正確さの保証を無効にする扉を開きます。
このクラスを考えてください。
>>> class Empty(object):
... def __eq__(self, other):
... return not other
それであなたはそれをNone
で試してみてそれは機能します
>>> empty = Empty()
>>> empty==None
True
しかし、それからそれはまた空の文字列にも働きます
>>> empty==''
True
そしてまだ
>>> ''==None
False
>>> empty is None
False
None
をブール値として使用次の2つのテスト
if value:
# do something
if not value:
# do something
実際には
if bool(value):
# do something
if not bool(value):
# do something
None
は "falsey"です。つまり、ブール値にキャストするとFalse
が返され、not
演算子を適用するとTrue
が返されます。ただし、None
に固有のプロパティではありません。 False
自体に加えて、このプロパティは空のリスト、タプル、セット、辞書、文字列、0、およびFalse
を返す__bool__()
マジックメソッドを実装するクラスのすべてのオブジェクトによって共有されます。
>>> bool(None)
False
>>> not None
True
>>> bool([])
False
>>> not []
True
>>> class MyFalsey(object):
... def __bool__(self):
... return False
>>> f = MyFalsey()
>>> bool(f)
False
>>> not f
True
したがって、次の方法で変数をテストするときは、テストに含めたり、テストから除外したりしているものに特に注意してください。
def some_function(value=None):
if not value:
value = init_value()
上記では、値が特にNone
に設定されているときにinit_value()
を呼び出すことを意味しましたか、それとも0
、空の文字列、または空のリストに設定された値も初期化を引き起こすべきです。私が言ったように、注意してください。 Pythonではよくあることですが、 明示的は暗黙的よりも優れています 。
None
None
None
はPythonでは特別な地位を占めています。多くのアルゴリズムが例外的な値として扱うので、これはお気に入りのベースライン値です。このようなシナリオでは、条件が何らかの特別な処理(デフォルト値の設定など)を必要とすることを知らせるためのフラグとして使用できます。
None
を関数のキーワード引数に割り当てて、それを明示的にテストすることができます。
def my_function(value, param=None):
if param is None:
# do something outrageous!
オブジェクトの属性にたどり着き、それから何か特別なことをする前に明示的にそれをテストしようとするときは、デフォルトとしてそれを返すことができます。
value = getattr(some_obj, 'some_attribute', None)
if value is None:
# do something spectacular!
デフォルトでは、辞書のget()
メソッドは存在しないキーにアクセスしようとするとNone
を返します。
>>> some_dict = {}
>>> value = some_dict.get('foo')
>>> value is None
True
添え字表記を使ってアクセスしようとした場合、KeyError
が発生します。
>>> value = some_dict['foo']
KeyError: 'foo'
存在しないアイテムをポップしようとした場合も同様
>>> value = some_dict.pop('foo')
KeyError: 'foo'
通常はNone
に設定されているデフォルト値で抑制できます。
value = some_dict.pop('foo', None)
if value is None:
# booom!
None
上で説明したNone
の使用は、それが有効な値と見なされていないときに適用されますが、何か特別なことをするためのシグナルのようなものです。ただし、None
がどこから来たのかを知ることが重要な場合があります。なぜなら、それがシグナルとして使用されていても、それがデータの一部である可能性もあるからです。
getattr(some_obj, 'attribute_name', None)
を使用してオブジェクトの属性を照会したときに、None
は、アクセスしようとしていた属性がNone
に設定されているかどうか、またはオブジェクトにまったく含まれていないかどうかを通知しません。 some_dict.get('some_key')
のような辞書からキーにアクセスするときと同じ状況で、some_dict['some_key']
が見つからないのか、それがNone
に設定されているのかはわかりません。その情報が必要な場合、これを処理する通常の方法は、try/except
構造内から属性またはキーに直接アクセスすることです。
try:
# equivalent to getattr() without specifying a default
# value = getattr(some_obj, 'some_attribute')
value = some_obj.some_attribute
# now you handle `None` the data here
if value is None:
# do something here because the attribute was set to None
except AttributeError:
# we're now hanling the exceptional situation from here.
# We could assign None as a default value if required.
value = None
# In addition, since we now know that some_obj doesn't have the
# attribute 'some_attribute' we could do something about that.
log_something(some_obj)
Dictと同じです。
try:
value = some_dict['some_key']
if value is None:
# do something here because 'some_key' is set to None
except KeyError:
# set a default
value = None
# and do something because 'some_key' was missing
# from the dict.
log_something(some_dict)
上記の2つの例は、オブジェクトと辞書のケースを処理する方法を示しています。同じことですが、そのためにはダブルアスタリスクキーワード引数を使用します。
def my_function(**kwargs):
try:
value = kwargs['some_key']
if value is None:
# do something because 'some_key' is explicitly
# set to None
except KeyError:
# we assign the default
value = None
# and since it's not coming from the caller.
log_something('did not receive "some_key"')
None
は有効な値としてのみ使用されますあなたのコードが単にNone
フラグとNone
データを区別するために上記のtry/except
パターンで散らばっているのを見つけたならば、ただ別のテスト値を使ってください。一連の有効な値の範囲外の値がデータ構造のデータの一部として挿入され、特別な条件(境界、状態など)の制御とテストに使用されるパターンがあります。このような値は センチネル と呼ばれ、None
がシグナルとして使用される方法で使用できます。 Pythonでセンチネルを作るのは簡単です。
undefined = object()
上記のundefined
オブジェクトはユニークで、プログラムにとって重要なことはほとんどしません。したがって、フラグとしてのNone
の代わりになる優れたものです。いくつかの注意点が適用されますが、それについてはコードの後に詳しく説明します。
機能付き
def my_function(value, param1=undefined, param2=undefined):
if param1 is undefined:
# we know nothing was passed to it, not even None
log_something('param1 was missing')
param1 = None
if param2 is undefined:
# we got nothing here either
log_something('param2 was missing')
param2 = None
口述とは
value = some_dict.get('some_key', undefined)
if value is None:
log_something("'some_key' was set to None")
if value is undefined:
# we know that the dict didn't have 'some_key'
log_something("'some_key' was not set at all")
value = None
オブジェクトあり
value = getattr(obj, 'some_attribute', undefined)
if value is None:
log_something("'obj.some_attribute' was set to None")
if value is undefined:
# we know that there's no obj.some_attribute
log_something("no 'some_attribute' set on obj")
value = None
前述したように、カスタムセンチネルには注意点がいくつかあります。まず、それらはNone
のようなキーワードではないので、pythonはそれらを保護しません。上記のundefined
は、それが定義されているモジュール内の任意の場所でいつでも上書きできます。そのため、それらを公開して使用する方法には注意してください。次に、object()
によって返されるインスタンスはシングルトンではありません、あなたがその呼び出しを10回行うと、あなたは10個の異なるオブジェクトを取得します。最後に、センチネルの使用法は非常に独特です。センチネルはそれが使用されているライブラリに固有のものであり、その範囲は一般にライブラリの内部に限定されるべきです。 「漏れる」べきではありません。外部コードは、その目的がライブラリのAPIを拡張または補足することである場合にのみ、認識されるようにしてください。
他の言語のようにnullと呼ばれるのではなく、 None
となります。このオブジェクトのインスタンスは常に1つだけなので、必要に応じて、x is None
の代わりにx == None
(識別情報の比較)で等価性をチェックできます。
Pythonでは、値が存在しないことを表すために、オブジェクトにはNone value(types.NoneType.None)、""(または_)を使用できます。文字列の場合はlen()== 0)。したがって:
if yourObject is None: # if yourObject == None:
...
if yourString == "": # if yourString.len() == 0:
...
"=="と "is"の違いについては、 "=="を使用してオブジェクトの同一性をテストするだけで十分です。ただし、「is」という操作はオブジェクト識別操作として定義されているため、「==」ではなく、それを使用する方がおそらく適切です。速度差さえあるかどうかわからない。
とにかく、あなたは見てみることができます:
Per 真理値テスト 、 'None'は直接FALSEとしてテストするので、最も単純な式で十分です。
if not foo: