python中的靜態函數的用法(python類函數和靜態函數)

本文目錄一覽:

python的靜態方法有什麼用

ython的靜態方法和類成員方法都可以被類或實例訪問,兩者概念不容易理清,但還是有區別的:

1)靜態方法無需傳入self參數,類成員方法需傳入代表本類的cls參數;

2)從第1條,靜態方法是無法訪問實例變量的,而類成員方法也同樣無法訪問實例變量,但可以訪問類變量;

3)靜態方法有點像函數工具庫的作用,而類成員方法則更接近類似Java面向對象概念中的靜態方法。

python 裏面有靜態函數嗎

python的類里用@staticmethod的是靜態方法,@classmethod的是類方法,如下

class Person(object):

    person_list = []

    def __init__(self, name, age):

        self.name = name

        self.age = age

        self.person_list.append(self)

    @classmethod

    def one_year_later(cls):

        for p in cls.person_list:

            p.age += 1

    @staticmethod

    def born_one_boby(name):

        return Person(name, 0)

    def __repr__(self):

        return ‘Person name:%s, age:%s’ % (self.name, self.age)

if __name__ == ‘__main__’:

    petter =  Person(‘Petter’,23)

    merry = Person(‘Merry’,21)

    print(petter) # Person name:Petter, age:23

    print(merry)  #  Person name:Merry, age:21

    Person.one_year_later()

    print(petter)  #  Person name:Petter, age:24

    print(merry)  #  Person name:Merry, age:22

    baby = merry.born_one_boby(‘Tom’)

    print(Person.person_list) #  [Person name:Petter, age:24, Person name:Merry, age:22, Person name:Tom, age:0]

如何在Python中使用static,class,abstract方法

方法在Python中是如何工作的

方法就是一個函數,它作為一個類屬性而存在,你可以用如下方式來聲明、訪問一個函數:

Python

1

2

3

4

5

6

7

8

class Pizza(object):

…     def __init__(self, size):

…         self.size = size

…     def get_size(self):

…         return self.size

Pizza.get_size

unbound method Pizza.get_size

Python在告訴你,屬性_get_size是類Pizza的一個未綁定方法。這是什麼意思呢?很快我們就會知道答案:

Python

1

2

3

4

Pizza.get_size()

Traceback (most recent call last):

File “stdin”, line 1, in module

TypeError: unbound method get_size() must be called with Pizza instance as first argument (got nothing instead)

我們不能這麼調用,因為它還沒有綁定到Pizza類的任何實例上,它需要一個實例作為第一個參數傳遞進去(Python2必須是該類的實例,Python3中可以是任何東西),嘗試一下:

Python

1

2

Pizza.get_size(Pizza(42))

42

太棒了,現在用一個實例作為它的的第一個參數來調用,整個世界都清靜了,如果我說這種調用方式還不是最方便的,你也會這麼認為的;沒錯,現在每次調用這個方法的時候我們都不得不引用這個類,如果不知道哪個類是我們的對象,長期看來這種方式是行不通的。

那麼Python為我們做了什麼呢,它綁定了所有來自類_Pizza的方法以及該類的任何一個實例的方法。也就意味着現在屬性get_size是Pizza的一個實例對象的綁定方法,這個方法的第一個參數就是該實例本身。

Python

1

2

3

4

Pizza(42).get_size

bound method Pizza.get_size of __main__.Pizza object at 0x7f3138827910

Pizza(42).get_size()

42

和我們預期的一樣,現在不再需要提供任何參數給_get_size,因為它已經是綁定的,它的self參數會自動地設置給Pizza實例,下面代碼是最好的證明:

Python

1

2

3

m = Pizza(42).get_size

m()

42

更有甚者,你都沒必要使用持有Pizza對象的引用了,因為該方法已經綁定到了這個對象,所以這個方法對它自己來說是已經足夠了。

也許,如果你想知道這個綁定的方法是綁定在哪個對象上,下面這種手段就能得知:

Python

1

2

3

4

5

6

7

