أنماط تصميم Python: للحصول على كود أنيق وعصري
نشرت: 2022-03-11دعنا نقولها مرة أخرى: Python هي لغة برمجة عالية المستوى ذات كتابة ديناميكية وربط ديناميكي. أود أن أصفها بأنها لغة ديناميكية قوية عالية المستوى. يحب العديد من المطورين لغة Python بسبب تركيبتها الواضحة ، والوحدات النمطية والحزم المنظمة جيدًا ، ومرونتها الهائلة ومجموعة الميزات الحديثة.
في بايثون ، لا شيء يلزمك بكتابة الفئات وإنشاء كائنات منها. إذا لم تكن بحاجة إلى هياكل معقدة في مشروعك ، يمكنك فقط كتابة وظائف. والأفضل من ذلك ، يمكنك كتابة نص مسطح لتنفيذ بعض المهام البسيطة والسريعة دون هيكلة الكود على الإطلاق.
في نفس الوقت ، فإن Python هي لغة موجهة للكائنات بنسبة 100٪. كيف ذلك؟ حسنًا ، ببساطة ، كل شيء في بايثون هو كائن. الوظائف هي كائنات ، كائنات من الدرجة الأولى (مهما كان ذلك يعني). هذه الحقيقة حول كون الدوال كائنات مهمة ، لذا يرجى تذكرها.
لذلك ، يمكنك كتابة نصوص بسيطة في Python ، أو فقط افتح طرفي Python وتنفيذ العبارات هناك (هذا مفيد جدًا!). ولكن في نفس الوقت ، يمكنك إنشاء أطر عمل وتطبيقات ومكتبات معقدة وما إلى ذلك. يمكنك فعل الكثير في بايثون. هناك بالطبع عدد من القيود ، لكن هذا ليس موضوع هذه المقالة.
ومع ذلك ، نظرًا لأن Python قوية جدًا ومرنة ، فنحن بحاجة إلى بعض القواعد (أو الأنماط) عند البرمجة فيها. لذا ، دعنا نرى ما هي الأنماط ، وكيف ترتبط ببايثون. سنشرع أيضًا في تنفيذ بعض أنماط تصميم بايثون الأساسية.
لماذا تعتبر بايثون جيدة للأنماط؟
أي لغة برمجة جيدة للأنماط. في الواقع ، يجب النظر إلى الأنماط في سياق أي لغة برمجة معينة. تفرض كل من الأنماط وتركيب اللغة والطبيعة قيودًا على برامجنا. يمكن أن تختلف القيود التي تأتي من بناء جملة اللغة وطبيعة اللغة (ديناميكية ، وظيفية ، كائنية التوجه ، وما شابه) ، كما يمكن أن تختلف الأسباب الكامنة وراء وجودها. القيود القادمة من الأنماط موجودة لسبب ما ، فهي هادفة. هذا هو الهدف الأساسي للأنماط ؛ ليخبرنا كيف نفعل شيئًا وكيف لا نفعله. سنتحدث عن الأنماط ، وخاصة أنماط تصميم Python ، لاحقًا.
تم بناء فلسفة بايثون على رأس فكرة أفضل الممارسات المدروسة جيدًا. Python هي لغة ديناميكية (هل سبق أن قلت ذلك؟) وعلى هذا النحو ، تنفذ بالفعل ، أو تجعل من السهل تنفيذها ، عددًا من أنماط التصميم الشائعة مع بضعة أسطر من التعليمات البرمجية. بعض أنماط التصميم مدمجة في بايثون ، لذلك نستخدمها حتى بدون علم. ليست هناك حاجة لأنماط أخرى بسبب طبيعة اللغة.
على سبيل المثال ، المصنع هو نمط تصميم Python هيكلي يهدف إلى إنشاء كائنات جديدة ، وإخفاء منطق إنشاء مثيل من المستخدم. لكن إنشاء كائنات في Python ديناميكي حسب التصميم ، لذا فإن الإضافات مثل Factory ليست ضرورية. بالطبع ، أنت حر في تنفيذه إذا كنت ترغب في ذلك. قد تكون هناك حالات يكون فيها ذلك مفيدًا حقًا ، لكنها استثناء وليست قاعدة.
ما هو الشيء الجيد في فلسفة بايثون؟ لنبدأ بهذا (استكشفه في محطة بايثون):
> >> import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those!
قد لا تكون هذه أنماطًا بالمعنى التقليدي ، ولكن هذه هي القواعد التي تحدد نهج "Pythonic" للبرمجة بأكثر الطرق أناقة وفائدة.
لدينا أيضًا إرشادات تعليمات برمجية PEP-8 تساعد في هيكلة الكود الخاص بنا. إنه أمر لا بد منه بالنسبة لي ، مع بعض الاستثناءات المناسبة بالطبع. بالمناسبة ، يتم تشجيع هذه الاستثناءات بواسطة PEP-8 نفسها:
لكن الأهم من ذلك: معرفة متى تكون غير متسق - في بعض الأحيان لا ينطبق دليل النمط. عندما تكون في شك ، استخدم أفضل حكم لديك. انظر إلى الأمثلة الأخرى وقرر ما هو الأفضل. ولا تتردد في السؤال!
ادمج PEP-8 مع Zen of Python (أيضًا PEP - PEP-20) ، وسيكون لديك أساس مثالي لإنشاء كود يمكن قراءته وصيانته. أضف أنماط التصميم وستكون جاهزًا لإنشاء كل نوع من أنظمة البرامج مع الاتساق والقدرة على التطور.
أنماط تصميم بيثون
ما هو نمط التصميم؟
كل شيء يبدأ مع عصابة الأربعة (GOF). قم بإجراء بحث سريع عبر الإنترنت إذا لم تكن معتادًا على GOF.
تعد أنماط التصميم طريقة شائعة لحل المشكلات المعروفة. يوجد مبدآن رئيسيان في أسس أنماط التصميم المحددة من قبل GOF:
- برنامج لواجهة لا تطبيق.
- يفضل تكوين الكائن على الميراث.
دعونا نلقي نظرة فاحصة على هذين المبدأين من منظور مبرمجي بايثون.
برنامج لواجهة لا تطبيق
فكر في كتابة البط. في بايثون ، لا نرغب في تعريف الواجهات وفئات البرامج وفقًا لهذه الواجهات ، أليس كذلك؟ لكن استمع إلي! هذا لا يعني أننا لا نفكر في الواجهات ، في الواقع مع Duck Typing ، نقوم بذلك طوال الوقت.
دعنا نقول بعض الكلمات حول أسلوب Duck Typing الشهير لنرى كيف يتناسب مع هذا النموذج: برنامج إلى واجهة.
نحن لا نهتم بطبيعة الكائن ، ولا يتعين علينا الاهتمام بما هو الشيء ؛ نريد فقط معرفة ما إذا كان قادرًا على القيام بما نحتاج إليه (نحن مهتمون فقط بواجهة الكائن).
يمكن أن وجوه الدجال؟ لذا ، دعها دجال!
try: bird.quack() except AttributeError: self.lol()
هل حددنا واجهة لبطتنا؟ رقم! هل قمنا بالبرمجة على الواجهة بدلاً من التنفيذ؟ نعم! وأنا أجد هذا لطيفًا جدًا.
كما يشير أليكس مارتيلي في عرضه التقديمي المعروف حول أنماط التصميم في بايثون ، "يستغرق تعليم البط للكتابة بعض الوقت ، ولكنه يوفر عليك الكثير من العمل بعد ذلك!"
يفضل تكوين الكائن على الميراث
الآن ، هذا ما أسميه مبدأ بايثوني ! لقد أنشأت عددًا أقل من الفصول / الفئات الفرعية مقارنة بإدراج فئة واحدة (أو في كثير من الأحيان ، عدة فئات) في فصل آخر.
بدلاً من القيام بذلك:
class User(DbObject): pass
يمكننا أن نفعل شيئًا كهذا:
class User: _persist_methods = ['get', 'save', 'delete'] def __init__(self, persister): self._persister = persister def __getattr__(self, attribute): if attribute in self._persist_methods: return getattr(self._persister, attribute)
المزايا واضحة. يمكننا تقييد طرق الفصل المراد كشفها. يمكننا حقن النسخة المثابرة في وقت التشغيل! على سبيل المثال ، هي اليوم قاعدة بيانات علائقية ، ولكن غدًا يمكن أن تكون أيًا كانت ، مع الواجهة التي نحتاجها (مرة أخرى تلك البط المزعجة).
التركيب أنيق وطبيعي لبايثون.
الأنماط السلوكية
تتضمن الأنماط السلوكية التواصل بين الأشياء ، وكيف تتفاعل الأشياء وتؤدي مهمة معينة. وفقًا لمبادئ GOF ، هناك ما مجموعه 11 نمطًا سلوكيًا في Python: سلسلة المسؤولية ، الأوامر ، المترجم الفوري ، التكرار ، الوسيط ، التذكارات ، المراقب ، الدولة ، الإستراتيجية ، القالب ، الزائر.
أجد هذه الأنماط مفيدة للغاية ، لكن هذا لا يعني أن مجموعات الأنماط الأخرى ليست كذلك.
التكرار
التكرارات مدمجة في بايثون. هذه واحدة من أقوى خصائص اللغة. منذ سنوات ، قرأت في مكان ما أن التكرارات تجعل لغة Python رائعة ، وأعتقد أن هذا لا يزال هو الحال. تعرف على معلومات كافية عن مكررات ومولدات Python وستعرف كل ما تحتاجه حول نمط Python المحدد.
سلسلة المسؤولية
يمنحنا هذا النمط طريقة لمعالجة الطلب باستخدام طرق مختلفة ، كل منها يعالج جزءًا معينًا من الطلب. كما تعلم ، فإن أحد أفضل مبادئ الكود الجيد هو مبدأ المسؤولية الفردية .
كل جزء من الكود يجب أن يفعل شيئًا واحدًا فقط.
تم دمج هذا المبدأ بعمق في نمط التصميم هذا.
على سبيل المثال ، إذا أردنا تصفية بعض المحتوى ، فيمكننا تنفيذ عوامل تصفية مختلفة ، كل واحد يقوم بإجراء نوع واحد محدد وواضح من التصفية. يمكن استخدام هذه المرشحات لتصفية الكلمات المسيئة والإعلانات ومحتوى الفيديو غير المناسب وما إلى ذلك.
class ContentFilter(object): def __init__(self, filters=None): self._filters = list() if filters is not None: self._filters += filters def filter(self, content): for filter in self._filters: content = filter(content) return content filter = ContentFilter([ offensive_filter, ads_filter, porno_video_filter]) filtered_content = filter.filter(content)
أمر
هذا هو أحد أنماط تصميم Python الأولى التي نفذتها كمبرمج. هذا يذكرني: لا يتم اختراع الأنماط ، بل يتم اكتشافها . إنها موجودة ، نحتاج فقط إلى إيجادها واستخدامها. لقد اكتشفت هذا المشروع الرائع الذي نفذناه منذ سنوات عديدة: محرر XML WYSIWYM لأغراض خاصة. بعد استخدام هذا النمط بشكل مكثف في الكود ، قرأت المزيد عنه في بعض المواقع.
يكون نمط الأمر مفيدًا في المواقف التي نحتاج فيها ، لسبب ما ، إلى البدء بإعداد ما سيتم تنفيذه ثم تنفيذه عند الحاجة. الميزة هي أن تغليف الإجراءات بهذه الطريقة يمكّن مطوري Python من إضافة وظائف إضافية متعلقة بالإجراءات المنفذة ، مثل التراجع / الإعادة ، أو الاحتفاظ بسجل الإجراءات وما شابه ذلك.
دعنا نرى كيف يبدو المثال البسيط والمستخدم بشكل متكرر:
class RenameFileCommand(object): def __init__(self, from_name, to_name): self._from = from_name self._to = to_name def execute(self): os.rename(self._from, self._to) def undo(self): os.rename(self._to, self._from) class History(object): def __init__(self): self._commands = list() def execute(self, command): self._commands.append(command) command.execute() def undo(self): self._commands.pop().undo() history = History() history.execute(RenameFileCommand('docs/cv.doc', 'docs/cv-en.doc')) history.execute(RenameFileCommand('docs/cv1.doc', 'docs/cv-bg.doc')) history.undo() history.undo()
الأنماط الخلقية
لنبدأ بالإشارة إلى أن الأنماط الإبداعية ليست شائعة الاستخدام في بايثون. لماذا ا؟ بسبب الطبيعة الديناميكية للغة.
شخص أكثر حكمة مما قلته من قبل أن المصنع مبني في لغة بايثون. هذا يعني أن اللغة نفسها توفر لنا كل المرونة التي نحتاجها لإنشاء كائنات بطريقة أنيقة بدرجة كافية ؛ نادرًا ما نحتاج إلى تنفيذ أي شيء في الأعلى ، مثل Singleton أو Factory.
في أحد دروس Python Design Patterns ، وجدت وصفًا لأنماط التصميم الإبداعي التي تنص على أن "أنماط التصميم توفر طريقة لإنشاء كائنات أثناء إخفاء منطق الإنشاء ، بدلاً من إنشاء كائنات مباشرة باستخدام عامل تشغيل جديد ."

