Python 設計模式 - 快速指南



Python 設計模式 - 簡介

設計模式用於表示開發人員建立軟體或 Web 應用程式時使用的模式。這些模式是根據需求分析選擇的。這些模式描述了問題的解決方案、何時何地應用該解決方案以及實施的後果。

設計模式的結構

設計模式的文件以一種更關注所用技術及其使用方式的方式維護。下圖解釋了設計模式文件的基本結構。

Design Pattern

模式名稱

它以簡短有效的方式描述了模式。

意圖/動機

它描述了模式的作用。

適用性

它描述了模式適用的情況列表。

參與者和後果

參與者包括參與設計模式的類和物件,以及模式存在的一系列後果。

為什麼選擇 Python?

Python 是一種開源指令碼語言。它擁有支援各種設計模式的庫。Python 的語法易於理解,並使用英語關鍵字。

Python 提供對以下列出的設計模式的支援。這些設計模式將在本教程中使用 -

  • 模型-檢視-控制器模式
  • 單例模式
  • 工廠模式
  • 建造者模式
  • 原型模式
  • 外觀模式
  • 命令模式
  • 介面卡模式
  • 原型模式
  • 裝飾器模式
  • 代理模式
  • 責任鏈模式
  • 觀察者模式
  • 狀態模式
  • 策略模式
  • 模板模式
  • 享元模式
  • 抽象工廠模式
  • 面向物件模式

使用設計模式的好處

以下是設計模式的不同好處 -

  • 模式為開發人員提供了針對指定問題的經過驗證的解決方案的選擇。

  • 所有設計模式都是語言中立的。

  • 模式有助於實現溝通和維護良好的文件。

  • 它包含一項成就記錄,以減少專案的技術風險。

  • 設計模式使用起來非常靈活且易於理解。

Python 設計模式 - 要點

Python 是一種開源指令碼語言,它是高階的、解釋型的、互動式的和麵向物件的。它被設計成高度可讀的。Python 語言的語法易於理解,並且經常使用英語關鍵字。

Python 語言的特性

在本節中,我們將學習 Python 語言的不同特性。

解釋型

Python 在執行時使用直譯器進行處理。在執行之前不需要編譯程式。它類似於 PERL 和 PHP。

面向物件

Python 遵循面向物件風格和設計模式。它包括類定義,具有封裝、多型等各種特性。

可移植性

在 Windows 作業系統中編寫的 Python 程式碼可以在 Mac 作業系統中使用。程式碼可以根據需要重複使用和移植。

易於編碼

Python 語法易於理解和編碼。任何開發人員都可以在幾個小時內理解 Python 的語法。Python 可以被描述為“程式設計師友好型”

可擴充套件性

如果需要,使用者也可以用 C 語言編寫一些 Python 程式碼。也可以將 python 程式碼放入不同語言(如 C++)的原始碼中。這使得 Python 成為一種可擴充套件的語言。

要點

請考慮以下與 Python 程式語言相關的要點 -

  • 它包括函式式和結構化程式設計方法以及面向物件程式設計方法。

  • 它可以用作指令碼語言或程式語言。

  • 它包括自動垃圾回收。

  • 它包括高階動態資料型別,並支援各種動態型別檢查。

  • Python 包括與 C、C++ 和 Java 等語言整合的特性。

如何在您的系統中下載 python 語言?

要在您的系統中下載 Python 語言,請訪問以下連結 -

https://python.club.tw/downloads/

Python Language

它包括適用於各種作業系統(如 Windows、MacOS 和 Linux 發行版)的軟體包。

Python 中的重要工具

在本節中,我們將簡要了解 Python 中的一些重要工具。

Python 字串

字串的基本宣告如下 -

str = 'Hello World!'

Python 列表

python 的列表可以宣告為用逗號分隔的複合資料型別,並用方括號([])括起來。

list = [ 'abcd', 786 , 2.23, 'john', 70.2 ]
tinylist = [123, 'john']

Python 元組

元組是 Python 的動態資料型別,它包含用逗號分隔的多個值。元組用括號括起來。

tinytuple = (123, 'john')

Python 字典

Python 字典是一種雜湊表。字典鍵幾乎可以是 Python 的任何資料型別。資料型別通常是數字或字串。

tinydict = {'name': 'omkar','code':6734, 'dept': 'sales'}

構成 Python 中的設計模式是什麼?

Python 透過以下引數幫助構成設計模式 -

  • 模式名稱
  • 意圖
  • 別名
  • 動機
  • 問題
  • 解決方案
  • 結構
  • 參與者
  • 約束
  • 示例程式碼

模型-檢視-控制器模式

模型-檢視-控制器是最常用的設計模式。開發人員發現此設計模式易於實現。

以下是模型-檢視-控制器的基本架構 -

Architecture

現在讓我們看看結構是如何工作的。

模型

它包含純應用程式邏輯,與資料庫互動。它包含所有資訊以將資料呈現給終端使用者。

檢視

視圖表示與終端使用者互動的 HTML 檔案。它將模型的資料呈現給使用者。

控制器

它充當檢視和模型之間的中介。它偵聽檢視觸發的事件並查詢模型以獲取相同的資訊。

Python 程式碼

讓我們考慮一個名為“Person”的基本物件並建立一個 MVC 設計模式。

Model.py

import json

class Person(object):
   def __init__(self, first_name = None, last_name = None):
      self.first_name = first_name
      self.last_name = last_name
   #returns Person name, ex: John Doe
   def name(self):
      return ("%s %s" % (self.first_name,self.last_name))
		
   @classmethod
   #returns all people inside db.txt as list of Person objects
   def getAll(self):
      database = open('db.txt', 'r')
      result = []
      json_list = json.loads(database.read())
      for item in json_list:
         item = json.loads(item)
         person = Person(item['first_name'], item['last_name'])
         result.append(person)
      return result

它呼叫一個方法,該方法獲取資料庫中 Person 表的所有記錄。這些記錄以 JSON 格式呈現。

檢視

它顯示模型中獲取的所有記錄。檢視從不與模型互動;控制器執行此工作(與模型和檢視通訊)。

from model import Person
def showAllView(list):
   print 'In our db we have %i users. Here they are:' % len(list)
   for item in list:
      print item.name()
def startView():
   print 'MVC - the simplest example'
   print 'Do you want to see everyone in my db?[y/n]'
def endView():
   print 'Goodbye!'

控制器

控制器透過getAll()方法與模型互動,該方法獲取顯示給終端使用者的所有記錄。

from model import Person
import view

def showAll():
   #gets list of all Person objects
   people_in_db = Person.getAll()
   #calls view
   return view.showAllView(people_in_db)