m = Pizza(42).get_size

m.__self__

__main__.Pizza object at 0x7f3138827910

# You could guess, look at this:

m == m.__self__.get_size

True

顯然,該對象仍然有一個引用存在,只要你願意你還是可以把它找回來。

在Python3中,依附在類上的函數不再當作是未綁定的方法,而是把它當作一個簡單地函數,如果有必要它會綁定到一個對象身上去,原則依然和Python2保持一致,但是模塊更簡潔:

Python

1

2

3

4

5

6

7

8

class Pizza(object):

…     def __init__(self, size):

…         self.size = size

…     def get_size(self):

…         return self.size

Pizza.get_size

function Pizza.get_size at 0x7f307f984dd0

靜態方法

靜態方法是一類特殊的方法,有時你可能需要寫一個屬於這個類的方法,但是這些代碼完全不會使用到實例對象本身,例如:

Python

1

2

3

4

5

6

7

class Pizza(object):

@staticmethod

def mix_ingredients(x, y):

return x + y

def cook(self):

return self.mix_ingredients(self.cheese, self.vegetables)

這個例子中,如果把_mix_ingredients作為非靜態方法同樣可以運行,但是它要提供self參數,而這個參數在方法中根本不會被使用到。這裡的@staticmethod裝飾器可以給我們帶來一些好處:

Python不再需要為Pizza對象實例初始化一個綁定方法,綁定方法同樣是對象,但是創建他們需要成本,而靜態方法就可以避免這些。

Python

1

2

3

4

5

6

   

Pizza().cook is Pizza().cook

False

Pizza().mix_ingredients is Pizza.mix_ingredients

True

Pizza().mix_ingredients is Pizza().mix_ingredients

True

   

可讀性更好的代碼,看到@staticmethod我們就知道這個方法並不需要依賴對象本身的狀態。

可以在子類中被覆蓋,如果是把mix_ingredients作為模塊的頂層函數,那麼繼承自Pizza的子類就沒法改變pizza的mix_ingredients了如果不覆蓋cook的話。

類方法

話雖如此,什麼是類方法呢?類方法不是綁定到對象上,而是綁定在類上的方法。

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

   

class Pizza(object):

…     radius = 42

…     @classmethod

…     def get_radius(cls):

…         return cls.radius

Pizza.get_radius

bound method type.get_radius of class ‘__main__.Pizza’

Pizza().get_radius

bound method type.get_radius of class ‘__main__.Pizza’

Pizza.get_radius is Pizza().get_radius

True

Pizza.get_radius()

42

   

無論你用哪種方式訪問這個方法,它總是綁定到了這個類身上,它的第一個參數是這個類本身(記住:類也是對象)。

什麼時候使用這種方法呢?類方法通常在以下兩種場景是非常有用的:

工廠方法:它用於創建類的實例,例如一些預處理。如果使用@staticmethod代替,那我們不得不硬編碼Pizza類名在函數中,這使得任何繼承Pizza的類都不能使用我們這個工廠方法給它自己用。

Python

1

2

3

4

5

6

7

   

class Pizza(object):

def __init__(self, ingredients):

self.ingredients = ingredients

@classmethod

def from_fridge(cls, fridge):

return cls(fridge.get_cheese() + fridge.get_vegetables())

   

調用靜態類:如果你把一個靜態方法拆分成多個靜態方法,除非你使用類方法,否則你還是得硬編碼類名。使用這種方式聲明方法,Pizza類名明永遠都不會在被直接引用,繼承和方法覆蓋都可以完美的工作。

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

   

class Pizza(object):

def __init__(self, radius, height):

self.radius = radius

self.height = height

@staticmethod

def compute_area(radius):

return math.pi * (radius ** 2)

@classmethod

def compute_volume(cls, height, radius):

return height * cls.compute_area(radius)

def get_volume(self):

return self.compute_volume(self.height, self.radius)

   

抽象方法

抽象方法是定義在基類中的一種方法,它沒有提供任何實現,類似於Java中接口(Interface)裏面的方法。

