自己喜歡,
就好。
通過一個例子來區分三者的區別和使用場景:
定義一個Date類來輸出日期:
class Date:
# 構造函數
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
再在類中重新定義它的__str__方法,這樣在列印的時候就可以直接列印出日期:
class Date:
# 構造函數
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def __str__(self):
return "{year}/{month}/{day}".format(year = self.year, month = self.month,day = self.day)
運行一下:
class Date:
# 構造函數
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def __str__(self):
return "{year}/{month}/{day}".format(year = self.year, month = self.month,day = self.day)
if __name__ == "__main__":
new_day = Date(2018,12,30)
print(new_day)
運行結果:
在上面的代碼中__init__和__str__都是實例方法也就是對象方法。
再定義一個實例方法:
class Date:
# 構造函數
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def tomorrow(self):
self.day += 1
def __str__(self):
return "{year}/{month}/{day}".format(year = self.year, month = self.month,day = self.day)
if __name__ == "__main__":
new_day = Date(2018,12,30)
new_day.tomorrow()
print(new_day)
運行結果:
在上面的代碼中,傳遞給Date的值是2018、12、30三個數字,如果希望傳遞進來的是一個日期的字符串,如「2018-12-30」。
首先想到的方法就是split分割字符串,然後把對應的值賦給變量。
先在類外實現這個功能:
date_str = "2018-12-30"
year, month, day = tuple(date_str.split("-"))
print(year, month, day)
print(type(year))
運行結果:
image.png
這時候year、month、day的值的類型都是字符串,所以賦值的時候要進行類型轉換:
date_str = "2018-12-30"
year, month, day = tuple(date_str.split("-"))
print(year, month, day)
print(type(year))
new_day = Date(int(year), int(month), int(day))
print(new_day)
運行結果:
image.png
也就是說,每一次實例化的時候,都要運行上面的分割字符串,並把值賦給對應的變量這段代碼,所以就可以在類中定義一個靜態方法,也就是在def的上一行加上@staticmethod這句
class Date:
# 構造函數
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def tomorrow(self):
self.day += 1
@staticmethod
def parse_from_string(data_str):
year, month, day = tuple(date_str.split("-"))
return Date(int(year), int(month), int(day))
def __str__(self):
return "{year}/{month}/{day}".format(year = self.year, month = self.month,day = self.day)
這個靜態方法接收不需要self,也不需要接收class對象,與普通的函數用法相同。
new_day = Date.parse_from_string(date_str)
print(new_day)
運行一下:
image.png
這個靜態方法實現起來更簡單,也更易懂,缺點是,硬編碼。(return硬編碼,把Date直接返回了,也就是如果一旦改變了類名,這個位置也必須要修改),要想解決這個問題可以使用類方法。
class Date:
# 構造函數
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def tomorrow(self):
self.day += 1
@staticmethod
def parse_from_string(data_str):
year, month, day = tuple(date_str.split("-"))
return Date(int(year), int(month), int(day))
@classmethod
def from_string(cls,date_str):
year, month, day = tuple(date_str.split("-"))
return cls(int(year), int(month), int(day))
def __str__(self):
return "{year}/{month}/{day}".format(year = self.year, month = self.month,day = self.day)
類方法和實例方法的區別是:
類方法首先傳遞進來的是類,也就是cls,它是class的簡寫,cls改成self也是不會有問題的。
既然這樣類方法就完全可以取代靜態方法了嗎。
如果想要判斷傳遞進來的字符串是否是合法的時間,那麼就沒有必要把類傳遞到方法中,這時候使用靜態方法更方便一些。
class Date:
# 構造函數
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def tomorrow(self):
self.day += 1
@staticmethod
def parse_from_string(data_str):
year, month, day = tuple(date_str.split("-"))
return Date(int(year), int(month), int(day))
@staticmethod
def valid_str(data_str):
year, month, day = tuple(date_str.split("-"))
if int(year) > 0 and int(month) > 0 and int(month) < 13 and int(day) > 0 and int(day) < 32:
return True
else:
return False
@classmethod
def from_string(cls,date_str):
year, month, day = tuple(date_str.split("-"))
return cls(int(year), int(month), int(day))
def __str__(self):
return "{year}/{month}/{day}".format(year = self.year, month = self.month,day = self.day)
這裡只是簡單實現了一下判斷,實際在判斷字符串是否是合法的時間比這要複雜得多。
new_day = Date.from_string(date_str)
print(new_day)
print(new_day.valid_str(date_str))
運行一下:
作者:李白開水
來源:簡書