def start():
   view.startView()
   input = raw_input()
   if input == 'y':
      return showAll()
   else:
      return view.endView()

if __name__ == "__main__":
   #running controller function
   start()

Python 設計模式 - 單例模式

此模式限制將類的例項化限制為一個物件。它是一種建立型模式,僅涉及一個類來建立方法和指定的物件。

它為建立的例項提供了一個全域性訪問點。

Singleton Pattern

如何實現單例類?

以下程式演示了單例類的實現,其中它多次列印建立的例項。

class Singleton:
   __instance = None
   @staticmethod 
   def getInstance():
      """ Static access method. """
      if Singleton.__instance == None:
         Singleton()
      return Singleton.__instance
   def __init__(self):
      """ Virtually private constructor. """
      if Singleton.__instance != None:
         raise Exception("This class is a singleton!")
      else:
         Singleton.__instance = self
s = Singleton()
print s

s = Singleton.getInstance()
print s

s = Singleton.getInstance()
print s

輸出

上述程式生成以下輸出 -

Implementation of Singleton

建立的例項數量相同,輸出中列出的物件之間沒有差異。

Python 設計模式 - 工廠模式

工廠模式屬於建立型模式類別。它提供了一種建立物件的最佳方式。在工廠模式中,物件是在不向客戶端公開邏輯的情況下建立的,並使用通用介面引用新建立的物件。

工廠模式在 Python 中使用工廠方法實現。當用戶呼叫一個方法,例如我們傳入一個字串並將返回值作為新物件時,透過工廠方法實現。工廠方法中使用的物件型別由透過方法傳遞的字串確定。

在下面的示例中,每個方法都包含一個作為引數的物件,該物件透過工廠方法實現。

如何實現工廠模式?

現在讓我們看看如何實現工廠模式。

class Button(object):
   html = ""
   def get_html(self):
      return self.html

class Image(Button):
   html = "<img></img>"

class Input(Button):
   html = "<input></input>"

class Flash(Button):
   html = "<obj></obj>"

class ButtonFactory():
   def create_button(self, typ):
      targetclass = typ.capitalize()
      return globals()[targetclass]()

button_obj = ButtonFactory()
button = ['image', 'input', 'flash']
for b in button:
   print button_obj.create_button(b).get_html()

button 類有助於建立 html 標籤和關聯的 html 頁面。客戶端將無法訪問程式碼邏輯,並且輸出表示 html 頁面的建立。

輸出

Factory Pattern

說明

python 程式碼包含 html 標籤的邏輯,該邏輯指定了值。終端使用者可以檢視 Python 程式碼建立的 HTML 檔案。

Python 設計模式 - 建造者模式

建造者模式是一種獨特的模式,它幫助使用簡單物件構建複雜物件,並使用演算法方法。這種設計模式屬於建立型模式。在這種設計模式中,一個構建器類以分步的方式構建最終物件。這個構建器獨立於其他物件。

建造者模式的優點

  • 它提供了類建立的指定物件的構造和表示之間的清晰分離和唯一層。

  • 它提供了對建立模式的構建過程的更好控制。

  • 它為更改物件的內部表示提供了完美的場景。

如何實現建造者模式?

在本節中,我們將學習如何實現建造者模式。

class Director:
   __builder = None
   
   def setBuilder(self, builder):
      self.__builder = builder
   
   def getCar(self):
      car = Car()
      
      # First goes the body
      body = self.__builder.getBody()
      car.setBody(body)
      
      # Then engine
      engine = self.__builder.getEngine()
      car.setEngine(engine)
      
      # And four wheels
      i = 0
      while i < 4:
         wheel = self.__builder.getWheel()
			car.attachWheel(wheel)
         i += 1
      return car

# The whole product
class Car:
   def __init__(self):
      self.__wheels = list()
      self.__engine = None
      self.__body = None

   def setBody(self, body):
      self.__body = body

   def attachWheel(self, wheel):
      self.__wheels.append(wheel)

   def setEngine(self, engine):
      self.__engine = engine

   def specification(self):
      print "body: %s" % self.__body.shape
      print "engine horsepower: %d" % self.__engine.horsepower
      print "tire size: %d\'" % self.__wheels[0].size

class Builder:
      def getWheel(self): pass
      def getEngine(self): pass
      def getBody(self): pass

class JeepBuilder(Builder):
   
   def getWheel(self):
      wheel = Wheel()
      wheel.size = 22
      return wheel
   
   def getEngine(self):
      engine = Engine()
      engine.horsepower = 400
      return engine
   
   def getBody(self):
      body = Body()
      body.shape = "SUV"
      return body

# Car parts
class Wheel:
   size = None

class Engine:
   horsepower = None

class Body:
   shape = None

def main():
   jeepBuilder = JeepBuilder() # initializing the class
   
   director = Director()
   
   # Build Jeep
   print "Jeep"
   director.setBuilder(jeepBuilder)
   jeep = director.getCar()
   jeep.specification()
   print ""

if __name__ == "__main__":
   main()

輸出

上述程式生成以下輸出 -

Builder Pattern

Python 設計模式 - 原型模式

原型設計模式有助於隱藏類建立的例項的複雜性。現有物件的概念將與從頭建立的新物件有所不同。

如果需要,新複製的物件在屬性上可能有一些更改。這種方法節省了產品開發所需的時間和資源。

如何實現原型模式?

現在讓我們看看如何實現原型模式。

import copy

class Prototype:

   _type = None
   _value = None

   def clone(self):
      pass

   def getType(self):
      return self._type

   def getValue(self):
      return self._value

class Type1(Prototype):

   def __init__(self, number):
      self._type = "Type1"
      self._value = number

   def clone(self):
      return copy.copy(self)

class Type2(Prototype):

   """ Concrete prototype. """

   def __init__(self, number):
      self._type = "Type2"
      self._value = number

   def clone(self):
      return copy.copy(self)

class ObjectFactory:

   """ Manages prototypes.
   Static factory, that encapsulates prototype
   initialization and then allows instatiation
   of the classes from these prototypes.
   """

   __type1Value1 = None
   __type1Value2 = None
   __type2Value1 = None
   __type2Value2 = None

   @staticmethod
   def initialize():
      ObjectFactory.__type1Value1 = Type1(1)
      ObjectFactory.__type1Value2 = Type1(2)
      ObjectFactory.__type2Value1 = Type2(1)
      ObjectFactory.__type2Value2 = Type2(2)

   @staticmethod
   def getType1Value1():
      return ObjectFactory.__type1Value1.clone()

   @staticmethod
   def getType1Value2():
      return ObjectFactory.__type1Value2.clone()

   @staticmethod
   def getType2Value1():
      return ObjectFactory.__type2Value1.clone()

   @staticmethod
   def getType2Value2():
      return ObjectFactory.__type2Value2.clone()