在Python中實現抽象方法最簡單地方式是:

Python

1

2

3

   

class Pizza(object):

def get_radius(self):

raise NotImplementedError

   

任何繼承自_Pizza的類必須覆蓋實現方法get_radius,否則會拋出異常。

這種抽象方法的實現有它的弊端,如果你寫一個類繼承Pizza,但是忘記實現get_radius,異常只有在你真正使用的時候才會拋出來。

Python

1

2

3

4

5

6

7

   

Pizza()

__main__.Pizza object at 0x7fb747353d90

Pizza().get_radius()

Traceback (most recent call last):

File “stdin”, line 1, in module

File “stdin”, line 3, in get_radius

NotImplementedError

   

還有一種方式可以讓錯誤更早的觸發,使用Python提供的abc模塊,對象被初始化之後就可以拋出異常:

Python

1

2

3

4

5

6

7

8

   

import abc

class BasePizza(object):

__metaclass__  = abc.ABCMeta

@abc.abstractmethod

def get_radius(self):

“””Method that should do something.”””

   

使用abc後,當你嘗試初始化BasePizza或者任何子類的時候立馬就會得到一個TypeError,而無需等到真正調用get_radius的時候才發現異常。

Python

1

2

3

4

   

BasePizza()

Traceback (most recent call last):

File “stdin”, line 1, in module

TypeError: Can’t instantiate abstract class BasePizza with abstract methods get_radius

   

混合靜態方法、類方法、抽象方法

當你開始構建類和繼承結構時,混合使用這些裝飾器的時候到了,所以這裡列出了一些技巧。

記住,聲明一個抽象的方法,不會固定方法的原型,這就意味着雖然你必須實現它,但是我可以用任何參數列表來實現:

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

   

import abc

class BasePizza(object):

__metaclass__  = abc.ABCMeta

@abc.abstractmethod

def get_ingredients(self):

“””Returns the ingredient list.”””

class Calzone(BasePizza):

def get_ingredients(self, with_egg=False):

egg = Egg() if with_egg else None

return self.ingredients + egg

   

這樣是允許的,因為Calzone滿足BasePizza對象所定義的接口需求。同樣我們也可以用一個類方法或靜態方法來實現:

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

   

import abc

class BasePizza(object):

__metaclass__  = abc.ABCMeta

@abc.abstractmethod

def get_ingredients(self):

“””Returns the ingredient list.”””

class DietPizza(BasePizza):

@staticmethod

def get_ingredients():

return None

   

這同樣是正確的,因為它遵循抽象類BasePizza設定的契約。事實上get_ingredients方法並不需要知道返回結果是什麼,結果是實現細節,不是契約條件。

因此,你不能強制抽象方法的實現是一個常規方法、或者是類方法還是靜態方法,也沒什麼可爭論的。從Python3開始(在Python2中不能如你期待的運行,見issue5867),在abstractmethod方法上面使用@staticmethod和@classmethod裝飾器成為可能。

Python

1

2

3

4

5

6

7

8

9

10

11

12

   

import abc

class BasePizza(object):

__metaclass__  = abc.ABCMeta

ingredient = [‘cheese’]

@classmethod

@abc.abstractmethod

def get_ingredients(cls):

“””Returns the ingredient list.”””

return cls.ingredients

   

別誤會了,如果你認為它會強制子類作為一個類方法來實現get_ingredients那你就錯了,它僅僅表示你實現的get_ingredients在BasePizza中是一個類方法。

可以在抽象方法中做代碼的實現?沒錯,Python與Java接口中的方法相反,你可以在抽象方法編寫實現代碼通過super()來調用它。(譯註:在Java8中,接口也提供的默認方法,允許在接口中寫方法的實現)

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

   

import abc

class BasePizza(object):

__metaclass__  = abc.ABCMeta

default_ingredients = [‘cheese’]

@classmethod

@abc.abstractmethod

def get_ingredients(cls):

“””Returns the ingredient list.”””

