python 類函數,實例函數,靜態函數

1、實現方法

class Function(object):
    # 在類定義中定義變量
    cls_variable = "class varibale"

    def __init__(self):
        # 在構造函數中建立變量
        self.__instance_variable = "instance variable"

    def instance_method(self):
        print(self.cls_variable)
        print(self.__instance_variable)
        print("this is a instance method")

    @staticmethod
    def static_method():
        print(Function.cls_variable)
        # print(Function.__instance_variable)    此處會報錯,沒法訪問實例變量
        print("this is a static method")

    @classmethod
    def class_method(cls):
        print(cls.cls_variable)
        # print(cls.__instance_variable)   此處會報錯,沒法訪問實例變量
        print("this is a class method")

    @classmethod
    def set_class_variable(cls):
        cls.cls_variable = 'new class variable'

    def set_instace_varibale(self):
        self.__instance_variable = 'new instance varibale'

#  類實例能夠調用類方法和靜態方法
function1 = Function()
function1.set_class_variable()
function1.class_method()
function1.instance_method()
function1.static_method()

function2 = Function()
function2.set_instace_varibale()
function2.class_method()
function2.instance_method()
function2.static_method()


一、從代碼定義中,能夠看到只是在默認傳入參數的不一樣。python

Function.class_method()
Function.static_method()
# 能夠調用實例函數,只不過須要傳入實例變量
Function.instance_method(function1)

二、從代碼訪問中,經過實例訪問這三種方法是同樣的。可是同時類訪問時,不同,實例函數須要傳入實例。函數

三、函數訪問變量中,有很大不一樣。this

@classmethod
    def class_method(cls):
        print(cls.cls_variable)
        # print(cls.__instance_variable)   此處會報錯,沒法訪問實例變量

在init函數定義的是實例變量,由於變量前綴添加了self。在類開始時定義的類變量,不須要添加前綴。spa

在變量訪問中,發現類函數和靜態函數是沒法直接訪問實例變量的,由於在後續調用中,不知道是那個實例的。可是實例函數是能夠訪問類變量的。設計

四、修改變量的範圍code

new class variable
this is a class method
new class variable
instance variable
this is a instance method
new class variable
this is a static method

上圖是function1中輸出的結果。orm

new class variable
this is a class method
new class variable
new instance varibale
this is a instance method
new class variable
this is a static method
new class variable

這是function2的結果,則class variable都變化了。blog

若是經過類方法修改變量,則全部實例中的類變量都會修改,這個相似靜態變量了繼承

若是經過實例修改變量,只是修改對應的實例變量。ip

2、三者選擇原則

經過第一節的分析,咱們得知三者的不一樣,在訪問權限和方式上,類方法和靜態方法有不少相同之處。與實例方法的區別就是看看這個方法是否是實例獨有的方法,或者須要訪問實例變量的。另外一個不一樣就是在繼承上了。

一、類方法和靜態方法

# -*- coding: utf-8 -*-
"""
@Time   : 2017/12/29 9:50
@Author:dongbl
@Description:
"""


class Function(object):
    X = 1
    Y = 2

    @staticmethod
    def averag(*mixes):
        return sum(mixes) / len(mixes)

    @staticmethod
    def static_method():
        # 經過function調用,若是類名修改,此處須要修改不太方便
        return Function.averag(Function.X, Function.Y)

    @classmethod
    def class_method(cls):
        return cls.averag(cls.X, cls.Y)

class Subclass(Function):
    X =3
    Y = 5

    @staticmethod
    def averag(*mixes):
        return sum(mixes) / 3

func = Subclass()
print(func.static_method())
print(func.class_method())

一、調用方式不一樣,另外一方面就是若是類名修改,函數也修改

二、繼承。這是二者最大的不一樣

1.5
2.6666666666666665

上面是二者的輸出。

子類的實例繼承了父類的static_method靜態方法,調用該方法,仍是調用的父類的方法和類屬性。
子類的實例繼承了父類的class_method類方法,調用該方法,調用的是子類的方法和子類的類屬性。

這就是最大的不一樣,靜態方法在類沒有初始化,已經加載了,後續繼承和她就沒有關係了。同時靜態方法關鍵明確指明瞭調用了Function的方法了,因此就沒法修改了。這是本質。

3、類方法和實例方法

類中最經常使用的方法是實例方法, 即經過經過實例做爲第一個參數的方法。

若是如今咱們想寫一些僅僅與類交互而不是和實例交互的方法會怎麼樣呢?在Python2.2之後可使用@classmethod裝飾器來建立類方法.

好比咱們建立一個類:

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

    def print_date(self):
        print("{}:{}:{}".format(self.year,self.month,self.day))

若是用戶輸入的是「2017-12-02」這樣的字符,咱們在調用類以前就須要調整一下。

這個設計角度能夠理解每一個實例均可以調用這個轉化函數。

# -*- coding: utf-8 -*-
"""
@Time   : 2017/12/29 9:50
@Author:dongbl
@Description:
"""
class DateTest():
    def __init__(self,year,month,day):
        self.year = year
        self.day = day
        self.month = month

    def print_date(self):
        print("{}:{}:{}".format(self.year,self.month,self.day))

    @classmethod
    def get_date(cls,string_date):
        year,month,day = map(int,string_date.split('-'))
        return cls(year,month,day)

t = DateTest(2017,9,10)
r = DateTest.get_date("2017-12-09")
r.print_date()
t.print_date()

classmethod主要用途是做爲構造函數。
Python只有一個構造函數__new__,若是想要多種構造函數就很不方便。只能在new裏面寫一堆if isinstance 。
有classmethod以後就能夠用classmethod來寫不一樣的構造函數,好比:
dict.fromkeys
fractions.Fraction.from_decimal
inspect.Signature.from_function
python裏面大部分classmethod最後都是 return cls(XXX), return XXX.__new__ ()之類的

staticmethod主要用途是限定namespace,也就是說這個函數雖然是個普通的function,可是它只有這個class會用到,不適合做爲module level的function。這時候就把它做爲staticmethod。
若是不考慮namespace的問題的話直接在module裏面def function就好了。

4、參考文獻


一、python類的靜態方法和類方法區別

二、知乎經典解答

相關文章
相關標籤/搜索