هذا يلخص المشكلة إلى حد كبير: ليس لدينا مشغل جديد في Python!
ومع ذلك ، دعنا نرى كيف يمكننا تنفيذ بعضها ، إذا شعرنا أننا قد نحقق ميزة باستخدام مثل هذه الأنماط.
سينجلتون
يتم استخدام نمط Singleton عندما نريد ضمان وجود مثيل واحد فقط من فئة معينة أثناء وقت التشغيل. هل نحتاج حقًا إلى هذا النمط في بايثون؟ بناءً على تجربتي ، من الأسهل ببساطة إنشاء مثيل واحد عن قصد ثم استخدامه بدلاً من تطبيق نمط Singleton.
ولكن إذا كنت ترغب في تنفيذه ، فإليك بعض الأخبار الجيدة: في Python ، يمكننا تغيير عملية إنشاء مثيل (جنبًا إلى جنب مع أي شيء آخر تقريبًا). هل تتذكر طريقة __new__()
التي ذكرتها سابقًا؟ ها نحن:
class Logger(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, '_logger'): cls._logger = super(Logger, cls ).__new__(cls, *args, **kwargs) return cls._logger
في هذا المثال ، المسجل هو Singleton.
هذه هي البدائل لاستخدام Singleton في Python:
- استخدم وحدة.
- قم بإنشاء مثيل واحد في مكان ما في المستوى الأعلى لتطبيقك ، ربما في ملف التكوين.
- قم بتمرير المثيل إلى كل كائن يحتاجه. إنها حقنة تبعية وهي آلية قوية ويسهل إتقانها.
حقن التبعية
لا أنوي الدخول في مناقشة حول ما إذا كان حقن التبعية هو نمط تصميم ، لكنني سأقول إنها آلية جيدة جدًا لتنفيذ أدوات التوصيل السائبة ، وتساعد في جعل تطبيقنا قابلاً للصيانة وقابل للتمديد. اجمعها مع كتابة البط وستكون القوة معك. دائما.
لقد أدرجته في قسم الأنماط الإبداعية في هذا المنشور لأنه يتعامل مع مسألة متى (أو حتى أفضل: أين) تم إنشاء الكائن. تم إنشاؤه في الخارج. من الأفضل أن نقول أن الكائنات لا يتم إنشاؤها على الإطلاق حيث نستخدمها ، لذلك لا يتم إنشاء التبعية حيث يتم استهلاكها. يتلقى رمز المستهلك الكائن الذي تم إنشاؤه خارجيًا ويستخدمه. لمزيد من المرجع ، يرجى قراءة الإجابة الأكثر تصويتًا على سؤال Stackoverflow هذا.
إنه شرح جميل لحقن التبعية ويعطينا فكرة جيدة عن إمكانات هذه التقنية المعينة. تشرح الإجابة بشكل أساسي المشكلة في المثال التالي: لا تشرب الأشياء من الثلاجة بنفسك ، فذكر الحاجة بدلاً من ذلك. أخبر والديك أنك بحاجة إلى شيء لتشربه مع الغداء.
تقدم لنا بايثون كل ما نحتاجه لتنفيذ ذلك بسهولة. فكر في إمكانية تنفيذه بلغات أخرى مثل Java و C # ، وستدرك بسرعة جمال Python.
لنفكر في مثال بسيط على حقن التبعية:
class Command: def __init__(self, authenticate=None, authorize=None): self.authenticate = authenticate or self._not_authenticated self.authorize = authorize or self._not_autorized def execute(self, user, action): self.authenticate(user) self.authorize(user, action) return action() if in_sudo_mode: command = Command(always_authenticated, always_authorized) else: command = Command(config.authenticate, config.authorize) command.execute(current_user, delete_user_action)
نقوم بحقن أساليب المصدق والمخول في فئة الأوامر. كل ما تحتاجه فئة الأوامر هو تنفيذها بنجاح دون القلق من تفاصيل التنفيذ. بهذه الطريقة ، قد نستخدم فئة Command مع أي آليات مصادقة وتفويض نقرر استخدامها في وقت التشغيل.
لقد أوضحنا كيفية ضخ التبعيات من خلال المُنشئ ، ولكن يمكننا بسهولة إدخالها عن طريق تعيين خصائص الكائن مباشرة ، وفتح المزيد من الإمكانات:
command = Command() if in_sudo_mode: command.authenticate = always_authenticated command.authorize = always_authorized else: command.authenticate = config.authenticate command.authorize = config.authorize command.execute(current_user, delete_user_action)
هناك الكثير لنتعلمه عن حقن التبعية ؛ قد يبحث الأشخاص الفضوليون عن IoC ، على سبيل المثال.
ولكن قبل القيام بذلك ، اقرأ إجابة Stackoverflow أخرى ، وهي الإجابة الأكثر تصويتًا على هذا السؤال.
مرة أخرى ، أوضحنا للتو كيف أن تنفيذ نمط التصميم الرائع هذا في Python هو مجرد مسألة استخدام الوظائف المضمنة في اللغة.
دعونا لا ننسى ما يعنيه كل هذا: تسمح تقنية حقن التبعية باختبار الوحدة المرن والسهل للغاية. تخيل بنية يمكنك من خلالها تغيير تخزين البيانات أثناء التنقل. يصبح الاستهزاء بقاعدة البيانات مهمة تافهة ، أليس كذلك؟ لمزيد من المعلومات ، يمكنك الاطلاع على مقدمة Toptal للسخرية في بايثون.
قد ترغب أيضًا في البحث عن أنماط تصميم النماذج الأولية والمنشئ والمصنع .
الأنماط الهيكلية
مظهر زائف
قد يكون هذا هو نمط تصميم Python الأكثر شهرة.
تخيل أن لديك نظامًا به عدد كبير من العناصر. يقدم كل كائن مجموعة غنية من أساليب API. يمكنك القيام بالكثير من الأشياء مع هذا النظام ، ولكن ماذا عن تبسيط الواجهة؟ لماذا لا تضيف كائن واجهة يعرض مجموعة فرعية مدروسة جيدًا لجميع طرق API؟ واجهة!
مثال على نمط تصميم واجهة Python:
class Car(object): def __init__(self): self._tyres = [Tyre('front_left'), Tyre('front_right'), Tyre('rear_left'), Tyre('rear_right'), ] self._tank = Tank(70) def tyres_pressure(self): return [tyre.pressure for tyre in self._tyres] def fuel_level(self): return self._tank.level
ليس هناك من مفاجأة ، لا حيل ، فئة Car
هي واجهة ، وهذا كل شيء.
مشترك كهربائي
إذا تم استخدام الواجهات لتبسيط الواجهة ، فإن المحولات تدور حول تغيير الواجهة. مثل استخدام بقرة عندما يتوقع النظام بطة.
لنفترض أن لديك طريقة عمل لتسجيل المعلومات إلى وجهة معينة. تتوقع طريقتك أن يكون للوجهة طريقة write()
(مثل كل كائن ملف ، على سبيل المثال).
def log(message, destination): destination.write('[{}] - {}'.format(datetime.now(), message))
أود أن أقول إنها طريقة مكتوبة جيدًا مع حقن التبعية ، مما يسمح بقابلية توسعة كبيرة. لنفترض أنك تريد تسجيل الدخول إلى مقبس UDP بدلاً من ذلك إلى ملف ، فأنت تعرف كيفية فتح مقبس UDP هذا ولكن المشكلة الوحيدة هي أن كائن socket
ليس لديه طريقة write()
. أنت بحاجة إلى محول !
import socket class SocketWriter(object): def __init__(self, ip, port): self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self._ip = ip self._port = port def write(self, message): self._socket.send(message, (self._ip, self._port)) def log(message, destination): destination.write('[{}] - {}'.format(datetime.now(), message)) upd_logger = SocketWriter('1.2.3.4', '9999') log('Something happened', udp_destination)
ولكن لماذا أجد المحول في غاية الأهمية؟ حسنًا ، عندما يتم دمجها بشكل فعال مع حقن التبعية ، فإنها تمنحنا مرونة كبيرة. لماذا نغير الكود الذي تم اختباره جيدًا لدعم الواجهات الجديدة بينما يمكننا فقط تنفيذ محول يقوم بترجمة الواجهة الجديدة إلى الواجهة المعروفة؟
يجب عليك أيضًا التحقق من أنماط تصميم الجسر والوكيل وإتقانها ، نظرًا لتشابهها مع المحول . فكر في مدى سهولة تنفيذها في Python ، وفكر في طرق مختلفة يمكنك استخدامها في مشروعك.
مصمم
أوه كم نحن محظوظون! المصممون رائعون حقًا ، وقد قمنا بالفعل بدمجهم في اللغة. أكثر ما أحبه في بايثون هو أن استخدامها يعلمنا استخدام أفضل الممارسات. لا يعني ذلك أنه لا يتعين علينا أن نكون واعين بأفضل الممارسات (وأنماط التصميم على وجه الخصوص) ، ولكن مع Python أشعر أنني أتبع أفضل الممارسات ، بغض النظر. أنا شخصياً أجد أن أفضل ممارسات Python بديهية وطبيعة ثانية ، وهذا شيء يقدره المطورون المبتدئون والنخبة على حدٍ سواء.
يدور نمط الديكور حول إدخال وظائف إضافية وخاصة القيام بذلك دون استخدام الميراث.
لذلك ، دعنا نتحقق من كيفية تزيين طريقة ما دون استخدام وظيفة Python المضمنة. هنا مثال مباشر.
def execute(user, action): self.authenticate(user) self.authorize(user, action) return action()
الشيء غير الجيد هنا هو أن وظيفة execute
تقوم بأكثر من تنفيذ شيء ما. نحن لا نتبع مبدأ المسؤولية الفردية حرفيا.
سيكون من الجيد أن تكتب ببساطة ما يلي:
def execute(action): return action()
يمكننا تنفيذ أي وظيفة تفويض ومصادقة في مكان آخر ، في ديكور ، مثل:
def execute(action, *args, **kwargs): return action() def autheticated_only(method): def decorated(*args, **kwargs): if check_authenticated(kwargs['user']): return method(*args, **kwargs) else: raise UnauthenticatedError return decorated def authorized_only(method): def decorated(*args, **kwargs): if check_authorized(kwargs['user'], kwargs['action']): return method(*args, **kwargs) else: raise UnauthorizeddError return decorated execute = authenticated_only(execute) execute = authorized_only(execute)
الآن طريقة execute()
هي:
- سهل القراءة
- يفعل شيئًا واحدًا فقط (على الأقل عند النظر إلى الكود)
- مزين بالمصادقة
- مزين بترخيص
نكتب نفس الشيء باستخدام بناء جملة مصمم بايثون المتكامل:
def autheticated_only(method): def decorated(*args, **kwargs): if check_authenticated(kwargs['user']): return method(*args, **kwargs ) else: raise UnauthenticatedError return decorated def authorized_only(method): def decorated(*args, **kwargs): if check_authorized(kwargs['user'], kwargs['action']): return method(*args, **kwargs) else: raise UnauthorizedError return decorated @authorized_only @authenticated_only def execute(action, *args, **kwargs): return action()
من المهم ملاحظة أنك لست مقيدًا بوظائف الديكور. قد يشتمل المصمم على فصول كاملة. الشرط الوحيد هو أنها يجب أن تكون قابلة للاستدعاء . لكن ليس لدينا مشكلة في ذلك ؛ نحتاج فقط إلى تحديد طريقة __call__(self)
.
قد ترغب أيضًا في إلقاء نظرة فاحصة على وحدة أدوات Python الوظيفية. هناك الكثير لاكتشافه هناك!
خاتمة
لقد أوضحت كيف أن استخدام أنماط تصميم Python أمر طبيعي وسهل ، لكنني أيضًا أوضحت كيف يجب أن تكون البرمجة في Python سهلة أيضًا.
"البساطة أفضل من المعقدة ،" تذكر ذلك؟ ربما لاحظت أنه لم يتم وصف أي من أنماط التصميم بشكل كامل ورسمي. لم يتم عرض أي تطبيقات معقدة واسعة النطاق. أنت بحاجة إلى "الشعور" وتنفيذها بالطريقة التي تناسب أسلوبك واحتياجاتك على أفضل وجه. Python هي لغة رائعة وتمنحك كل القوة التي تحتاجها لإنتاج كود مرن وقابل لإعادة الاستخدام.
ومع ذلك ، فهو يمنحك أكثر من ذلك. يمنحك "الحرية" في كتابة تعليمات برمجية سيئة حقًا . لا تفعل ذلك! لا تكرر نفسك (جاف) ولا تكتب أسطر كود أطول من 80 حرفًا. ولا تنس استخدام أنماط التصميم عند الاقتضاء ؛ إنها إحدى أفضل الطرق للتعلم من الآخرين والاستفادة من ثروتهم من الخبرة مجانًا.