python面向對象中的self,cls,staticmethod,classmethod

2021-02-21 python教程入門到實戰

先給大家拜年,新年第一篇繼續我複習面向對象的知識,這次打算說說我疑惑挺久的self,cls,staticmethod,classmethod是幹嘛的,有什麼用。

這裡會說到:類方法,靜態方法,類屬性,實例方法等相關。先看一個例子:

class Person:    belong_to = 'earthman'    def __init__(self,skin, name):        self.skin = skin        self.name = name    def get_skin(self):        return self.skin            @classmethod    def menthod_cls(cls):        print(f'{cls},hello,{Person.belong_to}')            @staticmethod    def menthod_state():        print(f'hello,{Person.belong_to}')        lm = Person('yellow', '李明')print(lm.get_skin())print(Person.menthod_cls())print(lm.menthod_cls())print(Person.menthod_state())
yellow<< span="">class '__main__.Person'>,hello,earthman<< span="">class '__main__.Person'>,hello,earthmanhello,earthman

可以看到使用了classmethod或者staticmethod裝飾後的方法,調用有些不一樣,可以直接用類名.方法名()調用。

一開始我並沒有get到這種做法有什麼特別妙的地方,看了眾多大佬的解讀,總結出:

•減少實例化對象的開銷,如果方法沒有用到實例化的任何屬性和方法,推薦使用靜態類方法@staticmethod

•屬於類的方法放到類裡面,利於組織代碼,容易閱讀。

cls和self有什麼特點

類的方法,第一個參數必須是self或者是cls(必須用classmethod裝飾),這是一種約定。

cls,表示的是類本身,self表示實例化具體對象的本身。好比說在解析器執行代碼的時候,具體的Person類也是一個對象,cls是Person的引用。slef就是lm對象的引用。

第一個參數為什麼必須是cls或者self?將在下面最後講到。

staticmethod和classmethod的特點

上面說到使用了這兩者裝飾的方法都可以用類.方法()調用,這兩個有什麼特點?

•@staticmethod,不需要self或者cls參數,靜態方法,主要處理與這個類的邏輯關聯, 如驗證數據。注意,無法在靜態類方法中使用實例化屬性或者方法,比如上面的靜態類方法:

@staticmethoddef menthod_state():    print(f'hello,{Person.belong_to}')    print(Person.get_skin())

 以上使用了實例化self對象的方法會報錯。我的理解是,帶有self的方法,是實例化對象的方法,所以無法通過類對象來使用。

•@classmethod,第一個參數必須是cls,類方法,可以來調用類的屬性,類的方法,實例化對象等,避免硬編碼。比如上面使用類.方法(),實例化.方法()效果是一樣的。重構類的時候不必要修改構造函數,只需要額外添加你要處理的函數(使用場景)。我在看scrapy代碼中發現不少這類型的方法,現在想來確實是用在重構中多些,之前還看不懂。

為什麼必須在方法定義和調用中顯式使用「self」?

據說曾經有建議取消self,後來被python發明的大佬回答為什麼必須帶self的原因。首先self代表了實例化對象。比如:

lm = Person('yellow', '李明')lm.get_skin()Person.get_skin(lm)

lm現在是一個具體叫李明的人,那麼在調用Person成員方法的時候,會隱式傳遞lm對象給get_skin(),也就是self。那為什麼非要把self寫到方法中?在官方python文檔有解釋:

在python中沒有局部變量聲明,加self就可以表示本實例化的變量/方法。可以理解成類裡面的全局變量,局部變量和實例變量存在於兩個不同的命名空間中,您需要告訴 Python 使用哪個命名空間。

那麼對於cls參數其實也類似,必須告訴調用的方法,具體的類名,通過cls傳遞類對象進行調用。在重構的時候,也用得著。

以上就是本次閱讀了大量資料後整理出的資料,希望對你們有幫助。