def main():
   ObjectFactory.initialize()
   
   instance = ObjectFactory.getType1Value1()
   print "%s: %s" % (instance.getType(), instance.getValue())
   
   instance = ObjectFactory.getType1Value2()
   print "%s: %s" % (instance.getType(), instance.getValue())
   
   instance = ObjectFactory.getType2Value1()
   print "%s: %s" % (instance.getType(), instance.getValue())
   
   instance = ObjectFactory.getType2Value2()
   print "%s: %s" % (instance.getType(), instance.getValue())

if __name__ == "__main__":
   main()

輸出

以上程式將生成以下輸出:

Prototype Pattern

輸出有助於使用現有物件建立新物件,並且在上面提到的輸出中清晰可見。

Python 設計模式 - 外觀模式

外觀模式為子系統中的一組介面提供統一的介面。它定義了一個任何子系統都可以使用的更高級別的介面。

外觀類知道哪個子系統負責請求。

如何設計外觀模式?

現在讓我們看看如何設計外觀模式。

class _IgnitionSystem(object):
   
   @staticmethod
   def produce_spark():
      return True

class _Engine(object):

   def __init__(self):
      self.revs_per_minute = 0

   def turnon(self):
      self.revs_per_minute = 2000
   
   def turnoff(self):
      self.revs_per_minute = 0

class _FuelTank(object):
   
   def __init__(self, level=30):
      self._level = level
   
   @property
   def level(self):
      return self._level
   
   @level.setter
	def level(self, level):
      self._level = level

class _DashBoardLight(object):

   def __init__(self, is_on=False):
      self._is_on = is_on

   def __str__(self):
      return self.__class__.__name__

   @property
   def is_on(self):
      return self._is_on
   
   @is_on.setter
   def is_on(self, status):
      self._is_on = status
   
   def status_check(self):
      if self._is_on:
         print("{}: ON".format(str(self)))
      else:
         print("{}: OFF".format(str(self)))

class _HandBrakeLight(_DashBoardLight):
   pass

class _FogLampLight(_DashBoardLight):
   pass

class _Dashboard(object):
   
   def __init__(self):
      self.lights = {"handbreak": _HandBrakeLight(), "fog": _FogLampLight()}
   
   def show(self):
	   for light in self.lights.values():
      light.status_check()

# Facade
class Car(object):
   
   def __init__(self):
      self.ignition_system = _IgnitionSystem()
      self.engine = _Engine()
      self.fuel_tank = _FuelTank()
      self.dashboard = _Dashboard()
   
   @property
   def km_per_litre(self):
      return 17.0
   
   def consume_fuel(self, km):
      litres = min(self.fuel_tank.level, km / self.km_per_litre)
      self.fuel_tank.level -= litres
   
   def start(self):
      print("\nStarting...")
      self.dashboard.show()
      if self.ignition_system.produce_spark():
         self.engine.turnon()
      else:
         print("Can't start. Faulty ignition system")
   
   def has_enough_fuel(self, km, km_per_litre):
      litres_needed = km / km_per_litre
      if self.fuel_tank.level > litres_needed:
         return True
      else:
         return False
	   
      def drive(self, km = 100):
         print("\n")
         if self.engine.revs_per_minute > 0:
            while self.has_enough_fuel(km, self.km_per_litre):
               self.consume_fuel(km)
               print("Drove {}km".format(km))
               print("{:.2f}l of fuel still left".format(self.fuel_tank.level))
         else:
            print("Can't drive. The Engine is turned off!")
         
         def park(self):
            print("\nParking...")
            self.dashboard.lights["handbreak"].is_on = True
            self.dashboard.show()
            self.engine.turnoff()
         
         def switch_fog_lights(self, status):
            print("\nSwitching {} fog lights...".format(status))
            boolean = True if status == "ON" else False
            self.dashboard.lights["fog"].is_on = boolean
            self.dashboard.show()
         
         def fill_up_tank(self):
            print("\nFuel tank filled up!")
            self.fuel_tank.level = 100
				
# the main function is the Client
def main():
   car = Car()
   car.start()
   car.drive()
   car.switch_fog_lights("ON")
   car.switch_fog_lights("OFF")
	car.park()
   car.fill_up_tank()
   car.drive()
   car.start()
   car.drive()

if __name__ == "__main__":
   main()

輸出

上述程式生成以下輸出 -

Facade Pattern

說明

這個程式是根據一個場景設計的。它是啟動汽車或任何駕駛車輛的引擎。如果您觀察程式碼,它包括相關的駕駛、停車和消耗燃料的功能。

Python 設計模式 - 命令模式

命令模式在操作之間添加了一層抽象,幷包含一個呼叫這些操作的物件。

在這種設計模式中,客戶端建立一個命令物件,其中包含要執行的命令列表。建立的命令物件實現特定的介面。

以下是命令模式的基本架構:

Architecture of Command Pattern

如何實現命令模式?

我們現在將看到如何實現該設計模式。

def demo(a,b,c):
   print 'a:',a
   print 'b:',b
   print 'c:',c

class Command:
   def __init__(self, cmd, *args):
      self._cmd=cmd
      self._args=args

   def __call__(self, *args):
      return apply(self._cmd, self._args+args)
cmd = Command(dir,__builtins__)
print cmd()

cmd = Command(demo,1,2)
cmd(3)

輸出

上述程式生成以下輸出 -

Command Pattern

說明

輸出實現了Python語言中列出的所有命令和關鍵字。它列印變數的必要值。

Python 設計模式 - 介面卡模式

介面卡模式充當兩個不相容介面之間的橋樑。這種設計模式屬於結構型模式,因為這種模式結合了兩個獨立介面的功能。

這種模式涉及一個類,負責連線獨立或不相容介面的功能。一個現實生活中的例子可能是讀卡器,它充當儲存卡和筆記型電腦之間的介面卡。您將儲存卡插入讀卡器,然後將讀卡器插入筆記型電腦,以便可以透過筆記型電腦讀取儲存卡。

介面卡設計模式有助於使類一起工作。它根據需求將類的介面轉換為另一個介面。該模式包括一個規範多型性,它命名一個名稱和多個形式。比如一個形狀類,可以根據收集到的需求使用。

介面卡模式有兩種型別:

物件介面卡模式

這種設計模式依賴於物件實現。因此,它被稱為物件介面卡模式。

類介面卡模式

這是實現介面卡設計模式的另一種方法。該模式可以使用多重繼承來實現。

如何實現介面卡模式?

現在讓我們看看如何實現介面卡模式。

