python之類中靜態方法(@staticmethod),類方法(@classmethod)和實例方法(self)的使用與區別


前言

python 類里面常用的方法有3個:靜態方法(@staticmethod),類方法(@classmethod)和實例方法(self)。

函數

方法跟函數是有區別的,函數定義是def 關鍵字定義(外面沒class)。

def fun():
    a = "hello"
    return a

# 函數調用
res = fun()
print(res)

函數調用使用函數名稱后面加括號就能調用了

實例方法(self)

類里面的方法定義也是用def 關鍵字,注意在類里面叫方法了,不叫函數,定義的方法默認在括號里面加一個self參數。

self 是類本身的實例對象,所以在看到def 定義的方法括號后面有self參數的叫實例方法。

class A(object):
    count = 0

    def fun(self):
        b = "world"
        return b

# A類不能直接調用fun
# print(A.fun())
a = A()
print(a.fun())

靜態方法(@staticmethod)

我們可以在函數里面寫一個類:

def fun():
    a = "hello"
    
    class A(object):
        count = 0
    
        def fun(self):
            b = "world"
            return b
    return A

於是會想到,在類里面是不是也可以寫一個函數呢?【類里面寫函數,注意不是方法】於是就有了靜態方法(@staticmethod),靜態方法的出現就是為了在類里面可以寫一個函數,當普通的函數去調用。

定義靜態方法需使用@staticmethod裝飾器,並且括號后面不需要self參數了。

class A(object):
    count = 0

    def fun(self):
        b = "world"
        return b

    @staticmethod
    def start():
        print("start-----")

# 不用實例化也能調用
A.start()
# 實例化也能調用
a = A()
a.start()

靜態方法不需要實例化可以直接調用,實例化后也能調用,可以理解成函數。

類方法(@classmethod)

類里面有2個概念,屬性和方法。

既然已經知道了A類的屬性和A()實例對象屬性是不一樣的,再回到前面的實例方法概念上,實例方法是A()實例對象的方法。

既然A()實例對象有實例方法,那么A類當然也有類方法的概念了,於是可以在方法上加上@classmethod裝飾器聲明它是類方法,並且括號第一個參數cls是指類本身。

class A(object):
    count = 0

    def fun(self):
        b = "world"
        return b

    @staticmethod
    def start():
        print("start-----")

    @classmethod
    def create(cls):
        print("create--------")

# 不需要實例化,類名稱直接調用類方法
A.create()
# 實例化也能調用類方法
a = A()
a.create()

類方法使用場景

實例方法和靜態方法小伙伴們應該是經常用的,類方法這個概念本身比較難懂,就算看懂了也不知道如何用到具體場景上,在網上搜到一個案例講解的挺好的。

class DataTest(object):
    day = 0
    month = 0
    year = 0

    def __init__(self, year=0, month=0, day=0):
        self.day = day
        self.month = month
        self.year = year

    def out_date(self):
        print("year :", self.year)
        print("month :", self.month)
        print("day :", self.day)

t = DataTest(2021, 8, 18)
t.out_date()   

運行結果:

year : 2021
month : 8
day : 18

但是如果用戶輸入的是 "2016-8-1" 這樣的字符格式,那么就需要調用Date_test 類前做一下處理:

string_date = '2018-8-18'
year, month, day = map(int, string_date.split('-'))
s = DataTest(year, month, day)
print(s.out_date())

先把‘2018-8-18’ 分解成 year,month,day三個變量,然后轉成int,再調用DataTest(year, month, day) 也很符合期望。
那我可不可以把這個字符串處理的函數放到 DateTest 類當中呢?
那么@classmethod 就開始出場了:【類最基本的作用是實例化出一個對象,但是有的時候再實例化之前,就需要先和類做一定的交互,這種交互可能會影響實際實例化的過程,所以必須放在調用構造函數之前。】

class DataTest(object):
    day = 0
    month = 0
    year = 0

    def __init__(self, year=0, month=0, day=0):
        self.day = day
        self.month = month
        self.year = year

    def out_date(self):
        print("year :", self.year)
        print("month :", self.month)
        print("day :", self.day)

    @classmethod
    def get_data(cls, string_date):
        """處理'2018-8-18'字符格式"""
        year, month, day = map(int, string_date.split('-'))
        return cls(year, month, day)

定義一個get_data類方法,處理完字符串后返回這個類的實例對象:【與實例化類返回類的實例對象的作用相同】

r = DataTest.get_data('2018-8-18')
r.out_date()

這樣同樣可以達到實例化的效果,於是就兼容了前面的代碼了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM