1. 程式人生 > 其它 >面向物件(2)

面向物件(2)

今日內容總結

  • 動態方法與靜態方法

  • 面向物件的三大特性之一:繼承

  • 屬性查詢

  • 派生類

  • 派生功能前瞻

 

動態方法與靜態方法

# 動態方法
1.繫結給物件的方法
   class Student:
  def run (self):
           print(self)
# 類呼叫繫結給物件的方法:有幾個引數就需要傳幾個引數
Student.run(123)
# 物件呼叫繫結給物件的方法:會自動將物件當作第一個引數傳入
obj1.run()

2.繫結給類的方法
class Student:
       @classmethod
       def eat(cls):
           print(cls)
# 類呼叫繫結給類的方法:會自動將類當作第一個引數傳入
print(Student)  # <class '__main__.Student'>
   Student.eat()  # <class '__main__.Student'>
# 物件呼叫繫結給類的方法:也不需傳參 會講產生該物件的類自動當作第一個引數傳入
obj.eat()  # <class '__main__.Student'>

# 靜態方法
class Student:
       @staticmethod
     def speak(a):
         print(a)
   1.普通的函式:無論誰來呼叫 都必須傳固定的引數個數
   # 類呼叫靜態方法:要自己傳值
   Student.speak(123)
   # 物件呼叫靜態方法:要自己傳值
   obj1.speak(321)

面向物件的三大特性之一:傳承

"""
面向物件的三大性 其中最重要的就是繼承
繼承、封裝、多型
"""
# 繼承的含義
現實生活中繼承是用來描述人與人之間資源的從屬關係
   eg:兒子繼承父親 那麼就可以擁有父親的一切
   面向物件中繼承則是用來描述類與類之間的資料的從屬關係
   eg:類A繼承了類B 那麼類A就可以使用類B中所有的資料(資料、功能...)
# 繼承的目的
面向物件中通過繼承可以減少程式碼冗餘 提升開發效率 同樣也支援多繼承
   eg:類A可以繼承多個類同時擁有多個類裡面的程式碼使用權
# 繼承的基本使用
"""
class A(B):
pass
我們將被繼承的類稱為:父類或者基類 B
繼承別人的類稱為:子類或者派生類 A

"""
   在python中一個類可以同時繼承多個父類
  class A(B,C,D):
           pass

繼承的本質

抽象:右下往上抽取相同特徵
繼承:由上往下直接白嫖資源
"""
在面向物件程式設計中 其實和父類的主要功能都是用來減少程式碼冗餘的

物件:資料與功能的結合體
類:多個相同資料和功能的結合體
父類:多個類相同資料和功能的結合體
"""
class Person:
   def __init__(self,name,age,gender):
       self.name = name
       self.age = age
       self.gender = gender
class Teacher(Person):
   def teach(self):
       print(f'{self.name}老師正在講課')
class Student(Person):
   def study(self):
       print(f'{self.name}學生正在聽課')
stu1 = Student('faker',28,'male')

名字的查詢順序

# 不繼承的情況下
名字的查詢順序是
   先對物件自己的名稱空間中查詢 沒有則去類裡面的名稱空間查詢
  物件 >>>
     '''注意設定值的情況是在自身的名稱空間中新增或者修改資料'''
# 單繼承的情況下
名字的查詢順序是
   先從物件自己的名稱空間中查詢 沒有則取產生物件的類中查詢
   如果還沒有並且類有父類則取父類中查詢 以此往復下去!!!
  物件 >>> >>>父類
   經典案例
  class A:
           def f1(self):
               print('from A.f1')
           def f2(self):
               print('from A.f2')
               self.f1()  '''以後看到self點東西 一定要問自己self是誰'''
           class MyClass(A):
               def f1(self):
                   print('from MyClass.f1')
           obj = MyClass()
           obj.f2()
 

 

 


# 執行的方法分別是A裡面的f2和MyClass裡面的f1
   
   
# 多繼承的情況下
   """
  在python2中存在經典類與新式類
  在python3中只有新式類
  區分的關鍵在於是否繼承了預設的object類
  新式類:直接或者間接繼承的了object或者其子類的類
  經典類:不繼承任何類
  """
   class A:
       pass
   # print A.__bases__ # 空的
   # print(A.__bases__) # (<class 'object'>,)
   """
  有時候我們在定義類的時候會習慣的寫
  class MyClass(object):
  pass
  為了相容python2和python3
  """
強度:研究菱形和非菱形問題object不參與圖形構建
非菱形繼承的情況下
父類中名字的查詢順序就是按照繼承時從做往右依次查詢
   如果多個父類 那麼遵循"深度優先"
  ADBECF
菱形繼承的情況下
父類中名字的查詢順序就是按照繼承時從左往右依次查詢
   如果多個父類還有分類 那麼遵循"廣度優先"
  ADBCFM
 '''名字的查詢順序永遠都是 先從當前物件自身開始查詢'''      

派生類

class Person:
   def __init__(self,name,age,gender):
       self.name = name
       self.age = age
       self.gender = gender

class Teacher(Person):
   def __init__(self,name,age,gender,level,salary):
       # 用了Person類裡面的__init__方法之後
       # super(Teacher,self).__init__(name,age,gender) # 子類呼叫父類的的方法 完整語法
       super().__init__(name,age,gender)  # 子類呼叫父類的方法 精簡語法
       # 自己還要新增一個額外的東西
       self.level = level
       self.salary = salary
class Student(Person):
   def __init__(self,name,age,gender,stu_id,class_id):
       # 用了Person類裡面的__init__方法之後
       super().__init__(name,age,gender)
       # 自己還要新增一個額外的東西
       self.stu_id = stu_id
       self.class_id = class_id
"""
如果自己寫的子類需要使用父類的方法 並且還需要基於該方法做擴充套件
這樣的子類我們稱之為派生類(本質還是子類)
那麼可以使用super關鍵字來實現
"""
t1 = Teacher('faker',28,'male','特級',888888)
s1 = Student('kevin',78,'female',20191010,3)
print(t1.__dict__)
print(s1.__dict__)

 

 

 

派生功能前瞻

class MyClass(list):
   def append(self,args):
       if args == 123:
           print('數字123不能追加')
           return
       super(MyClass,self).append(args)
obj1 = MyClass()
obj1.append(666)
obj1.append(777)
obj1.append(123)
print(obj1)