することの違いは何ですか
class a:
def __init__(self):
self.val=1
することへ
class a:
val=1
def __init__(self):
pass
class a:
def __init__(self):
self.val=1
これにより、クラスが作成されます(Py2では、雑然とした、レガシー、古いスタイル、それを行わないでください!クラス。Py3では、厄介な古いレガシークラスが最終的になくなったため、これは唯一の種類のクラスになります- -** good *の種類。これはclass a(object):
、各インスタンスが整数オブジェクトへの独自の参照で開始するようにPy2)で必要1
です。
class a:
val=1
def __init__(self):
pass
これにより、それ自体が整数オブジェクトへの参照を持つ(同じ種類の)クラスが作成されます1
(そのインスタンスはインスタンスごとの参照なしで開始されます)。
値のような不変のint
場合、実際的な違いを確認するのは困難です。たとえば、どちらの場合でも、後でself.val = 2
の1つのインスタンスで実行a
すると、インスタンス参照が作成されます(この点で既存の回答はひどく間違っています)。
ミューテイタメソッドがあるため、ミュータブルオブジェクトの区別は重要です。したがって、特定のリストがインスタンスごとに一意であるか、すべてのインスタンス間で共有されているかを知ることは非常に重要です。ただし、不変オブジェクトの場合、オブジェクト自体を変更することはできず、割り当てることしかできないため(たとえばself.val
、インスタンスごとの参照を常に作成するに)、かなりマイナーです。
不変に関連する唯一の違い:後で割り当てるa.val = 3
場合、最初のケースでは、これは各インスタンスによって表示されるものに影響しself.val
ます(独自self.val
に割り当てられたインスタンス、または同等のアクションを除く)。2番目のケースでは、インスタンスによって表示される内容には影響しませんself.val
(実行したインスタンスdel self.val
または同等のアクションを除く)。
他の人は技術的な違いを説明しました。クラス変数を使用する理由を説明しようと思います。
クラスを一度だけインスタンス化する場合、クラス変数は事実上インスタンス変数です。ただし、多数のコピーを作成する場合、またはいくつかのインスタンス間で状態を共有する場合は、クラス変数が非常に便利です。例えば:
class Foo(object):
def __init__(self):
self.bar = expensivefunction()
myobjs = [Foo() for _ in range(1000000)]
高価なfunction()が100万回呼び出されます。データベースから構成パラメーターをフェッチするなど、毎回同じ値を返す場合は、クラス定義に移動して、一度だけ呼び出され、すべてのインスタンスで共有されるようにすることを検討する必要があります。
また、結果をメモ化するときにクラス変数をよく使用します。例:
class Foo(object):
bazcache = {}
@classmethod
def baz(cls, key):
try:
result = cls.bazcache[key]
except KeyError:
result = expensivefunction(key)
cls.bazcache[key] = result
return result
この場合、bazはクラスメソッドです。その結果は、インスタンス変数に依存しません。つまり、結果キャッシュの1つのコピーをクラス変数に保持できるため、1)同じ結果を複数回保存する必要がなく、2)各インスタンスが他のインスタンスからキャッシュされた結果の恩恵を受けることができます。
説明のために、100万のインスタンスがあり、それぞれがGoogle検索の結果を操作していると仮定します。それぞれが検索を実行して回答を待つよりも、これらすべてのオブジェクトがこれらの結果を共有する方がはるかに望ましいでしょう。
だから私はここでレナートに同意しません。クラス変数は、特定の場合に非常に便利です。それらが仕事に適したツールである場合は、それらを使用することを躊躇しないでください。
他の人が述べたように、ある場合にはそれはクラスの属性であり、他の場合にはインスタンスの属性です。これは重要ですか?はい、ある場合にはそうなります。Alexが言ったように、値が変更可能である場合。最良の説明はコードなので、それを示すためにいくつかのコードを追加します(これがこの答えのすべてです):
まず、2つのインスタンス属性を定義するクラス。
>>> class A(object):
... def __init__(self):
... self.number = 45
... self.letters = ['a', 'b', 'c']
...
次に、2つのクラス属性を定義するクラス。
>>> class B(object):
... number = 45
... letters = ['a', 'b', 'c']
...
今、私たちはそれらを使用します:
>>> a1 = A()
>>> a2 = A()
>>> a2.number = 15
>>> a2.letters.append('z')
そして、すべてが順調です:
>>> a1.number
45
>>> a1.letters
['a', 'b', 'c']
次に、クラス属性のバリエーションを使用します。
>>> b1 = B()
>>> b2 = B()
>>> b2.number = 15
>>> b2.letters.append('z')
そして、すべては...まあ...
>>> b1.number
45
>>> b1.letters
['a', 'b', 'c', 'z']
ええ、変更すると、すべてのクラスの可変クラス属性が変更されたことに注意してください。それは通常あなたが望むものではありません。
ZODBを使用している場合は、既存のオブジェクトを新しい属性でアップグレードしたり、永続化されないクラスレベルで情報を追加したりするのに便利な方法であるため、多くのクラス属性を使用します。そうでなければ、あなたはそれらをほとんど無視することができます。