Python_學習之面向對象

1、定義
類:具備相同屬性和能力的一類事物python

對象:類的具體表現api

語法:ide

# 構建
class LearnPython(object):
    """
    類名必須首字母大寫,駝峯體
    """

    country = "China"  # 靜態變量

    def __init__(self, name, location):  # 動態方法
        self.name = name
        self.location = location

    def read(self):
        pass

# 類
# 查看類擁有的全部屬性與方法
print(LearnPython.__dict__)

# {'__module__': '__main__',
 '__doc__': '\n    類名必須首字母大寫,駝峯體\n    ',
 'country': 'China',
 '__init__': <function LearnPython.__init__ at 0x000001E81E75E8C8>,
 'read': <function LearnPython.read at 0x000001E81E75E510>,
 '__dict__': <attribute '__dict__' of 'LearnPython' objects>,
 '__weakref__': <attribute '__weakref__' of 'LearnPython' objects>}

# 實例化
obj = LearnPython("Elvin", "北京")
# 查看實例全部的屬性
print(obj.__dict__)  # {'name': 'Elvin', 'location': '北京'}
# 查看實例擁有的方法【能力】
print(obj.read())   # Elvin在北京看故宮
# 對屬性值的更改
obj.name = "LiLei"
del obj.name
print(obj.__dict__)

2、實例化及建立對象的過程函數

一旦執行ClassName()類實例化動做,自動執行類中的new()方法,當前類中沒有的則去基類object中執行new(cls,*args,**kwargs),建立一個對象空間,返回給ClassName(),指針

而後執行init方法,將對象空間傳給self,init方法爲這個對象空間初始化封裝屬性,code

最後將封裝好的屬性返回給ClassName()對象

3、類與對象的小結繼承

類名:
一、類名查看類中全部的變量(字段),方法(函數):類名.__dict__
二、類名對靜態變量進行操做
  方法1、類名.__dict__["變量名"] 只能查,報錯不能增刪改 **不用**
  方法2、類名.變量名 可增刪改查 *****經常使用******  
三、類名對動態方法(函數)進行操做

類名.__dict__["方法名"] 或 類名.方法名 都只能查,不能增刪改

類調用函數必須給self賦值,哪怕賦的值是無用的,否則根據函數位置參數定義,就會因缺乏參數報錯

對象:
一、對象查看對象中全部的屬性:對象名.__dict__ (由於對象沒有創建本身的方法,故此時只能返回屬性的字典)
二、對象對對象自己的屬性的操做
  方法一、對象名.屬性 能夠增刪改查
  方法二、對象名.__dict__[屬性名] 能夠增刪改查 ******不用*****

三、對象對類中靜態字段的操做
3.一、對類靜態變量(字段)的操做:只能查,不能增刪改
3.二、對類方法的操做:只能引用,不能增刪改

self 是位置參數,默認接收的是對象的對象空間,約定俗成叫self

在類的非__init__方法中,也能夠給對象添加一些屬性,但如要使用這些屬性,前提必須先執行這個方法

類一旦建立了,就會執行裏面的代碼塊,若是裏面有print語句,就會執行,不像函數要調用才執行

類 只能操做本身的屬性及方法,沒法操做對象的屬性和方法,由於每一個對象的屬性都是本身獨有的

類屬性的補充
一、查看類的屬性和方法
dir(類名) ----->返回名字列表
類名.__dict__ ----->返回一個字典
二、特殊的類屬性
類名.__name__ # 類的名字
類名.__doc__ # 類的文檔字符串
類名.__base__ # 類的第一個父類名(繼承中從左到右)
類名.__bases__ # 類的全部父類 -----> 返回一個元組
類名.__dict__ # 類的全部屬性與方法
類名.__module__ # 類定義所在的模塊 【在類所在的腳本中執行和 print(__name__) 同樣都是固定的名字:__main__】
類名.__class__ # 實例對應的類(僅新式類中)

