1

私が達成したいこと:
1.作成されたオブジェクトの数のカウントを保持するクラス変数を持っています
2.その変数はオブジェクト/その他、つまりクラスに対してプライベートに使用できないはずです
3.初期化中に特定のIDが提供されない場合は、このカウンターを使用しますobject.ID を割り当てる変数
私は次の python コードを持っています

class UserClass(object) :
    __user_id_counter = 0
    def __init__(self, UserID=__user_id_counter) :
        self.UserID = UserID
        __user_id_counter += 1

myuser = UserClass()

しかし、私は UnboundLocalError: local variable '_UserClass__user_id_counter' referenced before assignment
Pythonが初めてなので、ここで親切に助けてくれます:)

4

3 に答える 3

4

__user_id_counterオブジェクトまたはクラス参照にアクセスするには必要です。引数リスト内selforUserClassにアクセスできないため、次のようになります。

class UserClass(object) :
    __user_id_counter = 0
    def __init__(self, UserID=None) :
        self.UserID = self.__user_id_counter if UserID is None else UserID
        UserClass.__user_id_counter += 1
于 2011-07-27T08:17:14.887 に答える
1

あなたは書く必要がありますself.__user_id_counter。インスタンス変数が見つからない場合、クラス変数も検索します。

編集:self Sudhi は、引数リストでは、宣言が無効であることを指摘しました。この問題を回避するには、次のことを試してください。

class UserClass(object) :
    __user_id_counter = 0
    def __init__(self, UserID=None) :
        if UserID is None:
            self.UserID = self.__user_id_counter
            self.__class__.__user_id_counter += 1
        else:
            self.UserID = UserID

myuser = UserClass()
于 2011-07-27T08:13:30.970 に答える
1

まず、名前UserClassUser(クラスであることはわかっています) および(クラス内にあるUserIDため、「ユーザー」ビットを繰り返す必要はありません。Python スタイルでは小文字をお勧めします) および(同上) に変更します。Python スタイルのガイドラインについては、PEP 8を参照してください。idUser__user_id_counter__id_counter

それでは、出発点は次のとおりです。

class User(object):
    __id_counter = 0
    def __init__(self, id=None) :
        self.id = self.__id_counter if id is None else id
        __id_counter += 1
myuser = User()
myuser2 = User()
myuser3 = User()

__init__現在、二重の先頭のアンダースコア ( andのような二重の末尾のアンダースコアなし__metaclass__) は特別であり、クラス プライベート変数の実装に使用されます。詳細については、Python マニュアルのプライベート変数を参照してください。これは、いわゆる「ネーム マングリング」を引き起こします。クラス全体__id_counterで名前が変更されたままになります。_User__id_counterこれは便利でもあり、危険でもあります。この場合、おそらく必要ないと思います。

これにより、サブクラスで問題が発生する可能性があります。

class SpecialUser(User):
    def __init__(self):
        self.__id_counter

これで、SpecialUser()がトリガーされAttributeError: 'SpecialUser' object has no attribute '_SpecialUser__id_counter'ます。

そこで問題は、サブクラスに同じID カウンターを持たせたいのか、それとも独自のID カウンターを持たせたいのかということです。

  • それらに同じID カウンターを持たせたい場合は、 を使用しますUser.__id_counter。またはと一緒に使用しないでください。これは、インスタンスに対して に設定され、この時点から独自のものを使用するため、必要なものとはかけ離れています。self.__class__.__id_countertype(self).__id_counter+= 1SpecialUserSpecialUser._User__id_counterUser._User__id_counter + 1SpecialUser _User__id_counter

  • それらに独自のID カウンターを持たせたい場合は、_id_counterではなくを使用することから始め__id_counterてください。

    いくつかの方法があります。

    • メタクラスを使用して、各クラスに独自のカウンター変数を与えます (現時点で書くのが面倒なトピックよりも高度なトピックです。必要に応じて詳細を尋ねてください)。

    • _id_counter = 0各クラス定義に一行入れます。(そうしないと、ID の開始点で問題が発生します。たとえば をたくさん作成すると、.ではなくUser(), User(), SpecialUser(), User(), SpecialUser(), SpecialUser(), User()(それぞれ) の ID を持つことになります。0, 1, 2, 2, 3, 4, 30, 1, 0, 2, 1, 2

    ここで名前マングリング アプローチを使用することで生じる追加の非効率性は、サブクラスに複数のカウンター_User__id_counter( 、_SpecialUser__id_counterなど) が含まれることです。

于 2011-07-27T16:38:15.830 に答える