大規模なプログラムを作成する場合、オブジェクト指向プログラミング言語はプロセス指向言語よりも便利で安全に使用できることがよくあります。理由の 1 つは、クラスの仕組みです。
クラスは多数のデータを分類してカプセル化し、データ オブジェクトを完全な個別、現実に近い、高度に抽象的なものにします。ただし、Python のクラスのカプセル化は適切ではありません。すべての属性とメソッドがパブリックであり、クラスの外部でクラスの属性を変更したり、属性を追加したりすることができます。これは確かに不安です。
学習後の解決策をまとめてみましょう。
1. プロパティまたはメソッドを非表示にするには、2 つのアンダースコア接頭辞を使用します。
__xxx #!/usr/bin/python3 #-*- coding:utf-8 -*- class Student: def __init__(self,name,score): self.name = name self.__score = score #将score隐藏起来,使之仅在类内部可用。 def __show(self): #一个隐藏的方法,同样只在内部可用 print(self.name,self.__score)#使用被隐藏的属性__score def Show(self): self.__show() #注意被隐藏方法的调用方式。 def main(): he = Student('Bob',95) he.Show() #显示:Bob 95 #print(he.__score) #AttributeError: 'Student' object has no attribute '__score' #he.__show() #AttributeError: 'Student' object has no attribute '__show' #隐藏属性真的被隐藏了吗?其实仍然可使用,使用格式 obj._className__attributeName #但是仅仅作为了解,不建议使用隐藏属性。 print(he._Student__show()) #显示:Bob 95 print(he._Student__score) # 显示: 95 if __name__=="__main__": main()
クラス属性に対する二重アンダースコアの影響:
1. 属性をこのクラス内でのみ使用し、外部クラスやサブクラスによって直接読み取ったり変更したりすることはできません。
2. _ _ を使用するクラスの属性は、実装中に名前が変更されます。たとえば、クラス内の __age は、最終的に _A__age になります (名前の再編成)。通常、クラス内で使用される親に使用されます。これにより、サブクラスのプロパティによってオーバーライドされることが回避されます。
2. 管理可能な属性を作成します。
場合によっては、属性の書き込みに関して追加のチェックを行ったり、不正な値の書き込みを拒否したり、例外をスローしたりする必要があります。
#!/usr/bin/python3 #-*- coding:utf-8 -*- class Student: def __init__(self,name,score): self.name = name self.score = score @property #实现属性的读取方法,读取实例的score值时,就会调用这个函数 def score(self): return self.__score @score.setter #实现属性写入方法,写入实例的score属性时,调用这个函数 def score(self,newVal): if not isinstance(newVal,(int,float)): raise TypeError('score value must be a number') if newVal>100 or newVal<0: raise ValueError('score value must between 0 and 100') self.__score = newVal def main(): he = Student('Bob',95) he.score = 100 #重新写入 print(he.score) #读取 if __name__=="__main__": main()
次のことがわかります: self.__score は属性値が実際に格納される場所であり、self.score は属性値メソッドを取得して書き込む関数 (ただし属性のように使用されます) です。
self.score への呼び出しが __init__() 関数の下にあるため、socre.setter 装飾関数も初期化中に呼び出されます
self.__score は属性の値を参照するためにのみ使用されるため、名前を付けることができます別の名前で? saveScore など...もちろん可能ですが、「公開」されているため、外部から利用できるようにする必要はありません。誤って変更されないように、__ を追加して非表示にする必要があります。
場合によっては、特定のクラスが継承を含まないことが確実な場合は、上記の二重アンダースコアを単一のアンダースコアに書き換えることができますが、隠れた効果は得られませんが、一方では名前の重複は発生しません。一方、
のメカニズム全体では、大騒ぎを避けることができます。アンダースコアで始めると、この属性を直接使用すべきではないことをユーザーに思い出させることができます。あとは自己認識次第です。
インスタンス オブジェクトは、外部から自由に属性を追加できます。#!/usr/bin/python3 #-*- coding:utf-8 -*- class Student: def __init__(self,name,score): self.name = name self.score = score def main(): he = Student('Bob',95) he.age = 19 print(he.age) if __name__=="__main__": main() 使用__slots__ #!/usr/bin/python3 #-*- coding:utf-8 -*- class Student: __slots__ = ('name','score') #将属性名以字符串形式加入元组 def __init__(self,name,score): self.name = name self.score = score def main(): he = Student('Bob',95) he.age = 19 #AttributeError: 'Student' object has no attribute 'age' print(he.age) if __name__=="__main__": main()
このようにして、オブジェクトのプロパティはクラスの内部に限定されます。
ただし、__slots__ は継承できません。さらに、__slots__ の本来の設計意図は上記の使用法ではなく、多数 (数万個) のオブジェクトを作成する際のメモリ使用量を最適化することです。
要約: これを書いていると、上記のテクニックはあまり重要ではないことがわかりました。クラスの設計者はプログラマ自身であり、ユーザーも自身であるため、クラス設計自体はあまり多くの保護コードを必要とせず、肥大化してしまいます。効率が低下します。クラス オブジェクトが受信するデータが常に正当であるように、保護手段はクラスの外側で行われるべきであり、これにより軽量かつ柔軟になります。これが私の感じ方です。
Python オブジェクト データの読み取りおよび書き込み権限について簡単に説明した上記の記事は、エディターによって共有されたすべての内容です。参考にしていただければ幸いです。また、PHP 中国語 Web サイトにもさらに注目していただければ幸いです。
Python オブジェクト データの読み取りおよび書き込み権限に関するその他の記事については、PHP 中国語 Web サイトに注目してください。