4、類與對象的命令空間接口

建立一個類就會建立一個類的名稱空間,用來存儲類中定義的全部名字,這些名字稱爲類的屬性

靜態屬性就是直接在類中定義的變量(靜態變量或者叫靜態字段)

動態屬性就是定義在類中的方法

類的靜態屬性是共享給全部對象的

類的動態屬性是綁定到全部對象的

建立一個對象/實例就會建立一個對象/實例的名稱空間(開始裏面只有對應類對象的指針,以便找到類的__init__()方法來傳空間地址及封裝對象屬性),存放對象/實例的名字,稱爲對象/實例的屬性

對象的查詢順序:先從對象空間去找,對象的空間沒有此變量或者方法,經過對象中的類對象指針去類中尋找.

類的查詢順序: 直接從類自己找.它沒法查找對象的屬性,由於是不一樣的命名空間

不管建立多少個對象,都是獨立開闢的命名空間,各個空間互相不能查找,干擾
  1. 計算一個類實例化了多少個對象?
class Test:
    count = 0

    def __new__(cls, *args, **kwargs):
        cls.count += 1
        return object.__new__(cls)

    def __init__(self):
        pass
print(Test.count)

5、類的三大特性內存

繼承

Python中一個類能夠繼承一個或多個父類,父類稱爲基類,子類稱爲派生類

做用:代碼重用,規範接口,統一調用【規範調用方式,調用者不用關心實現】

class A:
    pass
class B:
    pass
class C(A,B):
    pass
# 上面就是基本的一個繼承關係,C類分別繼承了A,B類的全部屬性和方法,C類實現的實例均可以訪問
# 但有一點,若是子類和父類都有相同的方法,優先執行子類本身的方法
# 全部的類,都繼承基類Object類

# 查看繼承關係
C.__bases__

# 查看是否爲某個類的對象【開發中常用】
instance(obj,cls)
如:instance("china",str)

# 查看是否爲某個類的子類
issubclass(cls,fater_cls)

# 接口類
定義一個抽象類,爲一組子類定義一個通用的api,使調用方式統一,且接口類是不能夠實例化的
from abc import ABCMeta, abstractmethod

class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        """經過裝飾器,標識爲抽象方法,全部子類都需實現本方法"""
        return

# a = Payment()  # Can't instantiate abstract class Payment with abstract methods pay

class UnionPay(Payment):
    def __init__(self, year):
        self.year = year

    def pay(self, money):
        """若是這裏不實現此方法,就沒法實例化"""
        print("222")

u = UnionPay("2021")  # Can't instantiate abstract class UnionPay with abstract methods pay

封裝
隱藏對象的屬性和實現細節,僅提供公共訪問方式,咱們實例化調用init就是一種封裝

私有屬性
Python中將在類中以雙劃線開頭定義的變量或方法,稱爲私有屬性或方法,僅提供給類內部調用

class Test(object):

    def __init__(self, action):
        self.action = action

    def __smoke(self):
        """此方法僅僅用於類內部調用"""
        print(f"class want ro {self.action}")

    def wash(self):
        print(self.__smoke())
        print(f"wash your {self.action}")

t = Test("face")
t.wash()
t.somke()   # AttributeError: 'Test' object has no attribute 'somke'

靜態屬性、靜態方法、類方法

class Test(object):
    __TYPE = "python小白養成記"

    def __init__(self, action):
        self.__action = action

    @property
    def do(self):
        return f"I can do:{self.__action}"

    @do.setter
    def do(self, v):
        """改變do返回的值"""
        self.__action = v

    @do.deleter
    def do(self):
        print("delete instance property is ok")

    @staticmethod
    def show_action():
        """靜態方法:實現普通方法,不需調用實例屬性和方法"""
        print("just a ordinary function")

    @classmethod
    def action(cls):
        """類方法"""
        return cls.__TYPE

    def __repr__(self):
        return f"just print the object instance:{self.__action}"

