8.面向物件
阿新 • • 發佈:2020-07-13
目錄
一、類的屬性問題
新增物件屬性
可以在類中,在__init__方法中使用self.屬性名 = 值,在內外使用物件名.屬性名 = 值
新增類的靜態屬性
內中但是不再__init__方法中,屬性名=值,在類外,類名.屬性名 = 值。
物件找類屬性的順序
先在本類中找,找不到再去父類中找
二、類與類之間的關係
2.1 依賴關係
一個類的物件可以作為另一個類中方法的引數,在該方法中可以呼叫該物件擁有的方法。
class A:
def __init__(self):
pass
def funca(self):
print('你好')
class B:
def __init__(self):
pass
def funcb(self, obj):
obj.funca()
a = A()
b = B()
b.funcb(a) # 你好
2.2 關聯,聚合,組合
組合:將一個類的物件封裝到另一個類的物件的屬性中,就叫組合。
另一個類的物件可以呼叫這個類物件的屬性個方法。
三、繼承與多型
繼承的優點:
- 增加了類的耦合性
- 減少了重複程式碼
- 使得程式碼更加規範化,合理化
3.1 繼承的分類
單繼承和多繼承:
# 多繼承 class A(object): def func(self): print("A") class B(A): def func(self): super().func() print('B') class C(A): def func(self): super().func() print('C') class D(B,C): def func(self): super().func() print('D') D().func() # 找的順序是DCBA,執行順序為ABCD
3.2 多型
父類對於子類的約束,只要有這種類,子類必須實現和父類中同名的方法
實現多型的方法,抽象類。子類繼承一個抽象類並重寫抽象類中的方法。
# 父類對於子類的約束,只要有這種類,子類必須實現和pay同名的方法
# class Payment():
# def pay(self, money): # money引數在子類中也是必須的
# raise NotImplementedError('請在子類中重寫pay方法')
# 實現抽象類的類一種方法,約束性強,但是依賴abc模組
from abc import ABCMeta, abstractclassmethod
class Payment(metaclass=ABCMeta):
@abstractclassmethod
def pay(self, money): # money引數在子類中也是必須的
raise NotImplementedError('請在子類中重寫pay方法')
3.3 例項化
例項化物件時必須執行__init__方法,類中沒有,從父類找,父類沒有,從object類中找。
例項化所經歷的步驟
- 類名() 之後的第一個事兒 :開闢一塊兒記憶體空間
- 呼叫 __init__ 把空間的記憶體地址作為self引數傳遞到函式內部
- 所有的這一個物件需要使用的屬性都需要和self關聯起來
- 執行完init中的邏輯之後,self變數會自動的被返回到呼叫處(發生例項化的地方)
四、反射
用字串資料型別的名字,來操作這個名字對應的函式\例項變數\繫結方法\各種方法
使用反射場景
-
反射物件的 例項變數
-
反射類的 靜態變數/繫結方法/其他方法
-
模組中的 所有變數
被匯入的模組
當前執行的py檔案
4.1 反射物件的 例項變數
# 物件名.屬性名 --> getattr(物件名, '屬性名')
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def func(self):
print('getattr')
an = Person('an',11)
ret = getattr(an,'name')
print(ret)
ret = getattr(an, 'func') # 返回funcdi地址
print(getattr(a, 'func')()) # 反射物件的繫結方法
print(ret)
4.2 反射模組中的所有變數
# 反射模組中的所有變數
import a
print(getattr(a, 'sww'))
print(getattr(a, 'lst'))
# print(getattr(a,'Alipay'))
# print(getattr(sys.modules['a'],'Alipay'))
# wahaha = 'hahaha'
# print(getattr(sys.modules['__main__'],'wahaha'))
4.3.1 反射本模組中內容
import sys
dog = 'aqwefr'
print(getattr(sys.modules['__main__'],'dog'))
# 反射的另一個方法,hasattr返回bool
if hasattr(a, 'name'):
getattr(a, 'name')
callable(a.name) # 判斷是否可呼叫,返回bool
五、內建的魔術方法
_new_
_call_ 物件呼叫這個類中的__call__方法
_len_ len(物件)需要實現類中的__len__方法
_eq_
_str_
_repr_
六、裝飾器函式
@classmethod 傳入cls表示當前類
class Goods:
__discount = 0.8
def __inti__(self):
self.__price = 5
self.price = self.__discount*self.__price
# 把一個物件繫結的方法修改成類繫結的方法
# 在方法中可以應用類中的靜態變數,不用例項化物件
@classmethod
def change_discount(cls,new_discount):
cls.__discount = new_discount
Goods.change_discount(0.6)
import time
class Date:
def __init__(self,year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def today(cls):
struct_t = time.localtime()
date = cls(struct_t.tm_year, struct_t.tm_mon, struct_t.tm_mday)
return date
date = Date.today()
print(date.year)
print(date.month)
print(date.day)
@staticmethod 靜態方法
class User:
# 類外函式放到類內,不用self引數,也不用例項化
@staticmethod
def login():
pass
User.login()