クラス属性の変容

シリーズ「あなたは警告された」からの短いメモ。



従来のプログラミング言語からPythonに切り替えると、多くの驚きが生じます。

ドキュメントを読む:

一般的に、インスタンス変数は各インスタンスに固有のデータ用であり、クラス変数はクラスのすべてのインスタンスで共有される属性とメソッド用です
遊んでみよう



class Vessel: #class attribute vtype = "boat" #instance attribute def __init__(self, name): self.name = name #    def __str__(self): res= '>>' for a in inspect.getmembers( self): if not a[0].startswith("__"): res += f"{a[0]}={a[1]:<14}" for a in inspect.getmembers( self.__class__): if not a[0].startswith("__"): res += f"__class__.{a[0]}={a[1]:<14}" return res
      
      







2つのオブジェクトを作成し、 すべての属性の値を確認します。



 Iowa = Vessel("Iowa") Drum=Vessel("Drum") printAttr(Iowa, Drum) >>name=Iowa vtype=boat __class__.vtype=boat >>name=Drum vtype=boat __class__.vtype=boat
      
      





これまでのところ、予想どおり。



vtypeを変更してみましょう。これは2つの方法で実行できます。



 Vessel.vtype = "USS boat" printAttr(Iowa, Drum) >>name=Iowa vtype=USS boat __class__.vtype=USS boat >>name=Drum vtype=USS boat __class__.vtype=USS boat Iowa.__class__.vtype = 'USS WW2 Boat' printAttr(Iowa, Drum) >>name=Iowa vtype=USS WW2 Boat __class__.vtype=USS WW2 Boat >>name=Drum vtype=USS WW2 Boat __class__.vtype=USS WW2 Boat
      
      





そして再び、すべてが整然としています。



次に、オブジェクトの属性を使用して同じことを試してみましょう。



 Drum.vtype = 'submarine' printAttr(Iowa, Drum) >>name=Iowa vtype=USS WW2 Boat __class__.vtype=USS WW2 Boat >>name=Drum vtype=submarine __class__.vtype=USS WW2 Boat
      
      





そして、最初の驚きがあります。vtypeはクラスの属性であるにもかかわらず、突然オブジェクトの属性になります。



チェック:



 Vessel.vtype = "NAVY Museum" >>name=Iowa vtype=NAVY Museum __class__.vtype=NAVY Museum >>name=Drum vtype=submarine __class__.vtype=NAVY Museum
      
      





もしも...



  del Drum.vtype >>name=Iowa vtype=NAVY Museum __class__.vtype=NAVY Museum >>name=Drum vtype=NAVY Museum __class__.vtype=NAVY Museum
      
      





また、クラス属性です。



次の式はパスしなくなりました



 del Drum.vtype printAttr(Iowa, Drum) del Drum.vtype AttributeError: vtype
      
      





また、クラスをエミュレートする最後の例は、vtype属性をオーバーライドして削除します。



 Drum.vtype = 'submarine' del Vessel.vtype printAttr(Iowa, Drum) >>name=Iowa >>name=Drum vtype=submarine
      
      





名前空間の処理を開始すると、この動作が理解できるようになります。

ただし、以前は通常の言語を扱っていたプログラマーにとっては、少なくともこれは奇妙に思えます。 そして、数世代の開発者によってサポートされている大規模なプロジェクトについて話すと、これは期限の失敗などになることがあります。



すべてがすべての人に開かれているというPythonの概念を考慮して、__ class__またはその類似物を介してのみ「クールな」属性にアクセスできるようにしてください。 私の意見では、これは少なくとも何らかの形でサプライズから保護し、オブジェクトレベルでクラス属性に何かを割り当てる前に10回考えるようにします。



更新:テキストPrintAttr



 def printAttr(*o): for a in o: print(a)
      
      






All Articles