相關焦點

  • Python中classmethod和staticmethod的區別
    class MyClass(object):    def instancemethod(self,parameters)                pass    @classmethod        def classmethod(cls):                pass    @staticmethod        def staticmethod
  • Python 中 staticmethod 和 classmethod 原理探究
    起步文章Python 中 property 的實現原理及實現中探究了 property 的實現原理。如果能理解那邊描述符的使用方式,那也能很快理解本篇中的 staticmethod 和 classmethod 。
  • Python的@staticmethod和@classmethod的作用與區別
    但是使用@staticmethod或@classmethod,就可以不需要實例化。所以@staticmethod或@classmethod作用:使用@staticmethod或@classmethod,就可以不需要實例化,直接類名.方法名()來調用。這有利於組織代碼,把某些應該屬於某個類的函數給放到那個類裡去,同時有利於命名空間的整潔。
  • [每日一題]2、Python中的類的定義和裝飾器@classmethod與@staticmethod
    普通方法類方法(@classmethod)靜態方法(@staticmethod)1、普通方法的使用class A():    def __init__(self, name, age):        self.name
  • Python 中的函數與方法 以及 Bound Method 和 Unbound Method
    method(方法) —— A function which is defined inside a class body.Ifcalled as an attribute of an instance of that class, the methodwill get the instance object as its first argument (which isusually called self).
  • 史上最全 Python 面向對象編程
    根據需要,決定是否寫一個main函數作為程序入口面向對象編程中,將函數和變量進一步封裝成類,類才是程序的基本元素,它將數據和操作緊密地連結在一起,並保護數據不會被外界的函數意外地改變。類和和類的實例(也稱對象)是面向對象的核心概念,是和面向過程編程、函數式編程的根本區別。
  • 可能是最全的Python面向對象入門教程了
    根據需要,決定是否寫一個main函數作為程序入口面向對象編程中,將函數和變量進一步封裝成類,類才是程序的基本元素,它將數據和操作緊密地連結在一起,並保護數據不會被外界的函數意外地改變。類和和類的實例(也稱對象)是面向對象的核心概念,是和面向過程編程、函數式編程的根本區別。
  • 轉載 | 史上最全 Python 面向對象編程
    面向對象編程和函數式編程(面向過程編程)都是程序設計的方法,不過稍有區別。類和和類的實例(也稱對象)是面向對象的核心概念,是和面向過程編程、函數式編程的根本區別。並不是非要用面向對象編程,要看你的程序怎麼設計方便,但是就目前來說,基本上都是在使用面向對象編程。面向對象是通過定義class類來定義,這麼說面向對象編程就是只使用 class 類,在 class 類中有封裝,繼承的功能,並且還可以構造要傳入的參數,方便控制。
  • Python中的靜態方法、類方法以及對象方法(實例方法)
    )運行結果:在上面的代碼中__init__和__str__都是實例方法也就是對象方法。(day)) def __str__(self): return "{year}/{month}/{day}".format(year = self.year, month = self.month,day = self.day)這個靜態方法接收不需要self,也不需要接收class對象,與普通的函數用法相同。
  • 一篇非常全的Python 面向對象編程
    根據需要,決定是否寫一個main函數作為程序入口面向對象編程中,將函數和變量進一步封裝成類,類才是程序的基本元素,它將數據和操作緊密地連結在一起,並保護數據不會被外界的函數意外地改變。類和和類的實例(也稱對象)是面向對象的核心概念,是和面向過程編程、函數式編程的根本區別。
  • 很全的 Python 面試題
    >3 @staticmethod和@classmethodPython其實有3個方法,即靜態方法(staticmethod),類方法(classmethod)和實例方法,如下:def foo(x):    print "executing foo(%s)"%(x)class A(object):    def foo(self,x
  • Python學習:類和實例
    將實例方法參數中的self去掉,然後在方法定義上方加上@staticmethod,就成為靜態方法。它屬於類,和實例無關。建議只使用類名.靜態方法的調用方式。(雖然也可以使用實例名.靜態方法的方式調用)class Foo:    @staticmethod    def static_method():        passFoo.static_method()類方法
  • 史上最全 Python 面向對象編程技巧!
    根據需要,決定是否寫一個main函數作為程序入口面向對象編程中,將函數和變量進一步封裝成類,類才是程序的基本元素,它將數據和操作緊密地連結在一起,並保護數據不會被外界的函數意外地改變。類和和類的實例(也稱對象)是面向對象的核心概念,是和面向過程編程、函數式編程的根本區別。
  • 史上最全Python面向對象編程
    根據需要,決定是否寫一個main函數作為程序入口面向對象編程中,將函數和變量進一步封裝成類,類才是程序的基本元素,它將數據和操作緊密地連結在一起,並保護數據不會被外界的函數意外地改變。類和和類的實例(也稱對象)是面向對象的核心概念,是和面向過程編程、函數式編程的根本區別。並不是非要用面向對象編程,要看你的程序怎麼設計方便,但是就目前來說,基本上都是在使用面向對象編程。
  • Python-15-類的定義和使用
    詳細區別可查看Python的@staticmethod和@classmethod的作用與區別,今天主要介紹普通方法。定義方式:(類似函數的定義),用class來標識。就像這樣:class ClassName: <statements> def funs(self, arg): <fun statements> @classmethod def clsFuns(cls, arg):
  • 詳解Python類中不同方法的應用
    主要是用來存放邏輯性的代碼,邏輯上屬於類,但是和類本身沒有關係,也就是說在靜態方法中,不會涉及到類中的屬性和方法的操作。可以理解為,靜態方法是個獨立的、單純的函數,它僅僅託管於某個類的名稱空間中,便於使用和維護。通常情況下,靜態方法使用@staticmethod裝飾器(或使用staticmethod())來聲明。
  • Python 為什麼要保留顯式的 self ?
    Python 約定了一種方式,即在定義時用第一個參數作區分:self 表示實例方法、cls或其它符號 表示類方法……三種方法都可以被類的實例調用,而且看起來一模一樣,如上例的等號左側那樣。這時候就要靠定義時賦予的參數來區分了,像上例等號右側,第一個參數是實例對象,表明此處是個實例方法。)
  • 學了這麼久,你真的了解函數(function)與方法(method)嗎?
    inspect 模塊,提供了一系列的對對象進行類型檢查的函數,其中可以看到 ismethod() 與 isfunction() 函數,就是用來判斷什麼是方法(method),什麼是函數(funtion)的...
  • python經典筆試、面試題
    一、高德軟體有限公司python試題及答案1. 在python中, list, tuple, dict, set有什麼區別, 主要應用在什麼樣的場景?定義:靜態函數(@staticmethod) : 即靜態方法,主要處理與這個類的邏輯關聯,它是不可以訪問實例變量或類變量的。類函數(@classmethod): 即類方法, 只能訪問類變量,不能訪問實例變量 , 類方法通過@classmethod裝飾器實現。
  • 全面深入理解 Python 類與對象
    -中.html類屬性和實例屬性查找順序屬性:在內部定義的方法或者變量使用代碼:class magic: a = 'langzi' def __init__(self,x): self.x = x def run(self): return