面向對象的三大特性: ①繼承 ②封裝 ③多態java
簡述面向對象的三大特性分別是什麼,以及主要功能
# 封裝、繼承、多態。
# 封裝:隱藏對象的屬性和實現細節,僅對外提供公共訪問方式;
# 繼承:子類自動共享父類數據結構和方法的機制。單繼承、多繼承;
# 多態:多態是指相同的操做或函數、過程可做用於多種類型的對象上,並得到不一樣的結果。
# 不一樣的對象,收到同一消息能夠產生不一樣的結果,這種現象稱爲多態性;
繼承:python
新式類: 繼承object類的類就是新式類.(python3x中都是新式類)c#
經典類:不繼承object類就是經典類.設計模式
python2x:默認全部類都不繼承(object),這樣就是新式類微信
繼承又分爲單繼承和多繼承.數據結構
單繼承:函數
①查詢順序微信支付
class A:spa
name = 'alex'設計
def func(self)
print(666)
class B(A):
age = 12
b1 = B()
b1.age
b1.name
②既要執行父類的又執行子類的方法
class A:
name = 'alex'
def func(self):
print('IN A')
class B(A):
age = 12
def func(self):
#super().func() #第一種 super(B,self).func()
A,func(self) #第二種
print('IN B')
b1 = B()
b1.func()
# class A: # name = 'alex' # def func(self): # #self = self = b1 # print(self) # 1,a1地址 5 b1 地址 (分歧:a1 地址) 1,<__main__.A object at 0x0000000000711198> 5, <__main__.B object at 0x00000000007111D0> # print('IN A') # 2 IN A 6 IN A 2 IN A # # class B(A): # age = 12 # def func(self): # #self = b1 # super().func() # 第一種 super(B,self).func() # print(self) # 4,b1 地址 4 <__main__.B object at 0x00000000007111D0> # # A.func(self) # 第二種 # print('IN B') # 7 IN B # a1 = A() # a1.func() # print(a1) # 3 a1地址 <__main__.A object at 0x0000000000711198> # b1 = B() # b1.func() # print(b1) # b1 地址
多繼承:
多繼承分爲 新式類和經典類
新式類:廣度優先. python3x 類名.mro()
經典類:一直找,找到底
接口類,抽象類:
是在工做中書寫的一種規範
強制制定規範,若是未按照規範執行,就會報錯
from abc import ABCMeta,abstractmethod ##引入來自abc文件的 ABCmeta ,abstractmethod 兩個模塊
class Payment(metaclass=ABCMeta): # 抽象類 接口類 規範和約束 metaclass指定的是一個元類
@abstractmethod
def pay(self):pass # 抽象方法
class QQ(Payment):
def pay(self,money):
print('您用qq支付了%s元' % money)
def ret(self):
print('支付失敗....')
class Ali(Payment):
def pay(self,money):
print('您用支付寶支付了%s元' % money)
class Wechat(Payment):
def pay(self,money):
print('您用微信支付了%s元' % money)
def pay(obj,money):
obj.pay(money) # a1.pay(200)
q1 = QQ()
a1 = Ali()
w1 = Wechat()
# q1 = QQ()
# a1 = Ali()
# pay(q1,100) # 統一化設計
# pay(a1,200)
# w1 = Wechat()
# pay(w1,500)
用處:在工做中,若是你要是規定幾個類必須有同樣的方法,
你要抽象類,制定一個規範,強制其有此方法
python沒有多態的概念,可是python崇尚鴨子類型.
定義變量的方法:
1.java c# 須要定義 類型.
2.java c# 沒有多繼承的概念
鴨子類型:它看着像鴨子,那麼它就是鴨子.↓
好比: str list tuple
str.index()
s1 = 'alex'
class Str:
def index(self):
pass
class List:
def index(self):
pass
class Tuple:
def index(self):
pass
python 中好多不一樣類但同名的方法不是強制規定,而是約定俗成,像上面這三種類,都一樣具備index方法,並且功能
類似,則,他們三個互爲鴨子.
封裝就是將一些屬性或者方法(有用的信息)放置在一個空間中.
1,封裝 對象的封裝
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
p1 = Person('oldboy',1000)
p2 = Person('alex',10000)
print(p1.name)
print(p2.name)
2.封裝(私有成員)
類的結構分析:
class Person:
mind = '有思想' ##第一部分:全部的共有靜態變量,公有靜態字段
__level = '高等動物' ##第一部分: (前面兩個下劃線) 私有靜態變量,私有靜態字段
def __init__(self,name,age,sex): ##構造方法 #第二部分: 動態方法,方法(函數)
self.name = name ##公有對象屬性
self.age = age
self.__sex = sex ##私有對象屬性
def func(self): ##第二部分:普通方法
print(666)
def __func1(self): ##第二部分:私有方法
print(777)
@staticmethod #靜態方法
def f2():pass
@classmethod #類方法
def f2():pass
@property #屬性
def hex(self):pass
總結:對於私有成員來講,他加載到內存時,都會加上_類名__變量名,因此你在類的外部,或者派生類中都不可訪問.
爲何設置私有成員?
有些變量,方法,屬性,只在類內部進行使用便可,不便於(不容許)類外部或者派生類去調用
isinstance(obj1,A) ##判斷obj1是否是A實例化出來的, 判斷這個對象是本類實例化的,或者是此類的子類實例化出來的
issubclass(B,A) ## 判斷B是否是A的子類, 判斷一個類是否是另外一個類的派生類
# *** item
# class Foo:
# def __init__(self, name, age, sex):
# self.name = name
# self.age = age
# self.sex = sex
# def __getitem__(self, item):
# # print(self.__dict__[item])
# # if hasattr(self,item):
# # return getattr(self,item)
# # else:
# # return '沒有此屬性'
# return getattr(self, item, '沒有此屬性')
# #
# def __setitem__(self, key, value):
# print(key,value)
#
# #
# def __delitem__(self, key):
# print(key)
# def __delattr__(self, item):
# print(item)
# print('del obj.key時,我執行')
#
#
#
# f1 = Foo('alex', 12, '男')
# print(f1['name']) # 對一個對象使用f1['name1']這種方法,自動觸發__getitem__這個方法,將'oldboy123' 傳到這個方法中.
# print(f1['age1'])
# f1['name1'] = 'wusir666' #對一個對象使用這種方法,自動觸發 __setitem__
# del f1['fkjdslfjdslafj'] ##這個自動觸發 __delitem__
# 若是你對對象進行類似的字典的操做,就會主動觸發類中__getitem__ __setitem__ delitem__
# del f1.name
# del f1.aaaaaa
特殊方法::
__len__
class A:
def __init__(self,name,age):
self.name = name
self.age = age
def __len__(self):
return len(self.__dict__)
a1 = A('oldboy',1000)
print(len(a1))
# 若是對一個對象進行len()操做,
# 他會找到對象從屬於的類中的__len__方法,而且此方法中必需要有數字的返回值.
__call__
對象後面加括號,觸發執行.
注:構造方法的執行是由建立對象觸發的,即:對象 = 類名();而對於__call__方法的執行是由對象後加括號()觸發的,即:對象()或者 類()
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 執行 __init__
obj() # 執行 __call__
__eq__
對一個類實例化的兩個對象進行比較運算時,他會自動觸發
# class A:
# def __init__(self):
# self.a = 1
# self.b = 2
#
# def __eq__(self,obj):
# if self.a == obj.a and self.b == obj.b:
# return True
# a1 = A()
# b1 = A()
# print(a1 == b1) # 對一個類實例化的兩個對象進行比較運算的時候,他會自動觸發類中的__eq__
__del__ 析構方法
在看析構以前 須要知道 python垃圾回收機制
python垃圾回收機制:文件中你建立的全部的變量,類等等,執行完畢以後,一段時間內若是沒有用到,他會自動在內存中去除,
深刻研究:他會將你的全部變量,類等等作個標記,在一段時間以內,沒有被調用,則就會自動回收.
析構方法:
class A:
def __init__(self):
pass
def __del__(self):
print(666)
al = A() ###這就觸發了, 日了.
__new__
object 產生並返回一個對象空間.
本身定義的 __new__ 第一個參數自動接收類空間
執行順序::先執行 __new__方法,而後在執行__init__方法
# class A:
# def __init__(self):
# self.x = 1
# print('in init function ')
#
# def __new__(cls, *args, **kwargs):
# print(cls) # <class '__main__.A'>
# print('in new function ')
# # return object.__new__(cls) # 調用object類中的__new__方法,產生一個真正的對象空間
# return super().__new__(cls) # 返回給 A()
# object
# a1 = A()
# print(a1)
# print(a1)
類名() 自動執行類中__new__ 類中沒有,則找到object
找到__new__ 這個方法是產生一個對象空間,自動執行類中的__init__,給這對象空間封裝一些屬性,
最後返回給A() 而後給 變量a1
class A1:
def __new__(cls, *args, **kwargs):
'產生對象空間'
pass
class B(A1):
def __init__(self):
self.x = 1
def __new__(cls, *args, **kwargs):
print('B1')
b1 = B()
print(b1)
1,類名() 執行 __new__方法,先從本身的類中尋找,
若是沒有找到,則從父類(直到object類)尋找,而後從object的__new__產生一個對象空間,返回給類名().
2,對象空間一旦產生並返回.則自動執行__init__方法,給這個對象空間封裝屬性.
3,最終你獲得是封裝好屬性的對象空間.
設計模式 :單例模式,最簡單的設計模式, (面常)
單例模式 :對一個類是能實例化一個對象
class A:
__instance = None
def __new__(cls, *args, **kwargs):
if A.__instance is None: # 第一次進入,知足這個條件
obj = object.__new__(cls) # 利用object 建立一個對象空間 給了obj
A.__instance = obj # 我將類的私有靜態字段 __instance 從新賦值了 對象空間obj
return A.__instance
a1 = A()
b1 = A()
c1 = A()
print(a1,b1,c1)
獲得結果 對象地址都是同樣的