class EuropeanSocketInterface:
   def voltage(self): pass

   def live(self): pass
   def neutral(self): pass
   def earth(self): pass

# Adaptee
class Socket(EuropeanSocketInterface):
   def voltage(self):
      return 230

	def live(self):
      return 1
   
   def neutral(self):
      return -1
   
   def earth(self):
      return 0

# Target interface
class USASocketInterface:
   def voltage(self): pass
   def live(self): pass
   def neutral(self): pass

# The Adapter
class Adapter(USASocketInterface):
   __socket = None
   def __init__(self, socket):
      self.__socket = socket
   
   def voltage(self):
      return 110
   
   def live(self):
      return self.__socket.live()
   
   def neutral(self):
      return self.__socket.neutral()

# Client
class ElectricKettle:
   __power = None
   
   def __init__(self, power):
	   self.__power = power
   
   def boil(self):
      if self.__power.voltage() > 110:
         print "Kettle on fire!"
      else:
         if self.__power.live() == 1 and \
            self.__power.neutral() == -1:
            print "Coffee time!"
         else:
            print "No power."

def main():
   # Plug in
   socket = Socket()
   adapter = Adapter(socket)
   kettle = ElectricKettle(adapter)
	
   # Make coffee
   kettle.boil()
	
   return 0
	
if __name__ == "__main__":
   main()

輸出

上述程式生成以下輸出 -

Adapter Pattern

說明

程式碼包括帶有各種引數和屬性的介面卡介面。它包括Adaptee以及實現所有屬性並顯示輸出(可見)的目標介面。

Python 設計模式 - 裝飾器模式

裝飾器模式允許使用者向現有物件新增新功能而無需更改其結構。這種設計模式屬於結構型模式,因為這種模式充當現有類的包裝器。

這種模式建立一個裝飾器類,該類包裝原始類並提供附加功能,同時保持類方法簽名不變。

裝飾器模式的目的是動態地附加物件的額外職責。

如何實現裝飾器設計模式

下面提到的程式碼簡單演示瞭如何在Python中實現裝飾器設計模式。該示例以類的形式涉及咖啡店的演示。建立的咖啡類是抽象的,這意味著它不能被例項化。

import six
from abc import ABCMeta

@six.add_metaclass(ABCMeta)
class Abstract_Coffee(object):

   def get_cost(self):
      pass

   def get_ingredients(self):
      pass
   
   def get_tax(self):
      return 0.1*self.get_cost()

class Concrete_Coffee(Abstract_Coffee):
   
   def get_cost(self):
      return 1.00
   
   def get_ingredients(self):
      return 'coffee'

@six.add_metaclass(ABCMeta)
class Abstract_Coffee_Decorator(Abstract_Coffee):
   
   def __init__(self,decorated_coffee):
      self.decorated_coffee = decorated_coffee
   
   def get_cost(self):
      return self.decorated_coffee.get_cost()
   
   def get_ingredients(self):
      return self.decorated_coffee.get_ingredients()

class Sugar(Abstract_Coffee_Decorator):
   
   def __init__(self,decorated_coffee):
      Abstract_Coffee_Decorator.__init__(self,decorated_coffee)
   
   def get_cost(self):
      return self.decorated_coffee.get_cost()
   
   def get_ingredients(self):
	   return self.decorated_coffee.get_ingredients() + ', sugar'

class Milk(Abstract_Coffee_Decorator):
   
   def __init__(self,decorated_coffee):
      Abstract_Coffee_Decorator.__init__(self,decorated_coffee)
   
   def get_cost(self):
      return self.decorated_coffee.get_cost() + 0.25
   
   def get_ingredients(self):
      return self.decorated_coffee.get_ingredients() + ', milk'

class Vanilla(Abstract_Coffee_Decorator):
   
   def __init__(self,decorated_coffee):
      Abstract_Coffee_Decorator.__init__(self,decorated_coffee)
   
   def get_cost(self):
      return self.decorated_coffee.get_cost() + 0.75
   
   def get_ingredients(self):
      return self.decorated_coffee.get_ingredients() + ', vanilla'

咖啡店的抽象類的實現使用單獨的檔案完成,如下所示:

import coffeeshop

myCoffee = coffeeshop.Concrete_Coffee()
print('Ingredients: '+myCoffee.get_ingredients()+
   '; Cost: '+str(myCoffee.get_cost())+'; sales tax = '+str(myCoffee.get_tax()))

myCoffee = coffeeshop.Milk(myCoffee)
print('Ingredients: '+myCoffee.get_ingredients()+
   '; Cost: '+str(myCoffee.get_cost())+'; sales tax = '+str(myCoffee.get_tax()))

myCoffee = coffeeshop.Vanilla(myCoffee)
print('Ingredients: '+myCoffee.get_ingredients()+
   '; Cost: '+str(myCoffee.get_cost())+'; sales tax = '+str(myCoffee.get_tax()))

myCoffee = coffeeshop.Sugar(myCoffee)
print('Ingredients: '+myCoffee.get_ingredients()+
   '; Cost: '+str(myCoffee.get_cost())+'; sales tax = '+str(myCoffee.get_tax()))

輸出

上述程式生成以下輸出 -

Decorator Pattern

Python 設計模式 - 代理模式

代理設計模式包括一個稱為“代理”的新物件,以代替稱為“真實主題”的現有物件。建立的真實主題的代理物件必須具有相同的介面,以便客戶端不會知道代理是否被用作真實物件的替代。客戶端向代理生成的請求透過真實主題傳遞。

代理模式的UML表示如下:

Proxy Pattern

如何實現代理模式?

現在讓我們看看如何實現代理模式。

class Image:
   def __init__( self, filename ):
      self._filename = filename
   
   def load_image_from_disk( self ):
      print("loading " + self._filename )
   
   def display_image( self ):
      print("display " + self._filename)

class Proxy:
   def __init__( self, subject ):
      self._subject = subject
      self._proxystate = None

class ProxyImage( Proxy ):
   def display_image( self ):
      if self._proxystate == None:
         self._subject.load_image_from_disk()
         self._proxystate = 1
      print("display " + self._subject._filename )

proxy_image1 = ProxyImage ( Image("HiRes_10Mb_Photo1") )
proxy_image2 = ProxyImage ( Image("HiRes_10Mb_Photo2") )

proxy_image1.display_image() # loading necessary
proxy_image1.display_image() # loading unnecessary
proxy_image2.display_image() # loading necessary
proxy_image2.display_image() # loading unnecessary
proxy_image1.display_image() # loading unnecessary

輸出

上述程式生成以下輸出 -

Proxy Pattern Output

代理模式設計有助於複製我們建立的影像。display_image() 函式有助於檢查值是否正在命令提示符中列印。

