python筆記60 - 類里面靜態方法(@staticmethod),類方法(@classmethod)和實例方法(self)的使用與區別


前言

python 類里面常用的方法有3個:靜態方法(@staticmethod),類方法(@classmethod)和實例方法(self)
本篇講解這3種方法在使用上有什么區別。

函數

先從函數說起,方法跟函數是有區別的,經常有人容易混淆,函數定義是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())

前面https://www.cnblogs.com/yoyoketang/p/15151723.html講屬性的時候說到過A類的屬性和A()實例對象屬性是不一樣的。
fun()里面帶了self參數,那么它是實例方法,也就是A()實例對象的方法了,所以必須先實例化A()才能調用此方法。

靜態方法(@staticmethod)

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

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

於是會想到,在類里面是不是也可以寫一個函數呢?於是就有了靜態方法(@staticmethod),靜態方法的出現就是為了在類里面可以寫一個函數,當普通的函數去調用。
定義靜態方法需使用@staticmethod裝飾器,並且括號后面不需要self參數了。

# 作者-上海悠悠 QQ交流群:717225969 
# blog地址 https://www.cnblogs.com/yoyoketang/


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類只要count屬性
  • A()實例對象的屬性是__init__里面的age和name,並且包含A類屬性count
class A(object):
    count = 0

    def __init__(self):
        self.age = 18
        self.name = "yoyo"
# A只有count屬性
print(A.count)

# A() 實例化對象
a = A()
print(a.count)
print(a.name)
print(a.age)

既然已經知道了A類的屬性和A()實例對象屬性是不一樣的,再回到前面的實例方法概念上,實例方法是A()實例對象的方法。
既然A()實例對象有實例方法,那么A類當然也有類方法的概念了,於是可以在方法上加上@classmethod裝飾器聲明它是類方法,並且括號第一個參數cls是指類本身

# 作者-上海悠悠 QQ交流群:717225969 
# blog地址 https://www.cnblogs.com/yoyoketang/


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()

這樣同樣可以達到實例化的效果,於是就兼容了前面的代碼了
參考資料https://www.zhihu.com/question/20021164


免責聲明!

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



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