8

いくつかの属性を持つクラスがあります。以下のa、b、cとx、y、zのような属性の設定の違いを誰かが明確にしてください。ただし、引数を入力する場合は、明らかにinitに含める必要があることを理解しています。ただし、デフォルトの変数をいくつか設定するためだけに使用することをお勧めします。これは、長所と短所が何であるかを示しています。

class Foo(object):
    a = 'Hello'
    b = 1
    c = False
    def __init__(self):
        self.x = 'World'
        self.y = 2
        self.z = True
4

4 に答える 4

8

変数ab、およびcはクラス変数です。それらは、クラスが最初に作成されたときに一度だけ評価され、設定されます。変数xy、およびzはインスタンス変数であり、そのクラスのオブジェクトがインスタンス化されるたびに評価および設定されます。

一般に、クラスのすべてのインスタンスで同じ値が使用され、一度だけ計算する必要がある場合は、クラス変数を使用します。そのクラスのインスタンスごとに異なる変数には、インスタンス変数を使用します。

インスタンス変数構文を使用してクラス変数にアクセスできますself.aが、問題のオブジェクトはクラスのすべてのインスタンス間で共有されています。整数や文字列などの不変データ型を使用する場合、これはあまり影響しませんが、リストなどの可変データ型を使用する場合、追加するself.aと、すべてのインスタンスが新しく追加された値を認識します。

IDLE のいくつかの例は、これを理解するのに役立つでしょう。

>>> class Foo(object):
    a = 'Hello'
    b = []
    def __init__(self):
        self.y = []

>>> instance_1 = Foo()
>>> instance_2 = Foo()
>>> instance_1.a
'Hello'
>>> instance_2.a
'Hello'
>>> instance_1.a = 'Goodbye'
>>> instance_1.a
'Goodbye'
>>> instance_2.a
'Hello'
>>> instance_1.b
[]
>>> instance_2.b.append('12345')
>>> instance_1.b
['12345']
>>> instance_2.y
[]
>>> instance_2.y.append('abcde')
>>> instance_2.y
['abcde']
>>> instance_1.y
[]
于 2012-09-13T00:15:48.883 に答える
6

クラス属性を使用してインスタンス固有のデータにする予定のデフォルト値を提供する主な問題は、値が変更されるまでデフォルト値がクラスのすべてのインスタンス間で共有されることです。例えば:

class Foo(object):
    a = []

foo1 = Foo()
foo2 = Foo()

foo1.a.append(123)

foo1.a # [123]
foo2.a # [123]

ただし、以下は期待どおりに機能します。

class Bar(object):
    a = 123    

bar1 = Bar()
bar2 = Bar()

bar1.a = 456

bar2.a # 123

この手法を使用しているときにこの問題を回避するには、不変値であるデフォルトを設定するためにのみ使用する必要があります。(例: 数値、文字列、タプル…)

Python がこのように動作する理由は、次のように属性にアクセスする場合です。

foo.bar

thenbarが最初にオブジェクト内で検索されますfoo。名前がオブジェクト (つまり ) で見つからない場合、名前はfoo.__dict__そのオブジェクトの型で検索されます。たとえば、このメカニズムはメソッド検索の仕組みの一部です。(オブジェクトの を見ると、__dict__そのメソッドが存在しないことがわかります。)

その他のマイナーな問題は、インスタンス固有であることを意図している場合に、型オブジェクトを介してデフォルトを公開することです。また、クラス固有の属性 (定数など) の定義がデフォルトと混在している場合。前者の当然の帰結は、class 属性に代入することによって、まだ値を変更していないすべてのオブジェクトに対して、後でデフォルトの値を再定義できるようにすることです。(これは便利な場合もあれば、混乱を招く場合もあります。変更可能な「グローバル」変数に対する同じ予防措置が適用されます。)

于 2012-09-13T00:43:18.117 に答える
2

宣言したとおり、a、b、および c は、Foo のインスタンスを作成せずに使用できます。
たとえば、次のように言えます。

Foo.a = "Goodbye"

対照的に、x、y、および z は、Foo のインスタンスを作成するまで作成されず、そのインスタンスに固有です。

bar = Foo()
bar.x = 42
于 2012-09-13T00:19:00.463 に答える
1

これは数え切れないほど尋ねられています...

a,b,cすべてのインスタンス間で共有されるクラス変数です。作成されたこのクラスのすべてのオカレンスをカウントするためのカウンターが適切な使用法です。x,y,zその単一のインスタンスに属するインスタンス変数であるため、selfそれらを設定するために使用されます...

self.a = 3このようにクラス変数を実際にシャドウすることができることに注意してくださいa

デモ:

>>> class Foo(object):
...     a = 3
...     def __init__(self):
...         self.x = 6
... 
>>> Foo.a
3
>>> b = Foo()
>>> b.a = 5
>>> b.a
5
>>> Foo.a
3
>>> b.a
5
>>> Foo.a = 9
>>> Foo.a
9
>>> b.a
5
>>> c = Foo()
>>> c.a
9
于 2012-09-13T00:39:25.197 に答える