[TOC]
Aの導入
オブジェクト指向プログラミングは、3つの特性を有している、最も重要な特徴は、パッケージカプセル化、継承、多態性です。パッケージは、データを参照し、機能が一体化され、非常に身近な音ではありません、はい、私たちは「統合」の前に言葉が実際に人気の引数のパッケージであると述べました。隠された、オープンインタフェース:また、オブジェクトまたはクラス属性へのパッケージのために、我々は、厳密に2つの段階で実現、それらへのアクセスを制御することができます
イラスト:パロディー16
2つの隠し属性
Pythonは隠された属性が(プライベート配置された)道の初めに採用し、二重下線のクラスのメカニズムですが、すべてのプロパティのクラスの始まりは二重線は、クラス定義の位相検出自動文法に落ちているとき、実際にはこれは、操作の単なる変形であります「_ __クラス名属性名」の形式次のようになります。
class Foo:
__N=0 # 变形为_Foo__N
def __init__(self): # 定义函数时,会检测函数语法,所以__开头的属性也会变形
self.__x=10 # 变形为self._Foo__x
def __f1(self): # 变形为_Foo__f1
print('__f1 run')
def f2(self): # 定义函数时,会检测函数语法,所以__开头的属性也会变形
self.__f1() #变形为self._Foo__f1()
print(Foo.__N) # 报错AttributeError:类Foo没有属性__N
obj = Foo()
print(obbj.__x) # 报错AttributeError:对象obj没有属性__x
イラスト:パロディー17
この変形の問題は、必要性の注意があること:
1、クラス外のプロパティに直接二重線の下落の始まりをアクセスしますが、あなたが名前を綴ることができ、クラスや属性の名前を知ることができません:クラス名_ _ プロパティを、あなたは、このようなFoo._A \として、訪問することができ _Nので、この動作モードと厳密な意味で地面に制限外部アクセス、文法的意味のわずかな変形は存在しません。
>>> Foo.__dict__
mappingproxy({..., '_Foo__N': 0, ...})
>>> obj.__dict__
{'_Foo__x': 10}
>>> Foo._Foo__N
0
>>> obj._Foo__x
10
>>> obj._Foo__N
0
図2は、クラス属性内で直接このような二重型の内部相線特性低下の開始時にクラス定義に均一変形ので自己.__ F1()、のような減少し始めるアクセス二重線です。
>>> obj.f2()
__f1 run
図3に示すように、変更後のクラス割り当ての定義は、クラス定義の段階でのみ発生したら、それを変形することはないであろう。
>>> Foo.__M=100
>>> Foo.__dict__
mappingproxy({..., '__M': 100,...})
>>> Foo.__M
100
>>> obj.__y=20
>>> obj.__dict__
{'__y': 20, '_Foo__x': 10}
>>> obj.__y
20
イラスト:パロディー18
3つのオープンインタフェース
カスタムプロパティを使用することで、それは隠蔽目的ではありません
3.1隠し属性データ
隠されたデータクラスは、インターフェイスクラスが間接外部操作データを許容提供する必要があり、インターフェースは厳密にデータの操作を制御するための追加ロジックに取り付けることができ、データに直接外部からの操作を制限します
>>> class Teacher:
... def __init__(self,name,age): #将名字和年纪都隐藏起来
... self.__name=name
... self.__age=age
... def tell_info(self): #对外提供访问老师信息的接口
... print('姓名:%s,年龄:%s' %(self.__name,self.__age))
... def set_info(self,name,age): #对外提供设置老师信息的接口,并附加类型检查的逻辑
... if not isinstance(name,str):
... raise TypeError('姓名必须是字符串类型')
... if not isinstance(age,int):
... raise TypeError('年龄必须是整型')
... self.__name=name
... self.__age=age
...
>>>
>>> t=Teacher('lili',18)
>>> t.set_info(‘LiLi','19') # 年龄不为整型,抛出异常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 11, in set_info
TypeError: 年龄必须是整型
>>> t.set_info('LiLi',19) # 名字为字符串类型,年龄为整形,可以正常设置
>>> t.tell_info() # 查看老师的信息
姓名:LiLi,年龄:19
イラスト:パロディー19
3.2隠しプロパティ関数
目的は、このようななどのカード、認証、金額を入力し、小さなチケット印刷、引き出し、その他の多くの機能コンポーネントを備えていますATMの引き出し機能プログラムとして分離株の複雑さ、に、だけが必要なユーザーのためにあります引き出しは、この関数インタフェースを開発することができ、我々はすべての機能が隠されて休むことができます
>>> class ATM:
... def __card(self): #插卡
... print('插卡')
... def __auth(self): #身份认证
... print('用户认证')
... def __input(self): #输入金额
... print('输入取款金额')
... def __print_bill(self): #打印小票
... print('打印账单')
... def __take_money(self): #取钱
... print('取款')
... def withdraw(self): #取款功能
... self.__card()
... self.__auth()
... self.__input()
... self.__print_bill()
... self.__take_money()
...
>>> obj=ATM()
>>> obj.withdraw()
イラスト:パロディー20
、およびクラス外でちょうどインターフェイスを取得するために、長いインターフェース名などとして、パラメータ変更せず、隠された属性とオープンインタフェースをまとめたもので、本質は明らかに内部と外部を区別することで、クラス内のコードの外部の発信者に影響を与えることなく、パッケージの中で何かを変更することができます設計者が内部実装コードを変更する方法に関係なく、ユーザーがコードを変更する必要がありません。長く同じ基本合意へのインタフェースとして、懸念のコード原因を修正するように、これは、協力のための良好な基礎を提供します。
四プロパティ
BMI指数は、人の体重と身長と健康への影響を測定するために使用される指標であるように計算されます
体质指数(BMI)=体重(kg)÷身高^2(m)
EX:70kg÷(1.75×1.75)=22.86
することができます、あなたはBMI値を表示するたびに前に計算する必要があるが、明らかにBMIが財産に特化したPythonのデコレータのために、より多くの機能のようではなく、機能よりも聞こえるように、身長や体重は絶えず変化しており、この訪問の結果として「変装」オブジェクトのdataプロパティ、オブジェクトのプロパティ、特定のトリガ実行機能へのアクセス、および戻り値のクラス、例えば中
>>> class People:
... def __init__(self,name,weight,height):
... self.name=name
... self.weight=weight
... self.height=height
... @property
... def bmi(self):
... return self.weight / (self.height**2)
...
>>> obj=People('lili',75,1.85)
>>> obj.bmi #触发方法bmi的执行,将obj自动传给self,执行后返回值作为本次引用的结果
21.913805697589478
イラスト:パロディー21
プロパティアクセスの一貫性を確保する効果的プロパティを使用します。次のようにさらにプロパティでも、設定機能と削除特性を提供します
>>> class Foo:
... def __init__(self,val):
... self.__NAME=val #将属性隐藏起来
... @property
... def name(self):
... return self.__NAME
... @name.setter
... def name(self,value):
... if not isinstance(value,str): #在设定值之前进行类型检查
... raise TypeError('%s must be str' %value)
... self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME
... @name.deleter
... def name(self):
... raise PermissionError('Can not delete')
...
>>> f=Foo('lili')
>>> f.name
lili
>>> f.name='LiLi' #触发name.setter装饰器对应的函数name(f,’Egon')
>>> f.name=123 #触发name.setter对应的的函数name(f,123),抛出异常TypeError
>>> del f.name #触发name.deleter对应的函数name(f),抛出异常PermissionError