Python-Entwurfsmuster - Kurzanleitung
Entwurfsmuster werden verwendet, um das Muster darzustellen, das Entwickler zum Erstellen von Software oder Webanwendungen verwenden. Diese Muster werden basierend auf der Anforderungsanalyse ausgewählt. Die Muster beschreiben die Lösung des Problems, wann und wo die Lösung anzuwenden ist und die Konsequenzen der Implementierung.
Struktur eines Entwurfsmusters
Die Dokumentation des Entwurfsmusters wird so gepflegt, dass der Schwerpunkt mehr auf der verwendeten Technologie und auf welche Weise liegt. Das folgende Diagramm erläutert die Grundstruktur der Entwurfsmusterdokumentation.
Mustername
Es beschreibt das Muster kurz und effektiv.
Absicht / Motiv
Es beschreibt, was das Muster tut.
Anwendbarkeit
Es beschreibt die Liste der Situationen, in denen Muster anwendbar sind.
Teilnehmer und Konsequenzen
Zu den Teilnehmern gehören Klassen und Objekte, die am Entwurfsmuster teilnehmen, mit einer Liste der Konsequenzen, die mit dem Muster verbunden sind.
Warum Python?
Python ist eine Open Source-Skriptsprache. Es verfügt über Bibliotheken, die eine Vielzahl von Entwurfsmustern unterstützen. Die Syntax von Python ist leicht zu verstehen und verwendet englische Schlüsselwörter.
Python bietet Unterstützung für die Liste der unten genannten Entwurfsmuster. Diese Entwurfsmuster werden in diesem Tutorial verwendet -
- Modellansicht-Controller-Muster
- Singleton-Muster
- Fabrikmuster
- Builder-Muster
- Prototypmuster
- Fassadenmuster
- Befehlsmuster
- Adaptermuster
- Prototypmuster
- Dekorateur Muster
- Proxy-Muster
- Muster der Verantwortungskette
- Beobachtermuster
- Zustandsmuster
- Strategiemuster
- Vorlagenmuster
- Fliegengewichtsmuster
- Abstraktes Fabrikmuster
- Objektorientiertes Muster
Vorteile der Verwendung von Designmustern
Im Folgenden sind die verschiedenen Vorteile des Entwurfsmusters aufgeführt:
Muster bieten Entwicklern eine Auswahl bewährter Lösungen für die angegebenen Probleme.
Alle Designmuster sind sprachneutral.
Muster helfen dabei, Kommunikation zu erreichen und eine gute Dokumentation aufrechtzuerhalten.
Es enthält eine Leistungsaufzeichnung, um das technische Risiko für das Projekt zu verringern.
Entwurfsmuster sind sehr flexibel zu verwenden und leicht zu verstehen.
Python ist eine Open-Source-Skriptsprache, die auf hoher Ebene interpretiert, interaktiv und objektorientiert ist. Es ist so konzipiert, dass es gut lesbar ist. Die Syntax der Python-Sprache ist leicht zu verstehen und verwendet häufig englische Schlüsselwörter.
Funktionen der Python-Sprache
In diesem Abschnitt lernen wir die verschiedenen Funktionen der Python-Sprache kennen.
Interpretiert
Python wird zur Laufzeit mit dem Interpreter verarbeitet. Es ist nicht erforderlich, das Programm vor der Ausführung zu kompilieren. Es ist ähnlich wie PERL und PHP.
Objektorientierter
Python folgt objektorientierten Stil- und Designmustern. Es enthält eine Klassendefinition mit verschiedenen Funktionen wie Kapselung, Polymorphismus und vielem mehr.
tragbar
Python-Code, der im Windows-Betriebssystem geschrieben wurde und im Mac-Betriebssystem verwendet werden kann. Der Code kann gemäß den Anforderungen wiederverwendet und portiert werden.
Einfach zu codieren
Die Python-Syntax ist leicht zu verstehen und zu codieren. Jeder Entwickler kann die Syntax von Python innerhalb weniger Stunden verstehen. Python kann als "programmiererfreundlich" bezeichnet werden.
Erweiterbar
Bei Bedarf kann ein Benutzer auch Python-Code in C-Sprache schreiben. Es ist auch möglich, Python-Code in verschiedenen Sprachen wie C ++ in den Quellcode einzufügen. Dies macht Python zu einer erweiterbaren Sprache.
Wichtige Punkte
Beachten Sie die folgenden wichtigen Punkte im Zusammenhang mit der Programmiersprache Python:
Es umfasst funktionale und strukturierte Programmiermethoden sowie objektorientierte Programmiermethoden.
Es kann als Skriptsprache oder als Programmiersprache verwendet werden.
Es enthält eine automatische Speicherbereinigung.
Es enthält dynamische Datentypen auf hoher Ebene und unterstützt verschiedene dynamische Typprüfungen.
Python enthält eine Funktion zur Integration in C, C ++ und Sprachen wie Java.
Wie lade ich die Python-Sprache in mein System herunter?
Folgen Sie diesem Link, um die Python-Sprache in Ihr System herunterzuladen -
https://www.python.org/downloads/Es enthält Pakete für verschiedene Betriebssysteme wie Windows-, MacOS- und Linux-Distributionen.
Die wichtigen Tools in Python
In diesem Abschnitt lernen wir kurz einige wichtige Tools in Python kennen.
Python-Strings
Die grundlegende Deklaration von Zeichenfolgen lautet wie folgt:
str = 'Hello World!'
Python-Listen
Die Python-Listen können als zusammengesetzte Datentypen deklariert werden, die durch Kommas getrennt und in eckigen Klammern ([]) eingeschlossen sind.
list = [ 'abcd', 786 , 2.23, 'john', 70.2 ]
tinylist = [123, 'john']
Python-Tupel
Ein Tupel ist ein dynamischer Python-Datentyp, der aus einer Anzahl von durch Kommas getrennten Werten besteht. Tupel sind in Klammern eingeschlossen.
tinytuple = (123, 'john')
Python-Wörterbuch
Python-Wörterbuch ist eine Art Hash-Tabelle. Ein Wörterbuchschlüssel kann fast jeder Datentyp von Python sein. Die Datentypen sind normalerweise Zahlen oder Zeichenfolgen.
tinydict = {'name': 'omkar','code':6734, 'dept': 'sales'}
Was macht ein Entwurfsmuster in Python aus?
Python hilft beim Erstellen eines Entwurfsmusters unter Verwendung der folgenden Parameter:
- Mustername
- Intent
- Aliases
- Motivation
- Problem
- Solution
- Structure
- Participants
- Constraints
- Beispielcode
Model View Controller ist das am häufigsten verwendete Entwurfsmuster. Entwickler finden es einfach, dieses Entwurfsmuster zu implementieren.
Im Folgenden finden Sie eine grundlegende Architektur des Model View Controllers:
Lassen Sie uns nun sehen, wie die Struktur funktioniert.
Modell
Es besteht aus reiner Anwendungslogik, die mit der Datenbank interagiert. Es enthält alle Informationen zur Darstellung von Daten für den Endbenutzer.
Aussicht
Ansicht stellt die HTML-Dateien dar, die mit dem Endbenutzer interagieren. Es repräsentiert die Daten des Modells für den Benutzer.
Regler
Es fungiert als Vermittler zwischen Ansicht und Modell. Es lauscht den Ereignissen, die durch das Ansichts- und Abfragemodell ausgelöst werden.
Python-Code
Betrachten wir ein Basisobjekt namens "Person" und erstellen Sie ein MVC-Entwurfsmuster.
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
Es wird eine Methode aufgerufen, die alle Datensätze der Personentabelle in der Datenbank abruft. Die Datensätze werden im JSON-Format dargestellt.
Aussicht
Es werden alle im Modell abgerufenen Datensätze angezeigt. Die Ansicht interagiert niemals mit dem Modell. Der Controller erledigt diese Arbeit (Kommunikation mit Modell und Ansicht).
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!'
Regler
Der Controller interagiert mit dem Modell über das getAll() Methode, mit der alle dem Endbenutzer angezeigten Datensätze abgerufen werden.
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()
Dieses Muster beschränkt die Instanziierung einer Klasse auf ein Objekt. Es handelt sich um eine Art Erstellungsmuster, an dem nur eine Klasse zum Erstellen von Methoden und angegebenen Objekten beteiligt ist.
Es bietet einen globalen Zugriffspunkt auf die erstellte Instanz.
Wie implementiere ich eine Singleton-Klasse?
Das folgende Programm demonstriert die Implementierung der Singleton-Klasse, bei der die mehrfach erstellten Instanzen gedruckt werden.
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
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Die Anzahl der erstellten Instanzen ist gleich und es gibt keinen Unterschied zwischen den in der Ausgabe aufgelisteten Objekten.
Das Factory-Muster fällt unter die Kategorie der Liste der Erstellungsmuster. Es bietet eine der besten Möglichkeiten, ein Objekt zu erstellen. Im Factory-Muster werden Objekte erstellt, ohne die Logik dem Client zur Verfügung zu stellen und über eine gemeinsame Schnittstelle auf das neu erstellte Objekt zu verweisen.
Factory-Muster werden in Python mithilfe der Factory-Methode implementiert. Wenn ein Benutzer eine Methode so aufruft, dass wir eine Zeichenfolge übergeben und der Rückgabewert als neues Objekt über die Factory-Methode implementiert wird. Der in der Factory-Methode verwendete Objekttyp wird durch eine Zeichenfolge bestimmt, die durch die Methode übergeben wird.
Im folgenden Beispiel enthält jede Methode ein Objekt als Parameter, der über die Factory-Methode implementiert wird.
Wie implementiere ich ein Factory-Muster?
Lassen Sie uns nun sehen, wie ein Factory-Muster implementiert wird.
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()
Die Schaltflächenklasse hilft beim Erstellen der HTML-Tags und der zugehörigen HTML-Seite. Der Client hat keinen Zugriff auf die Codelogik und die Ausgabe repräsentiert die Erstellung einer HTML-Seite.
Ausgabe
Erläuterung
Der Python-Code enthält die Logik von HTML-Tags, die den Wert angeben. Der Endbenutzer kann sich die vom Python-Code erstellte HTML-Datei ansehen.
Das Builder-Muster ist ein einzigartiges Entwurfsmuster, das beim Erstellen komplexer Objekte mit einfachen Objekten hilft und einen algorithmischen Ansatz verwendet. Dieses Entwurfsmuster fällt unter die Kategorie des Schöpfungsmusters. In diesem Entwurfsmuster erstellt eine Builder-Klasse das endgültige Objekt schrittweise. Dieser Builder ist unabhängig von anderen Objekten.
Vorteile des Builder-Musters
Es bietet eine klare Trennung und eine eindeutige Ebene zwischen Konstruktion und Darstellung eines bestimmten von der Klasse erstellten Objekts.
Es bietet eine bessere Kontrolle über den Konstruktionsprozess des erstellten Musters.
Es bietet das perfekte Szenario, um die interne Darstellung von Objekten zu ändern.
Wie implementiere ich ein Builder-Muster?
In diesem Abschnitt erfahren Sie, wie Sie das Builder-Muster implementieren.
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()
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Das Prototyp-Entwurfsmuster hilft dabei, die Komplexität der von der Klasse erstellten Instanzen zu verbergen. Das Konzept des vorhandenen Objekts unterscheidet sich von dem des neuen Objekts, das von Grund auf neu erstellt wird.
Das neu kopierte Objekt kann bei Bedarf einige Änderungen an den Eigenschaften aufweisen. Dieser Ansatz spart Zeit und Ressourcen für die Entwicklung eines Produkts.
Wie implementiere ich ein Prototypmuster?
Lassen Sie uns nun sehen, wie ein Prototypmuster implementiert wird.
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()
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Die Ausgabe hilft beim Erstellen neuer Objekte mit den vorhandenen und ist in der oben genannten Ausgabe deutlich sichtbar.
Das Fassadenentwurfsmuster bietet eine einheitliche Schnittstelle zu einer Reihe von Schnittstellen in einem Subsystem. Es definiert eine übergeordnete Schnittstelle, die jedes Subsystem verwenden kann.
Eine Fassadenklasse weiß, welches Subsystem für eine Anfrage verantwortlich ist.
Wie entwerfe ich ein Fassadenmuster?
Lassen Sie uns nun sehen, wie ein Fassadenmuster entworfen wird.
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()
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Erläuterung
Dieses Programm wurde mit einem Szenario entworfen. Es ist das Starten des Motors eines Autos oder eines fahrenden Fahrzeugs. Wenn Sie den Code beachten, enthält er die zugehörigen Funktionen zum Fahren, Parken und zum Verbrauch von Kraftstoff.
Das Befehlsmuster fügt eine Abstraktionsebene zwischen Aktionen hinzu und enthält ein Objekt, das diese Aktionen aufruft.
In diesem Entwurfsmuster erstellt der Client ein Befehlsobjekt, das eine Liste der auszuführenden Befehle enthält. Das erstellte Befehlsobjekt implementiert eine bestimmte Schnittstelle.
Es folgt die grundlegende Architektur des Befehlsmusters -
Wie implementiere ich das Befehlsmuster?
Wir werden nun sehen, wie das Entwurfsmuster implementiert wird.
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)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Erläuterung
Die Ausgabe implementiert alle Befehle und Schlüsselwörter, die in der Python-Sprache aufgeführt sind. Es werden die erforderlichen Werte der Variablen gedruckt.
Das Adaptermuster fungiert als Brücke zwischen zwei inkompatiblen Schnittstellen. Diese Art von Entwurfsmuster fällt unter ein Strukturmuster, da dieses Muster die Fähigkeit zweier unabhängiger Schnittstellen kombiniert.
Dieses Muster umfasst eine einzelne Klasse, die für die Verknüpfung von Funktionen unabhängiger oder inkompatibler Schnittstellen verantwortlich ist. Ein Beispiel aus dem wirklichen Leben könnte ein Kartenleser sein, der als Adapter zwischen Speicherkarte und Laptop fungiert. Sie stecken die Speicherkarte in den Kartenleser und den Kartenleser in den Laptop, damit die Speicherkarte über den Laptop gelesen werden kann.
Das Adapter-Entwurfsmuster hilft beim Zusammenarbeiten von Klassen. Es konvertiert die Schnittstelle einer Klasse je nach Anforderung in eine andere Schnittstelle. Das Muster enthält eine Speziation, einen Polymorphismus, der einen Namen und mehrere Formen benennt. Sagen wir für eine Formklasse, die gemäß den gesammelten Anforderungen verwendet werden kann.
Es gibt zwei Arten von Adaptermustern:
Objektadaptermuster
Dieses Entwurfsmuster beruht auf der Objektimplementierung. Daher wird es als Objektadaptermuster bezeichnet.
Klassenadaptermuster
Dies ist eine alternative Möglichkeit, das Adapterdesignmuster zu implementieren. Das Muster kann unter Verwendung mehrerer Vererbungen implementiert werden.
Wie implementiere ich das Adaptermuster?
Lassen Sie uns nun sehen, wie das Adaptermuster implementiert wird.
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()
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Erläuterung
Der Code enthält eine Adapterschnittstelle mit verschiedenen Parametern und Attributen. Es enthält Adaptee sowie die Zielschnittstelle, die alle Attribute implementiert und die Ausgabe als sichtbar anzeigt.
Mit dem Dekorationsmuster kann ein Benutzer einem vorhandenen Objekt neue Funktionen hinzufügen, ohne dessen Struktur zu ändern. Diese Art von Entwurfsmuster fällt unter das Strukturmuster, da dieses Muster als Wrapper für vorhandene Klassen fungiert.
Dieses Muster erstellt eine Dekorationsklasse, die die ursprüngliche Klasse umschließt und zusätzliche Funktionen bietet, wobei die Signatur der Klassenmethoden intakt bleibt.
Das Motiv eines Dekorationsmusters besteht darin, zusätzliche Verantwortlichkeiten eines Objekts dynamisch zuzuordnen.
So implementieren Sie ein Dekorationsmuster
Der unten erwähnte Code ist eine einfache Demonstration der Implementierung eines Dekorationsdesignmusters in Python. Die Abbildung zeigt die Demonstration eines Coffeeshops im Format der Klasse. Die erstellte Kaffeeklasse ist abstrakt, was bedeutet, dass sie nicht instanziiert werden kann.
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'
Die Implementierung der abstrakten Klasse des Coffeeshops erfolgt mit einer separaten Datei, wie unten erwähnt -
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()))
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Das Proxy-Entwurfsmuster enthält ein neues Objekt, das anstelle eines vorhandenen Objekts, das als "reales Subjekt" bezeichnet wird, als "Proxy" bezeichnet wird. Das vom realen Subjekt erstellte Proxy-Objekt muss sich auf derselben Schnittstelle befinden, sodass der Client keine Vorstellung davon bekommen sollte, dass der Proxy anstelle des realen Objekts verwendet wird. Vom Client generierte Anforderungen an den Proxy werden über den eigentlichen Betreff weitergeleitet.
Die UML-Darstellung des Proxy-Musters lautet wie folgt:
Wie implementiere ich das Proxy-Muster?
Lassen Sie uns nun sehen, wie das Proxy-Muster implementiert wird.
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
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Das Proxy-Musterdesign hilft beim Replizieren der von uns erstellten Bilder. Mit der Funktion display_image () können Sie überprüfen, ob die Werte an der Eingabeaufforderung gedruckt werden.
Das Muster der Verantwortungskette wird verwendet, um eine lose Kopplung in Software zu erreichen, bei der eine bestimmte Anforderung vom Client durch eine Kette von darin enthaltenen Objekten geleitet wird. Es hilft beim Aufbau einer Kette von Objekten. Die Anforderung wird von einem Ende eingegeben und von einem Objekt zum anderen verschoben.
Mit diesem Muster kann ein Objekt einen Befehl senden, ohne zu wissen, welches Objekt die Anforderung verarbeitet.
Wie kann das Muster der Verantwortungskette umgesetzt werden?
Wir werden nun sehen, wie das Muster der Verantwortungskette umgesetzt werden kann.
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)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Erläuterung
Der obige Code erstellt einen Bericht für monatliche Aufgaben, in dem Befehle über jede Funktion gesendet werden. Es sind zwei Handler erforderlich - für PDF und für Text. Es gibt die Ausgabe aus, sobald das gewünschte Objekt jede Funktion ausführt.
In diesem Muster werden Objekte als Beobachter dargestellt, die auf das Auslösen eines Ereignisses warten. Ein Beobachter hängt sich an das Thema, sobald das angegebene Ereignis eintritt. Während das Ereignis eintritt, teilt das Subjekt den Beobachtern mit, dass es aufgetreten ist.
Das folgende UML-Diagramm zeigt das Beobachtermuster -
Wie implementiere ich das Beobachtermuster?
Lassen Sie uns nun sehen, wie das Beobachtermuster implementiert wird.
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()
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Erläuterung
Der obige Code erläutert das Herunterladen eines bestimmten Ergebnisses. Gemäß der Beobachtermusterlogik wird jedes Objekt als Beobachter behandelt. Es gibt die Ausgabe aus, wenn ein Ereignis ausgelöst wird.
Es bietet ein Modul für Zustandsautomaten, die mithilfe von Unterklassen implementiert werden, die von einer angegebenen Zustandsmaschinenklasse abgeleitet sind. Die Methoden sind zustandsunabhängig und verursachen Übergänge, die mit Dekoratoren deklariert wurden.
Wie implementiere ich das Zustandsmuster?
Die grundlegende Implementierung des Zustandsmusters ist unten dargestellt -
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)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Das Strategiemuster ist eine Art Verhaltensmuster. Das Hauptziel des Strategiemusters besteht darin, dem Kunden die Auswahl aus verschiedenen Algorithmen oder Verfahren zur Ausführung der angegebenen Aufgabe zu ermöglichen. Für die genannte Aufgabe können verschiedene Algorithmen ohne Komplikationen ein- und ausgetauscht werden.
Dieses Muster kann verwendet werden, um die Flexibilität beim Zugriff auf externe Ressourcen zu verbessern.
Wie implementiere ich das Strategiemuster?
Das unten gezeigte Programm hilft bei der Implementierung des Strategiemusters.
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()
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Erläuterung
Es enthält eine Liste von Strategien aus den Funktionen, die die Ausgabe ausführen. Der Hauptfokus dieses Verhaltensmusters liegt auf dem Verhalten.
Ein Vorlagenmuster definiert einen grundlegenden Algorithmus in einer Basisklasse mithilfe einer abstrakten Operation, bei der Unterklassen das konkrete Verhalten überschreiben. Das Vorlagenmuster behält den Umriss des Algorithmus in einer separaten Methode bei. Diese Methode wird als Vorlagenmethode bezeichnet.
Im Folgenden sind die verschiedenen Funktionen des Vorlagenmusters aufgeführt:
Es definiert das Gerüst des Algorithmus in einer Operation
Es enthält Unterklassen, die bestimmte Schritte eines Algorithmus neu definieren.
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()
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Erläuterung
Dieser Code erstellt eine Vorlage für die Zubereitung von Mahlzeiten. Hier stellt jeder Parameter das Attribut dar, um einen Teil der Mahlzeit wie Tee, Pizza usw. zu erstellen.
Die Ausgabe repräsentiert die Visualisierung von Attributen.
Das Fliegengewicht-Muster fällt unter die Kategorie der strukturellen Entwurfsmuster. Es bietet eine Möglichkeit, die Anzahl der Objekte zu verringern. Es enthält verschiedene Funktionen, die zur Verbesserung der Anwendungsstruktur beitragen. Das wichtigste Merkmal der Fliegengewichtsobjekte ist unveränderlich. Dies bedeutet, dass sie nach ihrer Erstellung nicht mehr geändert werden können. Das Muster verwendet eine HashMap zum Speichern von Referenzobjekten.
Wie implementiere ich das Fliegengewichtsmuster?
Das folgende Programm hilft bei der Implementierung des Fliegengewichtsmusters -
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()
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Das abstrakte Fabrikmuster wird auch Fabrik der Fabriken genannt. Dieses Entwurfsmuster fällt unter die Kategorie des kreativen Entwurfsmusters. Es bietet eine der besten Möglichkeiten, ein Objekt zu erstellen.
Es enthält eine Schnittstelle, die für die Erstellung von Objekten im Zusammenhang mit Factory verantwortlich ist.
Wie implementiere ich das abstrakte Fabrikmuster?
Das folgende Programm hilft bei der Implementierung des abstrakten Factory-Musters.
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())
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Erläuterung
Im obigen Programm erstellt die abstrakte Factory Objekte für jedes Fenster. Es ruft jede Methode auf, die die Ausgabe wie erwartet ausführt.
Das objektorientierte Muster ist das am häufigsten verwendete Muster. Dieses Muster ist in fast jeder Programmiersprache zu finden.
Wie implementiere ich das objektorientierte Muster?
Lassen Sie uns nun sehen, wie das objektorientierte Muster implementiert wird.
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))
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe
Erläuterung
Der Code enthält Klassenattribute und Instanzattribute, die gemäß den Anforderungen der Ausgabe gedruckt werden. Es gibt verschiedene Merkmale, die Teil des objektorientierten Musters sind. Die Funktionen werden im nächsten Kapitel erläutert.
In diesem Kapitel konzentrieren wir uns auf Muster mit objektorientierten Konzepten und deren Implementierung in Python. Wenn wir unsere Programme um Anweisungsblöcke herum entwerfen, die die Daten um Funktionen herum manipulieren, spricht man von prozedurorientierter Programmierung. In der objektorientierten Programmierung gibt es zwei Hauptinstanzen, die als Klassen und Objekte bezeichnet werden.
Wie implementiere ich Klassen und Objektvariablen?
Die Implementierung von Klassen und Objektvariablen ist wie folgt:
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()
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Erläuterung
Diese Abbildung zeigt die Art der Klassen- und Objektvariablen.
"Bevölkerung" gehört zur Klasse "Roboter". Daher wird es als Klassenvariable oder Objekt bezeichnet.
Hier bezeichnen wir die Populationsklassenvariable als Robot.population und nicht als self.population.
Das Iterator-Entwurfsmuster fällt unter die Kategorie Verhaltensentwurfsmuster. Entwickler stoßen in fast jeder Programmiersprache auf das Iteratormuster. Dieses Muster wird so verwendet, dass es hilft, sequentiell auf die Elemente einer Sammlung (Klasse) zuzugreifen, ohne das zugrunde liegende Layer-Design zu verstehen.
Wie implementiere ich das Iteratormuster?
Wir werden nun sehen, wie das Iteratormuster implementiert wird.
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")
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Wenn Sie sich auf das Muster konzentrieren, wird die Fibonacci-Serie mit dem Iteratormuster gedruckt. Bei gewaltsamer Beendigung des Benutzers wird die folgende Ausgabe gedruckt:
Erläuterung
Dieser Python-Code folgt dem Iteratormuster. Hier werden die Inkrementoperatoren verwendet, um die Zählung zu starten. Die Zählung endet mit einer erzwungenen Beendigung durch den Benutzer.
Wörterbücher sind die Datenstrukturen, die eine Schlüsselwertkombination enthalten. Diese werden häufig anstelle von JSON - JavaScript Object Notation verwendet. Wörterbücher werden für die API-Programmierung (Application Programming Interface) verwendet. Ein Wörterbuch ordnet eine Gruppe von Objekten einer anderen Gruppe von Objekten zu. Wörterbücher sind veränderlich; Dies bedeutet, dass sie je nach Bedarf bei Bedarf geändert werden können.
Wie implementiere ich Wörterbücher in Python?
Das folgende Programm zeigt die grundlegende Implementierung von Wörterbüchern in Python von der Erstellung bis zur Implementierung.
# 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)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Note −Die Implementierung von Wörterbüchern in Python weist Nachteile auf.
Nachteil
Wörterbücher unterstützen die Sequenzoperation der Sequenzdatentypen wie Zeichenfolgen, Tupel und Listen nicht. Diese gehören zum integrierten Mapping-Typ.
Die Lists-Datenstruktur ist ein vielseitiger Datentyp in Python, der als Liste von durch Kommas getrennten Werten in eckigen Klammern geschrieben werden kann.
Syntax
Hier ist die grundlegende Syntax für die Struktur -
List_name = [ elements ];
Wenn Sie dies beobachten, wird die Syntax wie Arrays deklariert, mit dem einzigen Unterschied, dass Listen Elemente mit unterschiedlichen Datentypen enthalten können. Die Arrays enthalten Elemente desselben Datentyps. Eine Liste kann eine Kombination aus Zeichenfolgen, Ganzzahlen und Objekten enthalten. Listen können für die Implementierung von Stapeln und Warteschlangen verwendet werden.
Listen sind veränderlich. Diese können bei Bedarf geändert werden.
Wie implementiere ich Listen?
Das folgende Programm zeigt die Implementierungen von Listen -
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])
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Die integrierten Funktionen von Python-Listen sind wie folgt:
Append()- Es fügt dem Ende der Liste ein Element hinzu.
Extend()- Es fügt Elemente der Liste zu einer anderen Liste hinzu.
Insert()- Es fügt ein Element in den definierten Index ein.
Remove()- Es löscht das Element aus der angegebenen Liste.
Reverse()- Es kehrt die Elemente in der Liste um.
sort() - Es hilft, Elemente in chronologischer Reihenfolge zu sortieren.
Eine Menge kann als ungeordnete Sammlung definiert werden, die iterierbar und veränderbar ist und keine doppelten Elemente enthält. In Python ist die Mengenklasse eine Notation der mathematischen Menge. Der Hauptvorteil der Verwendung eines Satzes besteht darin, dass er eine hochoptimierte Methode zur Überprüfung eines bestimmten Elements enthält.
Python enthält eine separate Kategorie namens Frozen Sets. Diese Mengen sind unveränderliche Objekte, die nur Methoden und Operatoren unterstützen, die ein erforderliches Ergebnis liefern.
Wie implementiere ich Sets?
Das folgende Programm hilft bei der Implementierung von Sets -
# 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)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Das eingefrorene Set kann mit dem folgenden Programm demonstriert werden:
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)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Die Warteschlange ist eine Sammlung von Objekten, die eine einfache Datenstruktur nach den Prozeduren FIFO (Fast In Fast Out) und LIFO (Last In First Out) definieren. Die Einfüge- und Löschvorgänge werden als bezeichnetenqueue und dequeue Operationen.
Warteschlangen erlauben keinen wahlfreien Zugriff auf die darin enthaltenen Objekte.
Wie implementiere ich das FIFO-Verfahren?
Das folgende Programm hilft bei der Implementierung von 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()
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Wie implementiere ich das LIFO-Verfahren?
Das folgende Programm hilft bei der Implementierung des LIFO-Verfahrens -
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()
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Was ist eine Prioritätswarteschlange?
Die Prioritätswarteschlange ist eine Containerdatenstruktur, die eine Reihe von Datensätzen mit den geordneten Schlüsseln verwaltet, um einen schnellen Zugriff auf den Datensatz mit dem kleinsten oder größten Schlüssel in der angegebenen Datenstruktur zu ermöglichen.
Wie implementiere ich eine Prioritätswarteschlange?
Die Implementierung der Prioritätswarteschlange ist wie folgt:
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
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Bei der Zeichenfolgenserialisierung wird ein Objektstatus in einen Bytestream geschrieben. In Python wird die "Pickle" -Bibliothek zum Aktivieren der Serialisierung verwendet. Dieses Modul enthält einen leistungsstarken Algorithmus zum Serialisieren und De-Serialisieren einer Python-Objektstruktur. "Pickling" ist der Prozess des Konvertierens der Python-Objekthierarchie in einen Bytestream und "Unpickling" ist das umgekehrte Verfahren.
Die Demonstration des Beizmoduls ist wie folgt:
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)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Parallelität wird oft als Parallelität missverstanden. Parallelität bedeutet, dass unabhängiger Code so geplant wird, dass er systematisch ausgeführt wird. Dieses Kapitel konzentriert sich auf die Ausführung der Parallelität für ein Betriebssystem mit Python.
Das folgende Programm hilft bei der Ausführung der Parallelität für ein Betriebssystem -
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)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Erläuterung
"Multiprocessing" ist ein Paket ähnlich dem Threading-Modul. Dieses Paket unterstützt lokale und Remote-Parallelität. Durch dieses Modul erhalten Programmierer den Vorteil, mehrere Prozesse auf dem jeweiligen System zu verwenden.
Anti-Patterns folgen einer Strategie im Gegensatz zu vordefinierten Designmustern. Die Strategie umfasst gemeinsame Ansätze für gemeinsame Probleme, die formalisiert werden können und allgemein als gute Entwicklungspraxis angesehen werden können. Normalerweise sind Anti-Muster entgegengesetzt und unerwünscht. Anti-Patterns sind bestimmte Muster, die in der Softwareentwicklung verwendet werden und als schlechte Programmierpraktiken angesehen werden.
Wichtige Merkmale von Anti-Mustern
Lassen Sie uns nun einige wichtige Merkmale von Anti-Mustern sehen.
Richtigkeit
Diese Muster brechen buchstäblich Ihren Code und bringen Sie dazu, falsche Dinge zu tun. Das Folgende ist eine einfache Illustration davon -
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))
Wartbarkeit
Ein Programm gilt als wartbar, wenn es gemäß den Anforderungen leicht zu verstehen und zu ändern ist. Das Importieren eines Moduls kann als Beispiel für die Wartbarkeit angesehen werden.
import math
x = math.ceil(y)
# or
import multiprocessing as mp
pool = mp.pool(8)
Beispiel eines Anti-Musters
Das folgende Beispiel hilft bei der Demonstration von Anti-Mustern -
#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
Erläuterung
Das Beispiel enthält die Demonstration guter und schlechter Standards zum Erstellen einer Funktion in Python.
Die Behandlung von Ausnahmen ist auch ein Hauptkriterium für Entwurfsmuster. Eine Ausnahme ist ein Fehler, der während der Ausführung eines Programms auftritt. Wenn ein bestimmter Fehler auftritt, ist es wichtig, eine Ausnahme zu generieren. Dies hilft bei der Eindämmung von Programmabstürzen.
Warum Ausnahmen verwenden?
Ausnahmen sind bequeme Möglichkeiten, mit Fehlern und besonderen Bedingungen in einem Programm umzugehen. Wenn ein Benutzer der Meinung ist, dass der angegebene Code einen Fehler verursachen kann, ist es wichtig, die Ausnahmebehandlung zu verwenden.
Beispiel - Division durch Null
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)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe -
Ausnahmen auslösen
Speziell in der Python-Programmierung werden Ausnahmen ausgelöst, wenn zur Laufzeit ein entsprechender Codefehler auftritt. Dies kann mit dem“raise” Stichwort.
Syntax
raise KeyboardInterrupt
Traceback (most recent call last):
...
KeyboardInterrupt