2016-11-16 17 views
2

私はPythonの+ =構文について読み始めて、次のポスト/答えにつまずい: Interactive code about +=フレームとオブジェクトの違いは何ですか?フレームとオブジェクトの違いは何ですか?

それでは、私が気づいたことは、フレームとオブジェクト間の違いがあるように思われるということでした。グローバルフレームで

Frames and Objects

、彼らは別の変数をしているにもかかわらず、同じオブジェクトを指しています。ライン

ではなく

l2 = l2 + [item] 

した場合は、その行が実行されるときに 'L2' は別々のオブジェクトになります。私の最大の疑問は、変数が別のオブジェクトを指し示すようにしたい場合です。また、なぜ同じオブジェクトを指し続けるのはなぜですか?

説明や使用例があれば幸いです!データサイエンスに関連するものについて言及できる場合は特にお礼を言いたいと思います。

+2

呼び出しスタックについて話している場合、[フレーム](https://en.wikipedia.org/wiki/Call_stack#STACK-FRAME)は、ローカルに作成されたすべてのオブジェクトを含むものです即時の範囲。あなたのスクリーンショットでは、青いボックス全体が1つのフレームであり、 'l1'、' l2'、および 'item'という名前に関連付けられたオブジェクトを含んでいます。フレームを直接制御することはできません。オブジェクトとその名前だけを制御できます。 – Kevin

答えて

3

frameobjectは、それらが意味するとは限りません。

プログラミングでは、スタックと呼ばれるものがあります。 Pythonでは、関数を呼び出すと、スタックフレームという名前のものが作成されます。このフレームは、基本的には、関数のローカルなすべての変数のテーブルです(例のように)。

関数を定義すると、という関数が新しいスタックフレームを作成しません。という関数が呼び出されます。例えば、このような何か:say_hello

def say_hello(): 
    name = input('What is your name?') 
    print('Hello, {}'.format(name)) 

あなたのグローバルフレームは、ただ一つの参照を保持しようとしています。

print(locals()) 

をあなたはこのようなものが表示されます:あなたは(:名前空間の間の1の関係、範囲、およびフレームスタックPythonであなたはほとんどが1を持っている)ローカル名前空間に何があるかチェックアウトしていることがわかります:名前(ダブルアンダースコア2つのアンダースコアのために短い)

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x1019bb320>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/private/tmp/fun.py', '__cached__': None, 'say_hello': <function say_hello at 0x101962d90>} 

注dunder - これらは自動的に提供され、そして私たちの議論の目的のために、あなたはそれらを無視することができます。それでは、私たちは次のようになります。

{'say_hello': <function say_hello at 0x101962d90>} 

その0xビットは、関数自体が存在するメモリアドレスです。そこでここでは、グローバルスタック/フレームにはその値が1つだけ含まれています。関数を呼び出してlocals()を再度チェックすると、nameは存在しないことがわかります。これは、関数を呼び出すときに新しいスタックフレームを作成し、そこに変数が割り当てられるからです。これは、関数の最後にprint(locals())を追加することで証明できます。次に、次のようなものが表示されます:

{'name': 'Arthur, King of the Brits'} 

ここではダンダーの名前はありません。また、メモリアドレスは表示されません。この価値がどこにあるのかを知りたい場合は、そのための機能があります。それはフレームについて話したときの例では、何を意味するのかだ

def say_hello(): 
    name = input('What is your name?') 
    print('hello {}'.format(name)) 
    print(locals()) 
    print(id(name)) 
    return name 

print(id(say_hello())) 

しかし、オブジェクトについてはどうですか?まあ、Pythonでは、すべてはオブジェクトです。ちょうどそれを試してみてください。

>>> isinstance(3, object) 
True 
>>> isinstance(None, object) 
True 
>>> isinstance('hello', object) 
True 
>>> isinstance(13.2, object) 
True 
>>> isinstance(3j, object) 
True 
>>> def fun(): 
... print('hello') 
... 
>>> isinstance(fun, object) 
True 
>>> class Cool: pass 
... 
>>> isinstance(Cool, object) 
True 
>>> isinstance(Cool(), object) 
True 
>>> isinstance(object, object) 
True 
>>> isinstance(isinstance, object) 
True 
>>> isinstance(True, object) 
True 

彼らはすべてオブジェクトです。しかし、それらは異なるオブジェクトかもしれません。あなたはどうやって話すことができますか? idで:

>>> id(3) 
4297619904 
>>> id(None) 
4297303920 
>>> id('hello') 
4325843048 
>>> id('hello') 
4325843048 
>>> id(13.2) 
4322300216 
>>> id(3j) 
4325518960 
>>> id(13.2) 
4322300216 
>>> id(fun) 
4322635152 
>>> id(isinstance) 
4298988640 
>>> id(True) 
4297228640 
>>> id(False) 
4297228608 
>>> id(None) 
4297303920 
>>> id(Cool) 
4302561896 

あなたはまた、二つのオブジェクトかどうかを比較することができます注isを使用して同じオブジェクトです。

>>> True is False 
False 
>>> True is True 
True 
>>> 'hello world' is 'hello world' 
True 
>>> 'hello world' is ('hello ' + 'world') 
False 
>>> 512 is (500+12) 
False 
>>> 23 is (20+3) 
True 

Ehhhhh ...?ちょっと待って、何が起こったの?さて、それが判明したように、python(すなわち、CPython)caches small integers。したがって、オブジェクト512は、オブジェクト12に追加されたオブジェクト500の結果であるオブジェクトとは異なります。注意すべき

一つ重要なことは、代入演算子=常に同じオブジェクトに新しい名前を割り当てることです。たとえば、次のように

>>> x = 592 
>>> y = 592 
>>> x is y 
False 
>>> x == y 
True 
>>> x = y 
>>> x is y 
True 
>>> x == y 
True 

そして、あなたがオブジェクトを与える、またはあなたがobject around to different framesを渡す場合でも、あなたはまだ、同じオブジェクトを持っているどのように多くの他の名前は重要ではありません。

しかし、あなたが収集するために開始しているとして、それは変更新しいオブジェクトを生成したオブジェクトと操作される操作の違いを理解することが重要です。一般的には、Pythonでfew immutable typesがあり、それらの操作によって新しいオブジェクトが生成されます。

あなたの質問については、いつオブジェクトを変更したいのですか?いつそれらを同じにしておきたいのですか?実際には間違った方法で見ています。変更が必要な場合は変更可能な型を使用し、変更したくない場合は変更不可能な型を使用します。

たとえば、グループがあり、グループにメンバーを追加したいとします。リストのような変更可能な型を使用してグループを追跡したり、メンバを表す文字列のような不変型を使用することができます。このように:

>>> group = [] 
>>> id(group) 
4325836488 
>>> group.append('Sir Lancelot') 
>>> group.append('Sir Gallahad') 
>>> group.append('Sir Robin') 
>>> group.append("Robin's Minstrels") 
>>> group.append('King Arthur') 
>>> group 
['Sir Lancelot', 'Sir Gallahad', 'Sir Robin', "Robin's Minstrels", 'King Arthur'] 

グループのメンバーが食べられるとどうなりますか?

>>> del group[-2] # And there was much rejoicing 
>>> id(group) 
4325836488 
>>> group 
['Sir Lancelot', 'Sir Gallahad', 'Sir Robin', 'King Arthur'] 

メンバーが変更されているにもかかわらず、同じグループがまだ存在することがわかります。

+0

非常に有益な答えです。フォローアップの質問:すべてのオブジェクトはヒープ上に存在しますか? – flow2k

関連する問題