1

関数に渡された代入演算子、コンストラクター、およびパラメーターが、特にリストとオブジェクトを使用して Python でどのように機能するかを理解しようとしています。パラメータとしてリストを持つクラスがあります。空のリストに初期化してから、コンストラクターを使用して入力したいと考えています。私はそれを行う方法がよくわかりません。

私のクラスが -

class A:
    List = []                   # Point 1

    def __init1__(self, begin=[]): # Point 2
        for item in begin:
            self.List.append(item)

    def __init2__(self, begin):  # Point 3
        List = begin

    def __init3__(self, begin=[]): # Point 4
        List = list()
        for item in begin:
            self.List.append(item)


listObj = A()

del(listObj)

b = listObj

次の質問があります。誰かがそれぞれのケースで何が起こるかを明らかにできれば素晴らしいだろう -

  1. ポイント1のように空の宣言は有効ですか? 何が作成されますか?NULL を指す変数?

  2. ポイント 2 とポイント 3 のどちらが有効なコンストラクターですか? ポイント 3 では、渡されたリスト (begin) の新しいコピーが作成されず、代わりに変数 List がポインター「begin」を指していると推測しています。ポイント 2 のようにコンストラクターを使用すると、リストの新しいコピーが作成されますか?

  3. del を使用してオブジェクトを削除するとどうなりますか? リストも削除されますか、または含まれているオブジェクトで del を呼び出す前に、List で del を呼び出す必要がありますか? Python が GC を使用していることは知っていますが、GC が作動する前であっても未使用のメモリをクリーンアップすることを懸念している場合、その価値はありますか?

  4. また、タイプ A のオブジェクトを別のオブジェクトに割り当てると、2番目のオブジェクトが最初の右を指すだけになりますか? もしそうなら、ディープコピーを行うにはどうすればよいですか? 演算子をオーバーロードする機能はありますか? Pythonはおそらくこれよりもはるかに単純であることを知っているため、質問です。

編集: 5. ポイント 2 とポイント 3 を使用しても違いがないことに気付きました。リストの先頭からの項目は、参照によってのみコピーされ、新しいコピーは作成されません。そのためには、list() を使用して新しいリストを作成する必要があります。これは、私が推測した後、私がそれを見た後、理にかなっています。

ありがとう!

4

2 に答える 2

2

順番に:

  1. この形式を使用することは、リスト コンストラクターを呼び出すための単純な構文糖衣です。つまり、新しい (空の) リストを作成しています。これはクラス自体 (静的フィールド) にバインドされ、すべてのインスタンスで同じになります。
  2. 常にinitでなければならないコンストラクター名は別として、どちらも有効な形式ですが、意味は異なります。
    • 最初のコンストラクターは、引数としてリストを指定して、または指定せずに呼び出すことができます。引数なしで呼び出された場合、デフォルトとして渡された空のリストが内部で使用されるため (この空のリストは、コンストラクター呼び出しごとに 1 回ではなく、クラス定義中に 1 回作成されます)、静的リストにアイテムは追加されません。
    • 2 番目は list パラメーターで呼び出す必要があります。そうしないと、python はエラーを出しますが、self なしで使用します。あなたがやっているように接頭辞を付けると、コンストラクタ内でのみアクセス可能な新しいローカル変数名Listが作成され、静的なA.List変数は変更されません。
  3. 削除すると、実際には何も削除されずに、オブジェクトへの参照がリンク解除されるだけです。ただし、すべての参照が削除されると、ガベージ コレクターは必要に応じて自由にメモリをクリアできます。通常、ガベージ コレクタを制御しようとするのは悪い考えです。代わりは。不要になったオブジェクトへの参照を保持していないことを確認し、それを機能させてください。
  4. オブジェクトに変数を割り当てると、同じオブジェクトへの新しい参照のみが作成されます。ディープ コピーを作成するには、関連する関数を使用するか、独自の関数を記述します。
  5. クラス定義でいくつかの特別なメソッドをオーバーライドすることで、演算子のオーバーロード (注意して使用してください。誤って使用すると、わかりやすくなるどころか、混乱を招く可能性があります) を行うことができます。

あなたの編集について:私が上で指摘したように、自己なしでコンストラクタ内にList=list()を書くとき。(または、変数が静的であるため、A.)プレフィックスを使用すると、空の変数を作成するだけで、クラス本体で定義した変数をオーバーライドしません。

参考までに、リストをデフォルトの引数として処理する通常の方法は、Noneプレースホルダーを使用することです。

class A(object):
   def __init__(self, arg=None):
      self.startvalue = list(arg) if arg is not None else list()
      # making a defensive copy of arg to keep the original intact

余談ですが、pythonチュートリアルを見てください。それは非常によく書かれており、従うのも理解するのも簡単です。

于 2013-03-30T21:16:33.713 に答える
1

「誰かがそれぞれのケースで何が起こるかを明確にできたら素晴らしいだろう」それが dis モジュールの目的ではありませんか? http://docs.python.org/2/library/dis.html

于 2013-03-30T22:54:26.837 に答える