責任鏈

責任鏈模式用於在軟體中實現松耦合,其中來自客戶端的指定請求透過其中包含的一系列物件傳遞。它有助於構建物件鏈。請求從一端進入,並從一個物件移動到另一個物件。

這種模式允許物件傳送命令,而無需知道哪個物件將處理請求。

如何實現責任鏈模式?

我們現在將看到如何實現責任鏈模式。

class ReportFormat(object):
   PDF = 0
   TEXT = 1
class Report(object):
   def __init__(self, format_):
      self.title = 'Monthly report'
      self.text = ['Things are going', 'really, really well.']
      self.format_ = format_

class Handler(object):
   def __init__(self):
      self.nextHandler = None

   def handle(self, request):
      self.nextHandler.handle(request)

class PDFHandler(Handler):

   def handle(self, request):
      if request.format_ == ReportFormat.PDF:
         self.output_report(request.title, request.text)
      else:
         super(PDFHandler, self).handle(request)
	
   def output_report(self, title, text):
      print '<html>'
      print ' <head>'
      print ' <title>%s</title>' % title
      print ' </head>'
      print ' <body>'
      for line in text:
         print ' <p>%s

' % line print ' </body>' print '</html>' class TextHandler(Handler): def handle(self, request): if request.format_ == ReportFormat.TEXT: self.output_report(request.title, request.text) else: super(TextHandler, self).handle(request) def output_report(self, title, text): print 5*'*' + title + 5*'*' for line in text: print line class ErrorHandler(Handler): def handle(self, request): print "Invalid request" if __name__ == '__main__': report = Report(ReportFormat.TEXT) pdf_handler = PDFHandler() text_handler = TextHandler() pdf_handler.nextHandler = text_handler text_handler.nextHandler = ErrorHandler() pdf_handler.handle(report)

輸出

上述程式生成以下輸出 -

Design Chain Pattern

說明

以上程式碼建立了一個每月任務的報告,它透過每個函式傳送命令。它需要兩個處理程式——一個用於PDF,一個用於文字。在所需物件執行每個函式後,它會列印輸出。

Python 設計模式 - 觀察者模式

在這種模式中,物件表示為觀察者,它們等待事件觸發。觀察者在指定事件發生後附加到主題。當事件發生時,主題會告訴觀察者它已發生。

以下UML圖表示觀察者模式:

Observer Pattern

如何實現觀察者模式?

現在讓我們看看如何實現觀察者模式。

import threading
import time
import pdb

class Downloader(threading.Thread):
   
   def run(self):
      print 'downloading'
      for i in range(1,5):
         self.i = i
         time.sleep(2)
			print 'unfunf'
         return 'hello world'

class Worker(threading.Thread):
   def run(self):
      for i in range(1,5):
         print 'worker running: %i (%i)' % (i, t.i)
         time.sleep(1)
         t.join()

         print 'done'

t = Downloader()
t.start()

time.sleep(1)

t1 = Worker()
t1.start()

t2 = Worker()
t2.start()

t3 = Worker()
t3.start()

輸出

上述程式生成以下輸出 -

Observer Pattern Output

說明

以上程式碼解釋了下載特定結果的過程。根據觀察者模式邏輯,每個物件都被視為觀察者。當事件觸發時,它會列印輸出。

Python 設計模式 - 狀態模式

它為狀態機提供了一個模組,該模組使用從指定狀態機類派生的子類實現。方法與狀態無關,並導致使用裝飾器宣告的轉換。

如何實現狀態模式?

狀態模式的基本實現如下所示:

class ComputerState(object):

   name = "state"
   allowed = []

   def switch(self, state):
      """ Switch to new state """
      if state.name in self.allowed:
         print 'Current:',self,' => switched to new state',state.name
         self.__class__ = state
      else:
         print 'Current:',self,' => switching to',state.name,'not possible.'

   def __str__(self):
      return self.name

class Off(ComputerState):
   name = "off"
   allowed = ['on']

class On(ComputerState):
   """ State of being powered on and working """
   name = "on"
   allowed = ['off','suspend','hibernate']

class Suspend(ComputerState):
   """ State of being in suspended mode after switched on """
   name = "suspend"
   allowed = ['on']

class Hibernate(ComputerState):
   """ State of being in hibernation after powered on """
   name = "hibernate"
   allowed = ['on']

class Computer(object):
   """ A class representing a computer """
   
   def __init__(self, model='HP'):
      self.model = model
      # State of the computer - default is off.
      self.state = Off()
   
   def change(self, state):
      """ Change state """
      self.state.switch(state)

if __name__ == "__main__":
   comp = Computer()
   comp.change(On)
   comp.change(Off)
   comp.change(On)
   comp.change(Suspend)
   comp.change(Hibernate)
   comp.change(On)
   comp.change(Off)

輸出

上述程式生成以下輸出 -

Design Pattern Output

Python 設計模式 - 策略模式

策略模式是一種行為型模式。策略模式的主要目標是使客戶端能夠從不同的演算法或程式中進行選擇以完成指定的任務。不同的演算法可以在不影響所述任務的情況下進行交換。

此模式可用於在訪問外部資源時提高靈活性。

如何實現策略模式?

下面顯示的程式有助於實現策略模式。

import types

class StrategyExample:
   def __init__(self, func = None):
      self.name = 'Strategy Example 0'
      if func is not None:
         self.execute = types.MethodType(func, self)

   def execute(self):
      print(self.name)

def execute_replacement1(self): 
   print(self.name + 'from execute 1')

def execute_replacement2(self):
   print(self.name + 'from execute 2')

if __name__ == '__main__':
   strat0 = StrategyExample()
   strat1 = StrategyExample(execute_replacement1)
   strat1.name = 'Strategy Example 1'
   strat2 = StrategyExample(execute_replacement2)
   strat2.name = 'Strategy Example 2'
   strat0.execute()
   strat1.execute()
   strat2.execute()

輸出

上述程式生成以下輸出 -

Strategy Pattern

說明

它從執行輸出的函式中提供了一個策略列表。這種行為模式的主要焦點是行為。

Python 設計模式 - 模板模式

模板模式在基類中定義了一個基本演算法,使用抽象操作,其中子類覆蓋具體行為。模板模式將演算法的輪廓儲存在一個單獨的方法中。此方法稱為模板方法。

以下是模板模式的不同功能:

  • 它在操作中定義了演算法的骨架

  • 它包括子類,這些子類重新定義演算法的某些步驟。

class MakeMeal:

   def prepare(self): pass
   def cook(self): pass
   def eat(self): pass

   def go(self):
      self.prepare()
      self.cook()
      self.eat()

