2
class Ball:
  a = []
  def __init__(self):
    pass

  def add(self,thing):
    self.a.append(thing)

  def size(self):
    print len(self.a)

for i in range(3):
  foo = Ball()
  foo.add(1)
  foo.add(2)
  foo.size()

私は次のリターンを期待します:

2
2
2

しかし、私は得る:

2
4
6

どうしてこれなの?initでa=[] を実行することで、この動作を回避できることがわかりましたが、その理由はよくわかりません。

4

3 に答える 3

4

理由がわかりました。

上記の場合、a はデータ属性ではなくクラス属性です。これらはすべての Balls() で共有されます。a=[] をコメントアウトしてinitブロックに配置すると、代わりにデータ属性になります。(そして、その時は foo.a でアクセスできませんでした。これは絶対にやるべきではありません。) クラス属性はクラスの静的属性のように振る舞い、すべてのインスタンスで共有されているようです。

うわあ。

ただし、1 つの質問: CodeCompletion はこのように最悪です。foo クラスでは、self.(変数) を実行できません。これは、自動的に定義されていないためです。関数によって定義されています。クラス変数を定義して、それをデータ変数に置き換えることはできますか?

于 2008-11-21T03:27:46.577 に答える
2

おそらくやりたいことは次のとおりです。

class Ball:
  def __init__(self):
    self.a = []

just を使用すると、関数a = []内にローカル変数が作成され、__init__関数が戻ると消えます。に代入するself.aと、それがインスタンス変数になり、それがあなたが求めているものになります。

半関連の落とし穴については、将来の呼び出し元のデフォルト パラメーターの値を変更する方法を参照してください。

于 2008-11-21T03:47:25.070 に答える
1

「クラス変数を定義して、それをデータ変数に置き換えることはできますか?」

いいえ、それらは別のものです。クラス変数は、クラス内に一度だけ存在します。

コードを完成させるために、いくつかのクラス変数から始めて、クラスを記述した後でそれらのコード行を削除することができます。しかし、それを忘れるたびに、良いことは何も起こりません。

別の IDE を試すことをお勧めします。 Komodo Editのコード補完は賢明なようです。

コード補完が実際に役立つような長い名前の変数が非常に多い場合は、クラスを小さくするか、短い名前を使用する必要があります。真剣に。

コード補完が煩わしいものよりも役立つ場所にたどり着くと、「すべてを頭に入れておく」複雑さのしきい値を超えていることがわかります。クラスが私の頭の中に収まらない場合、それは複雑すぎます。

于 2008-11-21T11:20:14.313 に答える