1. 如何在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 <mole>
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 <mole>
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 <mole>
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列表。
打賞支持我翻譯更多好文章,謝謝!
2. 如何使用靜態方法,類方法或者抽象方法
方法是作為類的屬性(attribute)存儲的函數。你可以以下面的方式聲明和獲取函數:
>>> 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告訴你的是,類Pizza的屬性get_size是一個非綁定的方法。這又指什麼呢?很快我們就會知道,試著調用一下:
>>> Pizza.get_size()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: unbound method get_size() must be called with Pizza instance as first argument (got nothing instead)
這里我們不能調用這個方法是因為它沒有被綁定到任一Pizza的實例上。一個方法需要一個實例作為它第一個參數(在Python 2中它必須是對應類的實例;在Python 3中可以是任何東西)。我們現在試試:
>>> Pizza.get_size(Pizza(42))
42
現在可以了!我們試用一個實例作為get_size方法的第一個參數調用了它,所以一切變得很美好。但是你很快會同意,這並不是一個很漂亮的調用方法的方式;因為每次我們想調用這個方法都必須使用到類。並且,如果我們不知道對象是哪個類的實例,這種方式就不方便了。
所以,Python為我們准備的是,它將類Pizza的所有的方法綁定到此類的任何實例上。這意味著類Pizza的任意實例的屬性get_size是一個已綁定的方法:第一個參數是實例本身的方法。
>>> Pizza(42).get_size
<bound method Pizza.get_size of <__main__.Pizza object at 0x10314b310>>
>>> Pizza(42).get_size()
42
如我們預期,現在不需要提供任何參數給get_size,因為它已經被綁定(bound),它的self參數是自動地設為Pizza類的實例。下面是一個更好的證明:
>>> m = Pizza(42).get_size
>>> m
<bound method Pizza.get_size of <__main__.Pizza object at 0x10314b350>>
>>> m()
42
因此,你甚至不要保存一個對Pizza對象的飲用。它的方法已經被綁定在對象上,所以這個方法已經足夠。
但是如何知道已綁定的方法被綁定在哪個對象上?技巧如下:
>>> m = Pizza(42).get_size
>>> m.__self__
<__main__.Pizza object at 0x10314b390>
>>> m == m.__self__.get_size
True
易見,我們仍然保存著一個對對象的引用,當需要知道時也可以找到。
在Python 3中,歸屬於一個類的函數不再被看成未綁定方法(unbound method),但是作為一個簡單的函數,如果要求可以綁定在對象上。所以,在Python 3中原理是一樣的,模型被簡化了。
>>> 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>
靜態方法
靜態方法是一類特殊的方法。有時,我們需要寫屬於一個類的方法,但是不需要用到對象本身。例如:
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作為一個非靜態的方法也可以work,但是給它一個self的參數將沒有任何作用。這兒的decorator@staticmethod帶來一些特別的東西:
>>> Pizza().cook is Pizza().cook
False
>>> Pizza().mix_ingredients is Pizza().mix_ingredients
True
>>> Pizza().mix_ingredients is Pizza.mix_ingredients
True
>>> Pizza()
<__main__.Pizza object at 0x10314b410>
>>> Pizza()
<__main__.Pizza object at 0x10314b510>
>>>
Python不需要對每個實例化的Pizza對象實例化一個綁定的方法。綁定的方法同樣是對象,創建它們需要付出代價。這里的靜態方法避免了這樣的情況:
降低了閱讀代碼的難度:看到@staticmethod便知道這個方法不依賴與對象本身的狀態;
允許我們在子類中重載mix_ingredients方法。如果我們使用在模塊最頂層定義的函數mix_ingredients,一個繼承自Pizza的類若不重載cook,可能不可以改變混合成份(mix_ingredients)的方式。
類方法
什麼是類方法?類方法是綁定在類而非對象上的方法!
>>> 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
False
>>> Pizza.get_radius()
42
此處有問題。原文中
>>> Pizza.get_radius is Pizza().get_radius
True
還需要check一下。
不管你如何使用這個方法,它總會被綁定在其歸屬的類上,同時它第一個參數是類本身(記住:類同樣是對象)
何時使用這種方法?類方法一般用於下面兩種:
1. 工廠方法,被用來創建一個類的實例,完成一些預處理工作。如果我們使用一個@staticmethod靜態方法,我們可能需要在函數中硬編碼Pizza類的名稱,使得任何繼承自Pizza類的類不能使用我們的工廠用作自己的目的。
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這個名字不需要直接被引用,並且繼承和方法重載將會完美運作。
class Pizza(object):
def __init__(self, radius, height):
self.radius = radius
self.height = height
@staticmethod
def compute_circumference(radius):
return math.pi * (radius ** 2)
@classmethod
def compute_volume(cls, height, radius):
return height * cls.compute_circumference(radius)
def get_volume(self):
return self.compute_volume(self.height, self.radius)
抽象方法
抽象方法在一個基類中定義,但是可能不會有任何的實現。在Java中,這被描述為一個介面的方法。
所以Python中最簡單的抽象方法是:
class Pizza(object):
def get_radius(self):
raise NotImplementedError
任何繼承自Pizza的類將實現和重載get_radius方法,否則會出現異常。這種獨特的實現抽象方法的方式也有其缺點。如果你寫一個繼承自Pizza的類,忘記實現get_radius,錯誤將會在你使用這個方法的時候才會出現。
>>> Pizza()
<__main__.Pizza object at 0x106f381d0>
>>> Pizza().get_radius()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
File "<stdin>", line 3, in get_radius
NotImplementedError
有種提前引起錯誤發生的方法,那就是當對象被實例化時,使用Python提供的abc模塊。
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def get_radius(self):
"""Method that should do something."""
使用abc和它的特類,一旦你試著實例化BasePizza或者其他繼承自它的類,就會得到TypeError
>>> BasePizza()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: Can't instantiate abstract class BasePizza with abstract methods get_radius
混合靜態方法、類方法和抽象方法
當我們構建類和繼承關系時,終將會碰到要混合這些方法decorator的情況。下面提幾個tip。
記住聲明一個類為抽象類時,不要冷凍那個方法的prototype。這是指這個方法必須被實現,不過是可以使用任何參數列表來實現。
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類對象定義的介面需求。就是說,我們可以把它當作一個類方法或者靜態方法來實現,例如:
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方法不需要知道對象,這是實現的細節,而非完成需求的評價指標。
因此,你不能強迫抽象方法的實現是正常的方法、類方法或者靜態方法,並且可以這樣說,你不能。從Python 3開始(這就不會像在Python 2中那樣work了,見issue5867),現在可以在@abstractmethod之上使用@staticmethod和@classmethod了。
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()調用:
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()
文/Not_GOD(簡書作者)
原文鏈接:http://www.jianshu.com/p/880d6a3ffdde
著作權歸作者所有,轉載請聯系作者獲得授權,並標注「簡書作者」。
3. Python有設計模式么
Python設計模式主要分為三大類:創建型模式、結構型模式、行為型模式;三 大類中又被細分為23種設計模式,以下這幾種是最常見的。
單例模式:是一種常用的軟體設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你希望在整個系統中,某個類只能出現一個是實例時,單例對象就能派上用場。單例對象的要點有三個:一是某個類只能有一個實例;二是它必須自行創建整個實例,三是它必須自行向整個系統提供這個實例。
工廠模式:提供一個創建對象的介面,不像客戶端暴露創建對象的過程,使用一個公共的介面來創建對象,可以分為三種:簡單工廠、工廠方法、抽象工廠。一個類的行為或其演算法可以在運行時更改,這種類型的設計模式屬於行為型模式。
策略模式:是常見的設計模式之一,它是指對一系列的演算法定義,並將每一個演算法封裝起來,而且使它們還可以相互替換。策略模式讓演算法獨立於使用它的客戶而獨立變化。換句話來講,就是針對一個問題而定義出一個解決的模板,這個模板就是具體的策略,每個策略都是按照這個模板進行的,這種情況下我們有新的策略時就可以直接按照模板來寫,而不會影響之前已經定義好的策略。
門面模式:門面模式也被稱作外觀模式。定義如下:要求一個子系統的外部與其內部的通信必須通過一個統一的對象進行。門面模式提供一個高層次的介面,使得子系統更易於使用。門面模式注重統一的對象,也就是提供一個訪問子系統的介面。門面模式與模板模式有相似的地方,都是對一些需要重復方法的封裝。但本質上是不同的,模板模式是對類本身的方法的封裝,其被封裝的方法也可以單獨使用;門面模式,是對子系統的封裝,其被封裝的介面理論上是不會被單獨提出來使用的。
4. 什麼是工廠函數Python 中工廠函數怎麼理解
看了半天答案,說了半天等於沒說.
見python核心編程:工廠函數看上去有點像函數,實質上他們是類,當你調用它們時,實際上是生成了該類型的一個實例,就像工廠生產貨物一樣.
5. python常用的幾種設計模式是什麼
python常用的幾種設計模式有:1、單例模式,確保某一個類只有一個實例;2、工廠模式,使用一個公共的介面來創建對象;3、策略模式,隨著策略對象改變內容;4、門面模式,對子系統的封裝,使得封裝介面不會被單獨提出來。
什麼是設計模式?
設計模式是一套被反復使用,多數人知道,經過分類編目的代碼設計經驗總結。
使用設計模式是為了提高代碼可重用性,可閱讀性,和可靠性。
你說理解的設計模式有幾種?
設計模式又可分為三種:創建型(單例模式)、(工廠模式),結構型,行為型(策略模式)
單例模式以及應用場景:
(1)確保某一個類只有一個實例,而且自行實例化並向整個系統提供這個實例,這個類稱為單例類,單例模式是一種對象創建型模式。Windows的Task Manager(任務管理器)、Recycle Bin(回收站)、網站計數器
(2)單例模式應用的場景一般發現在以下條件下:
資源共享的情況下,避免由於資源操作時導致的性能或損耗等。如上述中的日誌文件,應用配置。控制資源的情況下,方便資源之間的互相通信。如線程池等
要點:一是某個類只能有一個實例;二是它必須自行創建這個實例;三是它必須自行向整個系統提供這個實例。
工廠模式:
提供一個創建對象的介面,不像客戶端暴露創建對象的過程,而是使用一個公共的介面來創建對象。
可以分為三種:簡單工廠 工廠方法 抽象工廠
一個類的行為或其演算法可以在運行時更改。這種類型的設計模式屬於行為型模式。
策略模式:
在策略模式中,我們創建表示各種策略的對象和一個行為隨著策略對象改變而改變的 context 對象。策略對象改變 context 對象的執行演算法。
要點:把一個個策略,也就是演算法封裝成一個一個類,任意的替換
解決的問題:避免多個if....else帶來的復雜
使用場景:系統中需要動態的在集中演算法中動態的選擇一種,
門面模式:
門面模式也叫外觀模式,定義如下:要求一個子系統的外部與其內部的通信必須通過一個統一的對象進行。門面模式提供一個高層次的介面,使得子系統更易於使用。門面模式注重「統一的對象」,也就是提供一個訪問子系統的介面。門面模式與之前說過的模板模式有類似的地方,都是對一些需要重復方法的封裝。但從本質上來說,是不同的。模板模式是對類本身的方法的封裝,其被封裝的方法也可以單獨使用;而門面模式,是對子系統的封裝,其被封裝的介面理論上是不會被單獨提出來用的。
一個對象有很多行為,如果么有選擇合適的設計模式,這些行為就需要用多重的條件判斷來實現演算法的切換,增加了代碼的復雜度。
推薦課程:Python面對對象(Corey Schafer)
6. 請問下,python中的工廠函數和內置函數,他們兩個到底有什麼區別和聯系啊
定義不同啊。內置函數應該是不需要import就可以使用的函數。 工廠不是個函數,是個類。 工廠類這要從「設計模式」說起,工廠模式。
但是用起來,至少在python中,工廠模式的函數或者是類,與原來的用法沒有什麼區別。 只是對於程序員來說,擴展更容易些。 目前就沒有感覺差別。
這些「基本」「內建」之類的名詞可以不用學。 你知道會用就可以了。程序是用來用的。不是用來教學或者是顯擺的。學這么多名詞有時候是個負擔,意義不大。
7. python什麼是設計模式
Python軟體開發中引入設計模式是由生活中的一些實例啟發而來的。例如,有2個小朋友Alice和Jack,去麥當勞點餐。Alice不了解麥當勞的套餐模式,於是想了一下,跟服務員說:「我要一個麥辣雞腿堡、一個薯條和一杯可樂」。而Jack經常吃麥當勞,他也想點和Alice一樣的餐品。Jack發現其實Alice點的就是麥當勞的A套餐,於是他直接和服務員說:「給我一個A套餐」。
從上面的事例中可以看出,Jack的點餐效率高,因為Jack和服務員都了解麥當勞的套餐模式,溝通起來效率自然就高。那麼在這個生活案例中,創建套餐是提高點餐效率的可重用解決方案。它會根據客戶的需求和餐品的被點頻次制定出符合不同人群的套餐。套餐可以重復被更多的人去點,因此大大提高了顧客與服務員之間的溝通效率。
同理,在軟體開發世界裡,本來沒有設計模式的,用的人多了,也便總結出了設計模式。這就是設計模式的由來。設計模式針對同一情境,眾多軟體開發人員經過長時間總結,便得到了最佳可重用解決方案。這個可重用解決方案解決了軟體開發過程中常見的問題,擁有固定的術語,因此交流起來就方便了很多。
綜上,設計模式是軟體開發過程中共性問題的可重用解決方案。設計模式的內涵第一是一套被反復使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。第二是用來解決共性問題。設計模式的外延有:單例模式、工廠模式、適配器模式、代理模式等。據悉,現用的設計模式有24種,隨著時代的發展,軟體編程可能會遇到新的場景,設計模式會越來越豐富。
先看一個設計模式中最基本的單例模式的例子。Windows裡面的任務管理器就是個典型的單例模式軟體。這是因為Windows任務管理器只能打開一個,就算用戶重復打開,也只能獲得一個實例,這不同於word等軟體可以打開多個實例。其中的原因就是如果有2個窗口同時都能結束某進程,這就會造成在窗口A中某進程結束了,在窗口B中該進程還保留的;同理反過來,某進程在窗口B中結束了,而在窗口A中還保留著。這樣就會造成沖突,系統崩潰。Windows裡面的任務管理器符合單例模式,保證一個類僅有一個實例的設計模式。
8. Python設計模式之抽象工廠模式
Python設計模式之抽象工廠模式
這篇文章主要為大家詳細介紹了Python設計模式之抽象工廠模式,感興趣的小夥伴們可以參考一下
python面向對象編程入門,我們需要不斷學習進步
"""抽象工廠模式的實現"""
import random
class PetShop:
"""寵物商店"""
def __init__(self, animal_factory=None):
"""寵物工廠是我們的抽象工廠。我們可以隨意設置。"""
self.pet_factory = animal_factory
def show_pet(self):
"""使用抽象工廠創建並顯示一個寵物"""
pet = self.pet_factory.get_pet()
print("我們有一個可愛的 {}".format(pet))
print("它說 {}".format(pet.speak()))
print("我們還有 {}".format(self.pet_factory.get_food()))
# 工廠生產的事物
class Dog:
def speak(self):
return "汪"
def __str__(self):
return "Dog"
class Cat:
def speak(self):
return "喵"
def __str__(self):
return "Cat"
# Factory classes
class DogFactory:
def get_pet(self):
return Dog()
def get_food(self):
return "狗食"
class CatFactory:
def get_pet(self):
return Cat()
def get_food(self):
return "貓糧"
# 隨機創建合適的工廠
def get_factory():
"""讓我們動起來!"""
return random.choice([DogFactory, CatFactory])()
# 多個工廠顯示寵物
if __name__ == "__main__":
for i in range(4):
shop = PetShop(get_factory())
shop.show_pet()
print("=" * 20)
以上就是本文的全部內容,希望對大家的學習有所幫助