class MakePizza(MakeMeal):
   def prepare(self):
      print "Prepare Pizza"
   
   def cook(self):
      print "Cook Pizza"
   
   def eat(self):
      print "Eat Pizza"

class MakeTea(MakeMeal):
   def prepare(self):
      print "Prepare Tea"
	
   def cook(self):
      print "Cook Tea"
   
   def eat(self):
      print "Eat Tea"

makePizza = MakePizza()
makePizza.go()

print 25*"+"

makeTea = MakeTea()
makeTea.go()

輸出

上述程式生成以下輸出 -

Template Pattern

說明

此程式碼建立了一個準備膳食的模板。這裡,每個引數代表一個屬性,用於建立膳食的一部分,如茶、披薩等。

輸出表示屬性的視覺化。

Python 設計模式 - 享元模式

享元模式屬於結構型設計模式類別。它提供了一種減少物件數量的方法。它包括有助於改進應用程式結構的各種功能。享元物件最重要的特徵是不可變的。這意味著一旦構造它們就不能修改。該模式使用HashMap儲存引用物件。

如何實現享元模式?

以下程式有助於實現享元模式:

class ComplexGenetics(object):
   def __init__(self):
      pass
   
   def genes(self, gene_code):
      return "ComplexPatter[%s]TooHugeinSize" % (gene_code)
class Families(object):
   family = {}
   
   def __new__(cls, name, family_id):
      try:
         id = cls.family[family_id]
      except KeyError:
         id = object.__new__(cls)
         cls.family[family_id] = id
      return id
   
   def set_genetic_info(self, genetic_info):
      cg = ComplexGenetics()
      self.genetic_info = cg.genes(genetic_info)
   
   def get_genetic_info(self):
      return (self.genetic_info)

def test():
   data = (('a', 1, 'ATAG'), ('a', 2, 'AAGT'), ('b', 1, 'ATAG'))
   family_objects = []
   for i in data:
      obj = Families(i[0], i[1])
      obj.set_genetic_info(i[2])
      family_objects.append(obj)
   
   for i in family_objects:
      print "id = " + str(id(i))
      print i.get_genetic_info()
   print "similar id's says that they are same objects "

if __name__ == '__main__':
   test()

輸出

上述程式生成以下輸出 -

Flyweight Pattern

Python設計模式 - 抽象工廠

抽象工廠模式也稱為工廠的工廠。這種設計模式屬於建立型設計模式類別。它提供了一種建立物件的最佳方式之一。

它包含一個介面,負責建立與工廠相關的物件。

如何實現抽象工廠模式?

以下程式有助於實現抽象工廠模式。

class Window:
   __toolkit = ""
   __purpose = ""

   def __init__(self, toolkit, purpose):
      self.__toolkit = toolkit
      self.__purpose = purpose
   
   def getToolkit(self):
      return self.__toolkit
   
   def getType(self):
      return self.__purpose

class GtkToolboxWindow(Window):
   def __init__(self):
      Window.__init__(self, "Gtk", "ToolboxWindow")

class GtkLayersWindow(Window):
   def __init__(self):
      Window.__init__(self, "Gtk", "LayersWindow")

class GtkMainWindow(Window):
   def __init__(self):
      Window.__init__(self, "Gtk", "MainWindow")

class QtToolboxWindow(Window):
   def __init__(self):
      Window.__init__(self, "Qt", "ToolboxWindow")

class QtLayersWindow(Window):
   def __init__(self):
      Window.__init__(self, "Qt", "LayersWindow")

class QtMainWindow(Window):
   def __init__(self):
      Window.__init__(self, "Qt", "MainWindow")

# Abstract factory class
class UIFactory:
   def getToolboxWindow(self): pass
   def getLayersWindow(self): pass
   def getMainWindow(self): pass

class GtkUIFactory(UIFactory):
   def getToolboxWindow(self):
      return GtkToolboxWindow()
   def getLayersWindow(self):
      return GtkLayersWindow()
   def getMainWindow(self):
      return GtkMainWindow()

class QtUIFactory(UIFactory):
   def getToolboxWindow(self):
      return QtToolboxWindow()
   def getLayersWindow(self):
      return QtLayersWindow()
   def getMainWindow(self):
      return QtMainWindow()

if __name__ == "__main__":
   gnome = True
   kde = not gnome
   
   if gnome:
      ui = GtkUIFactory()
   elif kde:
      ui = QtUIFactory()
   
   toolbox = ui.getToolboxWindow()
   layers = ui.getLayersWindow()
   main = ui.getMainWindow()
   
   print "%s:%s" % (toolbox.getToolkit(), toolbox.getType())
   print "%s:%s" % (layers.getToolkit(), layers.getType())
   print "%s:%s" % (main.getToolkit(), main.getType())

輸出

上述程式生成以下輸出 -

Abstract Factory Pattern

說明

在上面的程式中,抽象工廠為每個視窗建立物件。它呼叫每個方法,該方法按預期執行輸出。

Python設計模式 - 面向物件

面向物件模式是最常用的模式。這種模式幾乎可以在每種程式語言中找到。

如何實現面向物件模式?

現在讓我們看看如何實現面向物件模式。

class Parrot:
   # class attribute
   species = "bird"
	
   # instance attribute
   def __init__(self, name, age):
      self.name = name
      self.age = age
		
# instantiate the Parrot class
blu = Parrot("Blu", 10)
woo = Parrot("Woo", 15)

# access the class attributes
print("Blu is a {}".format(blu.__class__.species))
print("Woo is also a {}".format(woo.__class__.species))

# access the instance attributes
print("{} is {} years old".format( blu.name, blu.age))
print("{} is {} years old".format( woo.name, woo.age))

輸出

以上程式生成以下輸出

Object Oriented

說明

程式碼包含類屬性和例項屬性,根據輸出要求列印。面向物件模式包含各種功能。下一章將解釋這些功能。

面向物件概念的實現

在本章中,我們將重點關注使用面向物件概念的模式及其在 Python 中的實現。當我們圍繞操縱函數週圍資料的語句塊設計程式時,稱為程序式程式設計。在面向物件程式設計中,有兩個主要例項稱為類和物件。

如何實現類和物件變數?

類和物件變數的實現如下:

class Robot:
   population = 0
   
   def __init__(self, name):
      self.name = name
      print("(Initializing {})".format(self.name))
      Robot.population += 1
   
   def die(self):
      print("{} is being destroyed!".format(self.name))
      Robot.population -= 1
      if Robot.population == 0:
         print("{} was the last one.".format(self.name))
      else:
         print("There are still {:d} robots working.".format(
            Robot.population))
   
   def say_hi(self):
      print("Greetings, my masters call me {}.".format(self.name))
   
   @classmethod
   def how_many(cls):
      print("We have {:d} robots.".format(cls.population))