t = Test("eat")

# 靜態屬性property
將類中方法實現的能力,調用時以屬性的方式調用
print(t.do)  # I can do:eat
t.do = "kiss"
print(t.do)  # I can do:kiss
del t.do  # Exception: can't delete instance property

# 靜態方法 staticmethod
類中實現的方法,非實例方法,第一個參數不是self,就至關於普通方法
t.show_action()

# 類方法,調用方爲類,雖然對象也能夠調用,但不建議
t.action()

多態
python天生多態,一類事物有多種狀態,相同的需求不一樣的對象接收時執行不一樣的行爲,但響應的接口是一致的

如:list、dict、set三種不一樣的對象,要刪除元素,都實現了pop方法,雖然他們內部執行的邏輯不一樣,這就是pop的多種狀態

反射【很是重要】
官方定義:程序能夠訪問、檢測和修改它自己狀態或行爲的一種能力

小白解析:經過字符串的形式操做對象的屬性【Python中的哲學:一切皆對象】

hasattr(obj,name) 對象是否有某個屬性
getattr(obj,name,default=None) 獲取對象的某個屬性,若是沒有則返回默認值
setattr(obj,name,value) 爲對象設置一個屬性name,其值爲value
delattr(obj,name) 刪除對象的某個屬性,若是該屬性不存在則拋出異常

# 示例:
class Test(object):
    def __init__(self, code, desc):
        self.code = code
        self.desc = desc

    def biz(self):
        return dict(code=self.code, desc=self.desc)

obj = Test(0, "success")

# 判斷
print(hasattr(obj, "code"))  # True
# 獲取
fun = getattr(obj, "biz", "沒有該屬性時返回的值,不配置時爲None")
print(fun())  # {'code': 0, 'desc': 'success'}
# 設置新屬性
setattr(obj, "data", lambda self: dict(self.biz()))
print(obj.data(obj))  # {'code': 0, 'desc': 'success'}

# 刪除屬性
delattr(obj, "code")

# 查看對象的全部屬性
print(obj.__dict__)  # {'desc': 'success', 'data': <function <lambda> at 0x000001E0835DE8C8>}

# py文件也是對象,驗證test.py文件中是否有某個方法
import test
if hasattr(test,"func"):
    ret = getattr(test,"func")("args")
    print(ret)

常見的魔法方法

__new__(cls)   對象的構造方法
__init__(self) 對象的初始化方法
__call__(self,*args,**kwargs) 類的實例化對象如函數通常調用,obj=A(),obj(a,b)
__del__(self)  析構方法,釋放內存,動用del obj時使用,Python內部自動觸發內存回收機制

__repr__(self) 友好的以字符串顯示對象,而不是一個內存地址空間,調用repr()方法
__str__(self)  友好的以字符串顯示對象,調用srt()方法
__dir__(self)  顯示對象的方法與屬性,調用dir()

__getattr__(self,name)  定義調用方試圖獲取一個不存在屬性時的動做
__setattr__(self,name,value)  定義當一個屬性被設置時的行爲
__delattr__(self,name)  定義當一個屬性被刪除時的行爲

__getitem__(self,key)   定義獲取容器指定元素的行爲,至關於self[key]
__setitem__(self, key, value)  定義設置容器中指定元素的行爲,至關於 self[key] = value
__delitem__(self, key)  定義刪除容器中指定元素的行爲,至關於 del self[key]

__enter__(self)  
1. 定義當使用 with 語句時的初始化行爲
2. __enter__ 的返回值被 with 語句的目標或者 as 後的名字綁定
__exit__(self, exc_type, exc_value, traceback)
1. 定義當一個代碼塊被執行或者終止後上下文管理器應該作什麼
2. 通常被用來處理異常,清除工做或者作一些代碼塊執行完畢以後的平常工做
相關文章
相關標籤/搜索