return cls.default_ingredients

class DietPizza(BasePizza):

def get_ingredients(self):

return [‘egg’] + super(DietPizza, self).get_ingredients()

   

這個例子中,你構建的每個pizza都通過繼承BasePizza的方式,你不得不覆蓋get_ingredients方法,但是能夠使用默認機制通過super()來獲取ingredient列表。

打賞支持我翻譯更多好文章,謝謝!

Python中靜態方法和類方法的區別

一、先是在語法上面的區別:

1、靜態方法不需要傳入self參數,類成員方法需要傳入代表本類的cls參數;

2、靜態方法是無妨訪問實例變量和類變量的,類成員方法無法訪問實例變量但是可以訪問類變量

二、使用的區別:

由於靜態方法無法訪問類屬性,實例屬性,相當於一個相對獨立的方法,跟類其實並沒有什麼關係。這樣說來,靜態方法就是在類的作用域里的函數而已。

原創文章,作者:FWFYT,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/315616.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
FWFYT的頭像FWFYT
上一篇 2025-01-09 12:13
下一篇 2025-01-09 12:13

相關推薦

  • Python周杰倫代碼用法介紹

    本文將從多個方面對Python周杰倫代碼進行詳細的闡述。 一、代碼介紹 from urllib.request import urlopen from bs4 import Bea…

    編程 2025-04-29
  • Python計算陽曆日期對應周幾

    本文介紹如何通過Python計算任意陽曆日期對應周幾。 一、獲取日期 獲取日期可以通過Python內置的模塊datetime實現,示例代碼如下: from datetime imp…

    編程 2025-04-29
  • 如何查看Anaconda中Python路徑

    對Anaconda中Python路徑即conda環境的查看進行詳細的闡述。 一、使用命令行查看 1、在Windows系統中,可以使用命令提示符(cmd)或者Anaconda Pro…

    編程 2025-04-29
  • Python中引入上一級目錄中函數

    Python中經常需要調用其他文件夾中的模塊或函數,其中一個常見的操作是引入上一級目錄中的函數。在此,我們將從多個角度詳細解釋如何在Python中引入上一級目錄的函數。 一、加入環…

    編程 2025-04-29
  • Python列表中負數的個數

    Python列表是一個有序的集合,可以存儲多個不同類型的元素。而負數是指小於0的整數。在Python列表中,我們想要找到負數的個數,可以通過以下幾個方面進行實現。 一、使用循環遍歷…

    編程 2025-04-29
  • Python清華鏡像下載

    Python清華鏡像是一個高質量的Python開發資源鏡像站,提供了Python及其相關的開發工具、框架和文檔的下載服務。本文將從以下幾個方面對Python清華鏡像下載進行詳細的闡…

    編程 2025-04-29
  • 蝴蝶優化算法Python版

    蝴蝶優化算法是一種基於仿生學的優化算法,模仿自然界中的蝴蝶進行搜索。它可以應用於多個領域的優化問題,包括數學優化、工程問題、機器學習等。本文將從多個方面對蝴蝶優化算法Python版…

    編程 2025-04-29
  • Python字典去重複工具

    使用Python語言編寫字典去重複工具,可幫助用戶快速去重複。 一、字典去重複工具的需求 在使用Python編寫程序時,我們經常需要處理數據文件,其中包含了大量的重複數據。為了方便…

    編程 2025-04-29
  • Python程序需要編譯才能執行

    Python 被廣泛應用於數據分析、人工智能、科學計算等領域,它的靈活性和簡單易學的性質使得越來越多的人喜歡使用 Python 進行編程。然而,在 Python 中程序執行的方式不…

    編程 2025-04-29
  • python強行終止程序快捷鍵

    本文將從多個方面對python強行終止程序快捷鍵進行詳細闡述,並提供相應代碼示例。 一、Ctrl+C快捷鍵 Ctrl+C快捷鍵是在終端中經常用來強行終止運行的程序。當你在終端中運行…

    編程 2025-04-29

發表回復

登錄後才能評論