droid1 = Robot("R2-D2")
droid1.say_hi()
Robot.how_many()

droid2 = Robot("C-3PO")
droid2.say_hi()
Robot.how_many()

print("\nRobots can do some work here.\n")

print("Robots have finished their work. So let's destroy them.")
droid1.die()
droid2.die()

Robot.how_many()

輸出

上述程式生成以下輸出 -

Object Oriented Concepts Implementation

說明

此示例有助於演示類和物件變數的性質。

  • “population”屬於“Robot”類。因此,它被稱為類變數或物件。

  • 在這裡,我們將人口類變數稱為 Robot.population,而不是 self.population。

Python 設計模式 - 迭代器模式

迭代器設計模式屬於行為型設計模式類別。開發人員在幾乎每種程式語言中都會遇到迭代器模式。此模式的使用方式有助於以順序方式訪問集合(類)的元素,而無需瞭解底層設計。

如何實現迭代器模式?

現在我們將瞭解如何實現迭代器模式。

import time

def fib():
   a, b = 0, 1
   while True:
      yield b
      a, b = b, a + b

g = fib()

try:
   for e in g:
      print(e)
      time.sleep(1)

except KeyboardInterrupt:
   print("Calculation stopped")

輸出

上述程式生成以下輸出 -

Iterator

如果您關注該模式,斐波那契數列將使用迭代器模式列印。在使用者強制終止時,將列印以下輸出:

Fibonacci Series

說明

此 Python 程式碼遵循迭代器模式。這裡,增量運算子用於開始計數。計數在使用者強制終止時結束。

Python 設計模式 - 字典

字典是資料結構,包括鍵值組合。它們被廣泛用於代替 JSON – JavaScript 物件表示法。字典用於 API(應用程式程式設計介面)程式設計。字典將一組物件對映到另一組物件。字典是可變的;這意味著可以根據需要更改它們。

如何在 Python 中實現字典?

以下程式展示了從建立到實現的 Python 字典的基本實現。

# Create a new dictionary
d = dict() # or d = {}

# Add a key - value pairs to dictionary
d['xyz'] = 123
d['abc'] = 345

# print the whole dictionary
print(d)

# print only the keys
print(d.keys())

# print only values
print(d.values())

# iterate over dictionary
for i in d :
   print("%s %d" %(i, d[i]))
	
# another method of iteration
for index, value in enumerate(d):
   print (index, value , d[value])

# check if key exist 23. Python Data Structure –print('xyz' in d)

# delete the key-value pair
del d['xyz']

# check again
print("xyz" in d)

輸出

上述程式生成以下輸出 -

Dictionaries

注意 -Python 中字典的實現存在一些缺點。

缺點

字典不支援字串、元組和列表等序列資料型別的序列操作。這些屬於內建對映型別。

列表資料結構

列表資料結構是 Python 中一種通用的資料型別,可以寫成方括號之間用逗號分隔的值列表。

語法

以下是該結構的基本語法:

List_name = [ elements ];

如果您觀察到,語法宣告類似於陣列,唯一的區別是列表可以包含不同資料型別的元素。陣列包含相同資料型別的元素。列表可以包含字串、整數和物件的組合。列表可用於堆疊和佇列的實現。

列表是可變的。可以根據需要更改它們。

如何實現列表?

以下程式展示了列表的實現:

my_list = ['p','r','o','b','e']
# Output: p
print(my_list[0])

# Output: o
print(my_list[2])

# Output: e
print(my_list[4])

# Error! Only integer can be used for indexing
# my_list[4.0]

# Nested List
n_list = ["Happy", [2,0,1,5]]

# Nested indexing

# Output: a
print(n_list[0][1])

# Output: 5
print(n_list[1][3])

輸出

上述程式生成以下輸出 -

Lists Data Structure

Python 列表的內建函式如下:

  • Append() - 將元素新增到列表的末尾。

  • Extend() - 將列表的元素新增到另一個列表。

  • Insert() - 將專案插入到定義的索引中。

  • Remove() - 從指定的列表中刪除元素。

  • Reverse() - 反轉列表中的元素。

  • sort() - 有助於按時間順序排序元素。

Python 設計模式 - 集合

集合可以定義為可迭代、可變的無序集合,並且其中不包含重複元素。在 Python 中,set 類是數學集合的表示法。使用集合的主要優點是它包含高度最佳化的檢查特定元素的方法。

Python 包含一個名為凍結集的單獨類別。這些集合是不可變物件,僅支援產生所需結果的方法和運算子。

如何實現集合?

以下程式有助於集合的實現:

# Set in Python

# Creating two sets
set1 = set()
set2 = set()

# Adding elements to set1
for i in range(1, 6):
   set1.add(i)

# Adding elements to set2
for i in range(3, 8):
   set2.add(i)

print("Set1 = ", set1)
print("Set2 = ", set2)
print("\n")

# Union of set1 and set2
set3 = set1 | set2# set1.union(set2)
print("Union of Set1 & Set2: Set3 = ", set3)

# Intersection of set1 and set2
set4 = set1 & set2# set1.intersection(set2)
print("Intersection of Set1 & Set2: Set4 = ", set4)
print("\n")

# Checking relation between set3 and set4
if set3 > set4: # set3.issuperset(set4)
   print("Set3 is superset of Set4")
elif set3 < set4: # set3.issubset(set4)
   print("Set3 is subset of Set4")
else : # set3 == set4
   print("Set3 is same as Set4")

# displaying relation between set4 and set3
if set4 < set3: # set4.issubset(set3)
   print("Set4 is subset of Set3")
   print("\n")

# difference between set3 and set4
set5 = set3 - set4
print("Elements in Set3 and not in Set4: Set5 = ", set5)
print("\n")

# checkv if set4 and set5 are disjoint sets
if set4.isdisjoint(set5):
   print("Set4 and Set5 have nothing in common\n")

# Removing all the values of set5
set5.clear()

print("After applying clear on sets Set5: ")
print("Set5 = ", set5)

輸出

上述程式生成以下輸出 -

Sets

可以使用以下程式演示凍結集:

normal_set = set(["a", "b","c"])

# Adding an element to normal set is fine
normal_set.add("d")

print("Normal Set")
print(normal_set)

# A frozen set
frozen_set = frozenset(["e", "f", "g"])

print("Frozen Set")
print(frozen_set)

輸出

上述程式生成以下輸出 -

Frozen Set

Python 設計模式 - 佇列

佇列是一組物件,它們定義了一個簡單的遵循 FIFO(先進先出)和 LIFO(後進先出)過程的資料結構。插入和刪除操作稱為入隊出隊操作。

