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

python面向物件(2)

python面向物件(2)

動態方法和靜態方法

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

	2.繫結給類的方法
    class Student:
      @classmethod
      def eat(cls):
        pr(cls)
  	# 類呼叫繫結給類的方法:會自動將類當做第一個引數傳入
    print(Student)  # <class '__main__.Student'>
    Student.eat()  # <class '__main__.Student'>
    # 物件呼叫繫結給類的方法:也不需要傳參 會講產生該物件的類自動當做第一個引數傳入
    obj1.eat()  # <class '__main__.Student'>
    
    '''在類定義中,使用@classmethod裝飾器修飾的方法,必須至少有一個引數,且第一個引數留給了cls,cls指代呼叫者即類物件自身
 cls這個識別符號可以是任意合法名稱,但是為了易讀,請不要修改
 通過cls可以直接操作類的屬性'''

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

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

# 繼承的概念:
子類 擁有 父類 的所有 方法 和 屬性

# 繼承的基本使用
	"""
		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('jason', 18, 'male')

#總結

class Studen(Person)這種形式就是從父類繼承,括號中寫上繼承的類的列表。
    繼承可以讓子類從父類獲取特徵(屬性和方法)

  父類:
    calss Person就是Student和Teacher的父類,也稱為基類,超類

  子類:
    Student就是Person的子類,也成為派生類
    
#在Python3中,object類是所有物件的根基類    

class A:
    pass
'如果類定義時,沒有基類列表,等同於繼承自object'
class A(object):
    pass

新式類和經典類

#新式類:
以 object 為基類的類,推薦使用

#經典類:
不以 object 為基類的類,不推薦使用

Python 3.x 
定義類時,如果沒有指定父類,會 預設使用 object 作為該類的 基類 —— Python 3.x 中定義的類都是 新式類

Python 2.x 
定義類時,如果沒有指定父類,則不會以 object 作為 基類

'''為了保證編寫的程式碼能夠同時在 Python 2.x 和 Python 3.x 執行!
今後在定義類時為了相容,如果沒有父類,建議統一繼承自 object '''

檢視繼承的特殊屬性和方法

class A:
    pass

print(A.__base__)               #類的基類。
print(A.__bases__)              #類的基類元組。
print(A.__mro__)                #顯示方法查詢順序,基類的元組。
print(A.mro())                  #同上,返回列表。
print(A.__subclasses__())       #類的子類列表。


繼承的優缺點

#繼承的特點:

​   a.子類的獨享可以直接訪問父類中未被私有化的屬性,訪問私有化屬性時,需要在父類提供get和set方法

​   b.子類物件可以呼叫父類中未被私有化的方法

​   c.父類物件無法訪問子類物件的屬性和方法

#優缺點:

1.優點:
​   可以簡化程式碼,減少冗餘

​   可以提高程式碼的維護性

​   可以提高程式碼的安全性

​   繼承是多型的前提

2.缺點:
耦合和內聚被用來描述類與類之間的關係,一般高內聚低耦合說明程式碼比較好

繼承關係中耦合性相對較高【如果修改父類,則所有子類需求都會改變】

名字的查詢順序

不繼承情況下

# 名字的查詢順序是
  	先從物件自己的名稱空間中查詢 沒有則去類裡面的名稱空間查詢
    	物件	>>>	類
        
  '''注意設定值的情況下是在自身的名稱空間中新增或者修改資料'''
  

單繼承情況下

#名字的查詢順序是
  	先從物件自己的名稱空間中查詢 沒有擇取產生物件的類中查詢
    如果還沒有並且類有父類則去父類中查詢 以此往復下去!!!
    	物件	>>>	類	>>> 父類

# 程式碼示例:        
  	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
    
#查詢順序

  1.物件.屬性 : 先從物件空間找,再從類名空間找,再從父類找

  2.類名.屬性 : 先從類名空間找,再從父類找

  3.物件與物件之間是相互獨立的

多繼承情況下(瞭解)

'研究菱形和非菱形問題object不參與圖形構建'     
  #非菱形繼承的情況下
  	父類中名字的查詢順序就是按照繼承時從左往右依次查詢
   	如果多個父類還有分類 那麼遵循"深度優先"
	eg:D->C->B->A
  #菱形繼承的情況下
  	父類中名字的查詢順序就是按照繼承時從左往右依次查詢
   	如果多個父類還有分類 那麼遵循"廣度優先"
    D->B->C->A


派生類

# 派生的定義:
子類可以新增自己新的屬性或者在自己這裡重新定義這些屬性(不會影響到父類)
重新定義了自己的屬性且與父類重名那麼呼叫新增的屬性時 就以自己為準

#程式碼示例:
class Animal():
    def __init__(self,name,age,gender,birth):
        self.name = name
        self.age = age
        self.gender = gender
        self.birth = birth

class Cat(Animal):
    def __init__(self,name,age,gender,birth,eat,live):
        # 子類呼叫父類的方法
        super().__init__(name,age,gender,birth) 
         # 自己還要新增一個額外的東西
        self.eat = eat
        self.live = live

class Dog(Animal):
    def __init__(self,name,age,gender,birth,play,sleep):
        super().__init__(name,age,gender,birth)
        self.play = play
        self.sleep = sleep
        """
如果自己寫的子類需要使用父類的方法 並且還需要基於該方法做擴充套件
這樣的子類我們稱之為派生類(本質還是子類)      
    那麼可以使用super關鍵字來實現
"""