佇列不允許隨機訪問它們包含的物件。

如何實現 FIFO 過程?

以下程式有助於實現 FIFO:

import Queue

q = Queue.Queue()

#put items at the end of the queue
for x in range(4):
   q.put("item-" + str(x))

#remove items from the head of the queue
while not q.empty():
   print q.get()

輸出

上述程式生成以下輸出 -

Fifo

如何實現 LIFO 過程?

以下程式有助於實現 LIFO 過程:

import Queue

q = Queue.LifoQueue()

#add items at the head of the queue
for x in range(4):
   q.put("item-" + str(x))

#remove items from the head of the queue
while not q.empty():
   print q.get()

輸出

上述程式生成以下輸出 -

Lifo

什麼是優先順序佇列?

優先順序佇列是一種容器資料結構,它管理一組具有有序鍵的記錄,以便快速訪問指定資料結構中最小的或最大的鍵的記錄。

如何實現優先順序佇列?

優先順序佇列的實現如下:

import Queue

class Task(object):
   def __init__(self, priority, name):
      self.priority = priority
      self.name = name
   
   def __cmp__(self, other):
      return cmp(self.priority, other.priority)

q = Queue.PriorityQueue()

q.put( Task(100, 'a not agent task') )
q.put( Task(5, 'a highly agent task') )
q.put( Task(10, 'an important task') )

while not q.empty():
   cur_task = q.get()
	print 'process task:', cur_task.name

輸出

上述程式生成以下輸出 -

Priority Queues

字串和序列化

字串序列化是將物件的狀態寫入位元組流的過程。在 python 中,“pickle”庫用於啟用序列化。此模組包含一個功能強大的演算法,用於序列化和反序列化 Python 物件結構。“Pickling”是將 Python 物件層次結構轉換為位元組流的過程,“unpickling”是反向過程。

pickle 模組的演示如下:

import pickle

#Here's an example dict
grades = { 'Alice': 89, 'Bob': 72, 'Charles': 87 }

#Use dumps to convert the object to a serialized string
serial_grades = pickle.dumps( grades )
print(serial_grades)

#Use loads to de-serialize an object
received_grades = pickle.loads( serial_grades )
print(received_grades)

輸出

上述程式生成以下輸出 -

Serialization

Python 中的併發

併發通常被誤解為並行。併發意味著以系統的方式安排獨立程式碼的執行。本章重點介紹使用 Python 為作業系統執行併發。

以下程式有助於為作業系統執行併發:

import os
import time
import threading
import multiprocessing

NUM_WORKERS = 4

def only_sleep():
   print("PID: %s, Process Name: %s, Thread Name: %s" % (
      os.getpid(),
      multiprocessing.current_process().name,
      threading.current_thread().name)
   )
   time.sleep(1)

def crunch_numbers():
   print("PID: %s, Process Name: %s, Thread Name: %s" % (
      os.getpid(),
      multiprocessing.current_process().name,
      threading.current_thread().name)
   )
   x = 0
   while x < 10000000:
      x += 1
for _ in range(NUM_WORKERS):
   only_sleep()
end_time = time.time()
print("Serial time=", end_time - start_time)

# Run tasks using threads
start_time = time.time()
threads = [threading.Thread(target=only_sleep) for _ in range(NUM_WORKERS)]
[thread.start() for thread in threads]
[thread.join() for thread in threads]
end_time = time.time()

print("Threads time=", end_time - start_time)

# Run tasks using processes
start_time = time.time()
processes = [multiprocessing.Process(target=only_sleep()) for _ in range(NUM_WORKERS)]
[process.start() for process in processes]
[process.join() for process in processes]
end_time = time.time()

print("Parallel time=", end_time - start_time)

輸出

上述程式生成以下輸出 -

Concurrency

說明

“multiprocessing”是一個類似於 threading 模組的包。此包支援本地和遠端併發。由於此模組,程式設計師可以利用給定系統上的多個程序。

Python 設計模式 - 反模式

反模式遵循與預定義設計模式相反的策略。該策略包括針對常見問題的常見方法,這些方法可以形式化,並且通常可以被認為是一種良好的開發實踐。通常,反模式是相反的和不希望的。反模式是在軟體開發中使用的一些模式,這些模式被認為是不好的程式設計實踐。

反模式的重要特徵

現在讓我們看看反模式的一些重要特徵。

正確性

這些模式實際上會破壞您的程式碼並讓您做錯事。以下是對此的一個簡單說明:

class Rectangle(object):
def __init__(self, width, height):
self._width = width
self._height = height
r = Rectangle(5, 6)
# direct access of protected member
print("Width: {:d}".format(r._width))

可維護性

如果程式易於理解和根據需要修改,則稱該程式是可維護的。匯入模組可以被視為可維護性的一個示例。

import math
x = math.ceil(y)
# or
import multiprocessing as mp
pool = mp.pool(8)

反模式示例

以下示例有助於演示反模式:

#Bad
def filter_for_foo(l):
   r = [e for e in l if e.find("foo") != -1]
   if not check_some_critical_condition(r):
      return None
   return r

res = filter_for_foo(["bar","foo","faz"])

if res is not None:
   #continue processing
   pass

#Good
def filter_for_foo(l):
   r = [e for e in l if e.find("foo") != -1]
   if not check_some_critical_condition(r):
      raise SomeException("critical condition unmet!")
   return r

try:
   res = filter_for_foo(["bar","foo","faz"])
   #continue processing

except SomeException:
   i = 0
while i < 10:
   do_something()
   #we forget to increment i

說明

該示例包括在 Python 中建立函式的良好和不良標準的演示。

Python 設計模式 - 異常處理

處理異常也是設計模式的主要標準。異常是在程式執行期間發生的錯誤。當發生特定錯誤時,務必生成異常。這有助於抑制程式崩潰。

為什麼要使用異常?

異常是在程式中處理錯誤和特殊情況的便捷方法。當用戶認為指定的程式碼可能產生錯誤時,務必使用異常處理。

示例 – 除以零

import sys

randomList = ['a', 0, 2]

for entry in randomList:
   try:
      print("The entry is", entry)
      r = 1/int(entry)
      break
   except:
      print("Oops!",sys.exc_info()[0],"occured.")
      print("Next entry.")
      print()
print("The reciprocal of",entry,"is",r)

輸出

上述程式生成以下輸出 -

Exceptions

引發異常

特別是在 Python 程式設計中,當代碼的相應錯誤在執行時發生時,會引發異常。可以使用“raise”關鍵字強制引發此異常。

語法

   raise KeyboardInterrupt
Traceback (most recent call last):
...
KeyboardInterrupt
廣告