Design Patterns in Python | Sean Bradley | Skillshare

Playback Speed


  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Design Patterns in Python

teacher avatar Sean Bradley, Course Instructor

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

79 Lessons (5h 5m)
    • 1. Design Patterns In Python Introduction

      1:59
    • 2. Development Environment Setup

      6:07
    • 3. Coding Conventions

      7:58
    • 4. UML Diagrams

      6:24
    • 5. Factory Pattern

      5:59
    • 6. Factory Use Case

      5:58
    • 7. ABCMeta

      9:27
    • 8. Abstract Factory

      5:09
    • 9. Abstract Factory Use Case

      2:35
    • 10. Exception Handling

      5:48
    • 11. Builder Pattern

      5:52
    • 12. Builder Use Case

      4:47
    • 13. Python List

      5:06
    • 14. Prototype Pattern

      7:21
    • 15. Prototype Use Case

      6:22
    • 16. Python id() Function

      3:15
    • 17. Singleton Pattern

      5:38
    • 18. Singleton Use Case

      3:02
    • 19. Python Dictionary

      3:15
    • 20. Decorator Pattern

      3:05
    • 21. Decorator Use Case

      5:53
    • 22. Python __str__ Dunder Method

      2:04
    • 23. Python getattr() Function

      2:53
    • 24. Adapter Pattern

      5:00
    • 25. Adapter Use Case

      6:20
    • 26. Python isinstance() Function

      2:06
    • 27. Python time Module

      8:56
    • 28. Facade Pattern

      3:00
    • 29. Facade Use Case

      4:49
    • 30. Python Decimal

      1:49
    • 31. Python Type Hints

      3:53
    • 32. Bridge Pattern

      4:05
    • 33. Bridge Use Case

      2:02
    • 34. Python Tuple

      2:38
    • 35. Python *args

      3:23
    • 36. Composite Pattern

      4:31
    • 37. Composite Use Case

      1:49
    • 38. Conditional Expressions

      2:18
    • 39. Flyweight Pattern

      4:12
    • 40. Flyweight Use Case

      2:18
    • 41. Python String Justification

      1:19
    • 42. Proxy Pattern

      4:28
    • 43. Proxy Use Case

      3:51
    • 44. Python __class__ Attribute

      3:03
    • 45. Avoiding Circular Imports

      2:25
    • 46. Command Pattern

      3:48
    • 47. Command Use Case

      3:34
    • 48. Single Leading Underscore

      1:47
    • 49. Chain of Responsibility Pattern

      3:38
    • 50. Chain of Responsibility Use Case

      2:40
    • 51. Python Floor Division

      1:38
    • 52. Accepting User Input

      1:02
    • 53. Observer Pattern

      4:59
    • 54. Observer Use Case

      3:21
    • 55. Python Set

      1:50
    • 56. Interpreter Pattern

      7:51
    • 57. Interpreter Use Case

      6:11
    • 58. String Slicing

      3:02
    • 59. Python __repr__ Dunder Method

      1:43
    • 60. Iterator Pattern

      2:52
    • 61. Iterator Use Case

      2:56
    • 62. Python iter() Function

      3:04
    • 63. Mediator Pattern

      3:05
    • 64. Mediator Use Case

      4:24
    • 65. Memento Pattern

      4:54
    • 66. Memento Use Case

      2:58
    • 67. Python Getters/Setters

      3:06
    • 68. State Pattern

      3:28
    • 69. State Use Case

      2:34
    • 70. Dunder __call__ Attribute

      1:07
    • 71. Strategy Pattern

      2:15
    • 72. Strategy Use Case

      2:20
    • 73. Template Method Pattern

      5:19
    • 74. Template Method Use Case

      4:01
    • 75. Visitor Pattern

      7:46
    • 76. Visitor Use Case

      3:21
    • 77. Python hasattr() Method

      1:10
    • 78. Python expandtabs() Method

      1:26
    • 79. Summary

      1:25
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

173

Students

--

Projects

About This Class

This course is about common GoF (Gang of Four) Design Patterns implemented in Python.

A Design Pattern is a description or template that can be repeatedly applied to a commonly recurring problem in software design.

You will find a familiarity with Design Patterns very useful when planning, discussing, developing, managing and documenting your applications from now on and into the future.

You will learn these Design Patterns

  • Creational
    • Factory
    • Abstract Factory
    • Builder
    • Prototype
    • Singleton
  • Structural
    • Decorator
    • Adapter
    • Facade
    • Bridge
    • Composite
    • Flyweight
    • Proxy
  • Behavioural
    • Command
    • Chain of Responsibility
    • Observer Pattern
    • Interpreter
    • Iterator
    • Mediator
    • Memento
    • State
    • Strategy
    • Template
    • Visitor

Thanks for joining my course on Design Patterns in Python.

Meet Your Teacher

Teacher Profile Image

Sean Bradley

Course Instructor

Teacher

Hello, I'm Sean.

For over 20 years I have been an IT professional developing and managing real time, low latency, high availability, asynchronous, multi threaded, remotely managed, fully automated, monitored solutions in the education, aeronautical, banking, drone, gaming and telecommunications industries.

I have also created and written hundreds of Open Source GitHub Repositories, Medium Articles and YouTube video tutorials.

See full profile

Class Ratings

Expectations Met?
  • Exceeded!
    0%
  • Yes
    0%
  • Somewhat
    0%
  • Not really
    0%
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Design Patterns In Python Introduction: Okay, so welcome to my course on design patents. In this course, I'm going to take you through all 23 of the famous Gang of Four design patterns. We'll start the course off by setting up the environment, whether you're on Windows, Linux, or Mac, OSX. I'll discuss the coding conventions that are used throughout the course, such as hip height, Pylint, UML diagrams. Then we'll go through all the patterns, creational, structural, and behavioral as H patent is discussed, I will start off with demonstrating a conceptual example of the pattern with the source code so that we can see what problem it's trying to solve. Then we move on to a use case example of the patterns so that we can see it would in context of a simple story. And all source code is provided on this free website, but also in environments set up. I also describe how you can get that code is either through GitHub, we can download a zip or you can manually type the code from the pages. Now, we'll look at all the patterns like this with a conceptual example. Then I use case example. And then also at the end of every pattern, there will be discussions on the new path and concept that we would have learned in that patents. So for example, in the Builder, I'll introduce lists. In the prototype, I'll introduce the Python function in singleton or introduced a Python dictionary. And in every patent introduces one or more different parts and concepts that I'll teach you about, such as a decorator pattern. He introduced a dunder String method and also the python get attribute function. So all of these patterns, all the way down to the end, even finally at the visitor pattern, we're still learning about Python as well as the pens. So has attributed string expand tabs in the state, the call method, Momento parts and getters and setters. So it is basically a course on Python at the same time. So if you've never had experience with pause and then you will also find it beneficial. Okay, So thanks for taking part in my course and I hope to see you there. 2. Development Environment Setup: Okay, So development environment set up. You'll need to have Python in order to run the exercises. Now, install Python from python.org downloads if you install it using any other methods such as the Windows Store or other links, you're likely to have some kind of problems. So it's used out there. Now. That's the page it will take you to. Now it's given me a button or ready to download Python 3.9.2 or my operating system, which is perfect. I've already installed it, so I don't need to install it. So I've installed the 64 bit version, which was all automatically chosen for me and Python works. Now I can test the pause them works by typing that into a command prompt or PowerShell or Bash prompt or anything. So open up a command prompt or something on your computer or other terminal on your computer, you can open up command like so or PowerShell, which I'll be using PowerShell throughout this course. So I'm going to open up PowerShell there, zoom into it. And first thing I want to type is, as it says here, that one there, python hyphen v, notice the capital V there. And it tells me I have Python 3.9.2. If you don't have Python installed, it's going to give you an error, or it's going to say python 2.9 or 2.7, for example, like 2, what you want for this course is porcelain three-point nine, point two, or basically just anything Python 3, since all the code in this course will work on any version of Python 3. So there you go. Now notice that I used the word Python there on some systems such as Linux, depending on how you've installed Python, it can also be called Python 3. It's not called Python 3 on my Windows machine. But if I was on a Linux machine, this is Ubuntu 20.04. So if I type Python, I VE to, that is going to give me a problem. But actually Python is usually installed by default on modern Linux system. So if I was to type Python 3, 5 and b, it now tells me Python 3.8.5. Now that's good enough. All the code will work on their version of buttons, so I'm happy with that, but just be aware if you're using Linux, you will start Python using Python 3, most likely instead of Python, python V. under older versions of Linux, if you were to type husband, wife and v like that, it will either give you an error, what it does. Now. It will tell you Python 2.7 or 2.5. And think, what do you want to use as Python 3 plus? So you go on my Windows machine, I have Python 3 and I can verify that just by typing Python hyphen 3.9.2. Excellent. Now there is a lot of code is course. We looked through some of the pages. You can see there's code there. Now, you can copy this code and put it into folders if you liked. About the easiest thing to do would be to install it from either GitHub by using this command git clone, like so. That is if you have Git installed in your system, nor everyone does, or you can download a zip from this link here and online arcs, you would use the W get command and zip it using the command line. In the browser, you can just click it there, open it up, and then we go and there's all the code here, PY files we'll use throughout the course. Extract that into a location on your file system. I've already done that down here. E, design patterns in Python. Or you can even create your own folder like directory cd to it, and then start creating all the code manually by copying from the pages like a concept, you can copy that, copy to clipboard now and go into the command prompt and save that. But I don't need to do that's already downloaded it. And also, I recommend if you're on Windows to use Visual Studio Code VS code, I've already installed it. You can get it from here. The great thing about this is if I was to open up PowerShell, which I am, and I cd to the folder where I've extracted that zipper. So C, D, E, line patterns in Python. Okay, So I'm in that folder. I can DIR, I can just type C, O, D dot-dot-dot. And it opens up Visual Studio Code for me already with all the oils that are in that extract unzip base. So there we go. Now also, I have been using Python for quite a while on my computer. So VS Code is already set up. Use Python here. If your system has never used possible for you'll get a prompt to install the Visual Studio Code extensions. They are here. So down here, it starts down here, Python, the Python extension for Visual Studio Code. It already has prompted me to install that so I can see that it's working. So once that is installed, you should get a little down the bottom left here near my mouse, it says my interpreter I'm using is 3.9.2 64 bit, and that is all good. So I called straightaway, open up a terminal. So that's Control Plus single quote there. And it's opened up an integrated PowerShell console inside VS Code. So, and I'm already in the folder design patterns in Python, so I can type ls or DIR too, search the folder contents. So we go, oh, I can cd into the Assad or factory, older, once again ls. And now I can run Python on one of these scripts. First one I'll do was called factory concept dot python. Factory concept PY. Remember if you're using Linux or Mac OSX might have to type Python 3. And there we go. It's run the first Basic code in the course. But anyway, we'll discuss more about that in the section on the factory pattern. But that's the idea, that's the code that I just run anyway, is videos about making sure your environment is set up so we won't look at the code too much detail by the moment case. So there we go. There are other IDEs, or you could even just use Notepad if you really wanted to. And Windows File Explorer doesn't really matter. But I just find these tools very useful in helping you to understand what problems you might have in your code at design time. Okay, so in the next video, we'll look at some information about the coding conventions that I've used throughout the course. Excellent. 3. Coding Conventions: Okay, so before we get started into the design patterns, I also want to take you through the coding conventions that I'm using throughout the course. Now there were two ways of rotting pause and scripts in the course. One is using the interactive console and the other is using scripts star dot p-y or anything dot p-y, the PY extension. So we can create a new file called example dot p-y. So in Visual Studio Code, I'm in the root of my design patterns in Python project that I have just extracted from the zip and opened up my terminal, or mean to grant a terminal inside Visual Studio Code. And I can see it. I can press ls or DIR to list the contents. Ls is the same as DIR, but if you use Linux, you probably type ls quite a lot. So just in the root folder, just down here, create new file called example. So example dot p. Well that's a Python file. There's nothing in it. Put in this print Hello World, Copy to Clipboard, control S to save. And now I can execute that. So Python example dot p-y. Now, you might have noticed I didn't actually type out the full word example. Then if I just type some part of it and then press Tab, it fills it in forming. The fault system. Thinks, well, there's nothing else. It starts over dx. I'll just give you example P1. Okay, I go, it says, Hello world, excellent. So the one important thing, which is not something that you're going to notice in today's modern computers, but in the past, you would have noticed that the encoding was quite important. So UTF-8, most text editors or IDs that you use will allow you to create files in UTF-8 by default. So this file is encoded in UTF-8 characters. I can verify that. So if I open that in Explorer, open that in Notepad. It down here it says UTF-8. So debt is by default on Windows and most modern Linux too. I've seen it's UTF-8 by default. Python will also read UTF-8 by default, okay, So if you were using Python to, in the past, Python to default encoding was asking. So python three default encoding as UTF eight. So if I type Python three default encoding, UTF-8. So that's the first PY script that you can just quickly draw, just printing anything else you like print ABC123, Control S, and S is abc123. Now, another way of running Python is just by typing Python directly into the terminal of your choice or Python 3, and then just press enter and now you get the Python interactive console dose three greater than signs there and saying, We can now type Python directly without using a point in the script. So I could just type print Hello World, like so, hello world. Now at some points in the course, I'll be using the Python interactive console. Most every other time I'll be using a PY script. So all these files exist there. Py scripts already containing parsing instructions. Now to exit the interactive console, press Control Z it and press Enter, or you can type in, quit like that. Okay, so that's what that section is about. Now pip, pip stands for Python enhancement proposals. Now I'm using a proposal debate and this is about styling recommendations. So I can say my constants will be defined using uppercase style with underscores or class names will use Pascal case. And these are all things listed in PEP 8 down here see PEP 8, 000, 000, eight there. And we can look at that in the browser. A style guide for Python code is locked to read there if you want to read all about that anyway, that's the stall that I'll use throughout the course. So if also look at some sample code here, we can see that I'm using snake case there or Pascal case for class names, snake case for method names or attributes. Now you don't really have to remember all of these things. You can use a tool called Pylint, which will prompt you to use these styles already. So I've already installed Poland and say these fall here. I can say Pylint doesn't matter if I use dot EXE or not. Fly white and blue awaits concept. Why? It tells me your code has been rated ten at a 10. Now, if I didn't use a particular style, such as I use capital G there and a capital F for the gadfly way to function. It tells me method get floor away doesn't conform to snake case naming style. So let me just put that back and try Pylint again. There we go, 10 out of 10. So that tool Pylint I'm using to help me comply with peptides styling recommendations. Now, you can install Pylint if you want. I have, as you can see, so I just used it to go and have it. You can draw a pip install Pylint. Now, pip is the Python package install depending on your system, it might already be installed. When you install Python, you can type PIP hyphen v with a capital V again, and it tells me, please install a version 21. You might have to try pepper spray it on some version of Linux. I would actually also works on my Windows. Also, if neither of those work for you, you can also call pip from Python. So Python, I'm using Python not price than three M for module hip, I found the v, it will call the PIP module and it's the same. Information works good for me. So remember pip install Pylint if you want, it works for me and I have to do that. Install Pylint, like so it's already installed. Soft, you have Pylint installed. You can run Pylint on any of your files, File Int and the file name via concept of PY, and this is 10 out of 10. It's very useful. Now, most IDEs allow you to set the winter, which is used inside your IDE in Visual Studio Code, you can check by typing Control Shift P, Control Shift P. And it will give you the strop down allowing you to select which Linton currently I've got it set as Pylint. So there we go, Pylint, there's lot of different lenses to use, but I'm going to use Pylint throughout this course. Another way of getting that drop-down is pressing F1 and you can just type Python. It'll give you everything that is related. Awesome. So select. There we go. Okay, so it's very useful. Here is a list of the common warnings and errors that you might see throughout the course. If you're experimenting with code running around, there are hundreds of pilings warning error messages, but these are the most common ones that you'll find. And there we go. There's the message that you will see and then there's my interpretation of that message in context of the call. Very good. So moving on, command line interfaces, if you're not using PowerShell, like I am, you're using a different terminal, for example, CMD. So the difference here is the prefix C is C colon slash where it says PSE colon slash. So I'll just sit into the folder. So a CD design patterns and pause and we'll see it doesn't have PS written in front of it, but we can still do the same thing. I can still check and hyphen the. So anyway, if you're using Git Bash on Windows, it might look like this username at host naming 64 or on Linux, you can have different prompts if you're using route or if you're using a user or a Mac OSX, it will say host name, username. But anyway, it doesn't matter what terminal you're using. Python 3 and then your scripts or Python then your script as I'm doing now, Python example PY Pi 3 example PY anyway, the point is with this just showing you that whichever terminal you use, it's going to look different. I'm using PowerShell. Excellent. In the next section, we'll look at some UML diagrams. Okay, Excellent. 4. UML Diagrams: Uml diagrams. Now, UML diagrams are used throughout this documentation to help describe the patents. Below are some examples of UML diagrams. On the left here is a conceptual version and then there's a use case example on the right, and it's designed for all of them. Now this is a very quick introduction to UML, but I'm just showing you how I'm using UML to describe the patents anyway, classes usually. So a class is the square box here with the class name as the total. And then he got attributes and methods and attributes. You can have public and private, although Python doesn't recognize public and private accesses, but you can still name your variables in such a way, in path and to indicate that it should be treated as private, but more of that later. But anyway, so he's a class with attributes and methods which input a type and output a type that could be anything. And here's an example. A car has wheels, which is considered private or Boolean, whether it's running true or false. A method to start the engine which returns true or false, and a method to sit speed which requires a number. So sit speed 100. This is an example, anyway, directed association, the most intuitive way to draw relationships between classes is just to use a single line with a filled arrow that's directed association. That's just the easiest way to draw UML. So what I'm saying is class a, class B, or class a uses a method in Class B or an attribute. It doesn't really matter. An example, a person uses the car, so the person will start the engine, set the speed. So in order to portray some kind of relationship, the easiest thing to do is just use a straight line with a filled arrowhead and that's just a directed association. Now, moving on, we can be more specific about it. The relationships between classes. For example, we can say that a class extends another class. And now extending a class means the extended class also has the methods and attributes of the class that it has extended. So fancy car, Lamborghini or Porsche or something. And this is a standard car, has wheels running true or false, start engines set speed, but the fancy car has some extra, has a turbo and we can enable the turbine. So basically fancy car extends car. So fancy car also has, we'll count running, start engine set speed as well, plus the extras, so extends or inherits. And that is the unfilled arrow head with a line like that. Okay, So moving on a class that implements an interface, okay, so it's unfilled arrowhead with a dotted line. Now implementing is not the same as extending an interface has methods signatures, but the methods have no bodies. So the method body needs to be implemented in the class that is implementing. So also, I am prefixing more interfaces with a capital I. So I class name, ICA. So class I implements our class name. So class I will GET method, but method will have no body. So in class a, we have to tell it what the method body is by using Python instructions. So car, same thing, all the same methods as the icon, the interface car, but the implementation or the actual code that using the Start engine function or method is inside the car class. Now, we use interfaces to create rules when you're coding that a class must conform to a minimum standard, such as a must implement these methods. Now, we'll use a tool called ABC metta to enforce interfaces, but more about that later. So fancy car inherits car or extends car interface is method signatures only nobody in the methods. So aggregates class a, aggregates class B. That means that class I can see Solve one or more class Bs, example was a library consists of books. Now, the thing about aggregates is that both of these things could exist independently of each other. So books don't need libraries and libraries don't make books. So the library can be created and then we can add books when we have books. Okay? Composition, very similar to aggregates, except it's a field diamond. The class I is composed of class B, or the airplane is composed of wings. Now the difference between a composition and aggregate is that the class or the main class here cannot exist without the other classes that is composed of. So the airplane is not an airplane without wings. Okay, so that's an example of composition. Whether you use composition or aggregates is subjective. I mean, you could say a library doesn't exist where books, and then you'd use composition. An airplane without wings is not really an airplane. It's subjective. Could just be an airplane without wings. So anyway, moving on, pseudo-code annotation, sometimes it's useful to have an extra box or something to describe what the method is about. So here pseudocode dotted line with a dot next to the method, okay, So it's not real code doesn't have to be syntactically correct or anything. It's like a helper annotation to help the reader understand more about the context of what that method might be doing. So you will see that throughout some of the UML diagrams as well. Okay, So this is a very quick introduction to UML, just showing you the most common things in UML. Uml is not an exact science. If you were to do a search on the internet for factory UML diagram, you'd say a whole lot of different ways that people have drawn a UML diagrams. Not everyone can agree on the absolute correct way to do it. But anyway, what I've done is shown the most common ways of using UML diagrams, using the class with the attributes, the methods, directed association, which is good to describe the class I use this class be extending a class, can extend a class or inherit all the attributes and methods of a class, implements an interface. So the interface, a method signatures, but no method bodies, we have to implement those in the implementing class. Aggregates, a library aggregates books, composition and error applying is composed of wings and pseudocode annotations anyway. So in the next video, we will look at a factory patents. And we have a UML diagram in the factory pattern that we can look at. Excellent. 5. Factory Pattern: The factory design pattern. When you're developing your code, you may instantiate objects directly in methods or in classes. While this is quite normal, you may want to add an extra abstraction between the creation of the object and where it is used in your project. Now, what does that mean? What we're doing here is the factories about creating that extra abstraction between the creation of the object and where it is used. The factory pattern is, one of the first pattern is that everybody learns when they learn about patents. And so it's the easiest to understand. And this video is about showing you what that abstraction can look like. When the abstraction is added, it gives you extra benefits such as being able to dynamically choose which classes to instantiate at runtime. And based on some kind of logic, it just gives you more options. So good example is you might have a house and you have a chair in that house. And when you start the application, It's already there. By default, adding the factory pattern allows you will use R to dynamically choose i-j or NodeJS or many Chase or different kinds of chairs. So at runtime it's just an extra layer in-between where the object is created and where it's used. Okay, so excellent. Okay, So there are four terms that are related to the factory pattern within the first one is concrete credit. This is really just the same as the client application or a class or method that calls the factory method or the creator. Sorry, that's the credit down here. So the credo is the factory class that the main or client or concrete creator can access. Now the credo, depending on some attribute or logic inside it, will return a concrete product from one of the subclasses that it was assigned, and each of those products will conform to a product interface. So here is the UML diagram. He has declined application is a factory class, create objects. It aggregates 012 or many classes which all conform to the class interface which describes one method create object type type, gray object type type. It's just conceptual. This is just in order to try and demonstrate the concept behind the factory. And so in the sample code, we will ask for an object named b. And rather than creating be directly in the client, will ask the creator the factory for the object. Instead, the factory finds irrelevant class using some kind of logic from the attributes and the request. It then our subclass to instantiate a new object that it then returns as a reference back to the client asking for, okay, so here's the code here, but also you may have already downloaded at your computer, as discussed in the setting up the environment section, open up the factory folder and look at factory concept dot p-y. Okay, so these are small piece of code which demonstrates the factory pattern. There is the concrete creator, which is same as the client, which is using a creator. And that's the crater there, the factory class. And this is the correct object method in the factory class. So create objects, they are in the factory class and it will return either a concrete, a, B, or C, ending on some property that was passed in with some property equals a or B or C. Great object B, it will turn concrete product be concrete products, c, b and a. They all implement the AI product interface, and that's the oil products interface just here. It contains one method which is static and abstract. We'll discuss these in one of the next videos. But right now, that's all we need to see is that there are three different products which all implement the same interface. Which means that the factory method or the factory class doesn't have to do anything too complicated. It can just return either an a or B or C back to the client. Okay, so we can run that. So control single quotes, open up the terminal if you're using Visual Studio Code log me and my default shell is PowerShell. So, and that's the folder where I've saved all my files from a zip. So to start Python, you can use parse and the ECC or Parson doesn't matter. Factory, factory concepts presented and it just prints out a concrete product B in case this was doing Downing and this is the client. Product equals greater create object B. I could create a different object. Now create objects C, and it prints out concrete product C. So concrete products see when it's initialized, sets the name to be concrete product C. So the factory class instantiates a new object of concrete products. See, concrete product C is a class that implements the odd products interface. So before the factory, you may have been doing something like this in your project. You would say product equals concrete products a directly. So we can run that. And it looks okay, but you've suddenly decided you want that extra abstraction between, and that's when you decide to use the factory patterns. So instead of saying that, you'd say, well it's called the creator, the factory class, crater dot create object like that. Okay, concrete product, right, so that's really just what the factory pattern is. Is that extra abstraction? That extra abstraction means that you can delegate a task to someone else, say it's third party or someone who works for you. Can you please create me a concrete product D, and then down here in the crater, wherever that code is, whether that's in a different fall or a different API, or a different server, you can create a new option for concrete product D. So remember this is just conceptual about the factory pattern. In the next video, we will look at an example use case where this can be applied. Okay, So just at its simplest level, the factory pattern is really about adding that extra abstraction between the object creation and where it is used. And this gives you the extra options you can always extend in the future. Excellent. Next video, we'll look at the example, use case. 6. Factory Use Case: Okay, so now let's look at an example use case of the factory pattern as imagined that there's a user interface where the user can select from a menu of items such as chairs. A user has been given a choice is unknown, how many chairs a user will choose or which type of chair until the application has started. So when the user selects the chair, the factory then take some property involved with that selection, such as an ID type or other attribute, and then decides which relevant subclass to instantiate in order to return the appropriate object. So here is a UML diagram. Here's the client application down here, could be anything and it has access to a chair factory. So it says to the chair factory at some unknown time, get the chair and passes in an attribute and we get an object back. So the chair factory has in it a small chair, a medium chair in a big chair. And they all comply to the archea interface, which describes one method get dimensions. So doesn't matter which chair that the client asks for, the chair will have a method get dimensions because they all implement that method, since they all implement the interface. So there's the source code. I have this source code or setup since when I downloaded the zip. Okay, so the first fall I would look at is here in factory client dot py. So what I've done compared to the concept code is split up all the classes into their own files. So there's client, which is the main entry point. There is a chair factory class where you can see that that's the chair factory there. And they are the imports. It needs to know about big share, medium and small chair. There is a big chair class implements our chair. So it has a get dimensions method, returns its own height, width, and depth that was initialized when we instantiated the big chair and the beak share gets instantiated in the factory class, That's the chair factory. They return a big share. Those two brackets are saying, give me an instance of the class. So where the chair factory is being used, which is inclined to share factory, good cheer. Give me a small chair. Small chair. Well, at this point we don't know what kind of charities get dimensions. So just printing the dimensions out. So I go back this to small chair class is the medium cheer class. And there's the archea interface, just one method that all the classes that implement the armchair need to provide, okay? And it's a static interface method. We'll talk about these decorators in the next video. Excellent, so we can run this client.print. So Parthenon factory, client dot p-y. Okay, so it gives me a small chair, small cheer width, depth and height is 40. 40, 40. Let's try something else. Let's try big share, okay, with depths and high 8088, okay? So also notice that after calling the client PY, since it imports are the classes and those classes such as chair factory is also important as well. The crisis new folder called pi cash. These are the compiled bytecode of the PY files down there. So when you first run it, it will generate KYC for all your imports into irrelevant file called pi cash under factory. In this case, I need to do this once, but if I changed any of these files such as small chair, go to small chair and I changed it to 41 and I run that again. Or bringing a small chair would have rebuilt this small chair C folder in here. We can't really read that in the editor right now. But there is some texts that's compiled bytecode that the Python interpreter we use as safe to delete dose if you ever think you need to, because the next time you run it, it will regenerate it. There we go, and only has to do it once. I run it again, it's not regenerating those. It's using the existing unless I changed something in there. Okay, so let's look at a summary down here. So the factory pattern is an interface that differs the creation of the final object to a subclass. Okay, so that's what we saw here in the chair factory. We have the chair factory in a chair factory is returning the new object, so there's the client. So we're not creating a small chair directly in the client, such as give me a small share like that where deferring it to the factory, where the factory will credit and give it back to us. So the factory pattern is about inserting another layer or abstraction between instantiating an object and weight in your code is actually use. So when you want that abstraction, you don't always have to have it. It's when you want useful, but when you don't know how many objects you will need to runtime. For example, a user interface. You can press buttons, right? And you want to localized knowledge of the specifics of instantiating a particular object. What this means is the client here only has to say get me a small chair or a big chair or medium chair. But the specifics or the complications of that, the client doesn't need to know about it. And actually the factory doesn't really either. The factory is asking the specific class for the chair and the chair that is returned is complying to the IK interface. So it has one method get dimensions, okay? So you may want to create an external framework of some sort that you can import or reference. Okay, so here I've split these up into different files. These are all under my control. But you could have a third party or developer who looks after the interface chair, the medium, small and describes chairs or an API somewhere or a specific client develop on the client developer doesn't really need to know about the complications of all these inner classes and what's involved in those. The client developers just worried about the client. So it's allowing you to hide the details of the specifics involved in creating the foreign object or product. Okay, so especially the unique factor by the factory pattern is that the object creation is now deferred to the subclass that the factory has delegated to. Excellent. So in the next video, we'll talk about ABC meta. That is these things here where I'm using this abstract method, decorator and importing ABC. Okay, so excellent. 7. ABCMeta: Okay, so now it's time to talk about a new coding concept that was introduced in the factory pattern and that was ABC matter. Yeah, I see Meta classes are a development tool to help you to write classes that conform to a specified interface that you've designed. So ABC matter refers to abstract base classes. Benefits of using ABC Meta classes to create abstract classes is that your IDE and Pylint will indicate to your development time whether you're implementing or inheriting classes conform to the class definition that you've asked them to. Okay, so let's look at this UML diagram and we can see there are three chairs and they all implement the armchair interface, which describes the get dimensions method. Now, I could add a fourth chair and forget to add a method or even spell it wrong, or use a different method which doesn't conform to the arch here interface. Now, you're normally not going to know that that's a problem until runtime. But the IBC Meta classes will tell you what development time there is a problem to solve. Let's look at that in action. So open your IDE. Mine is VS code. So I want to open up cheer factory. So double-clicking that small chair and interface chair. Okay, so let's go to small chair and forget to implement get dimensions. So I'm just going to comment that out Control S to save. Now, if I press F1, start typing the word lint. Again option to run the Olinto. So let's talk that. And while idea is telling me now that there was a problem with factory, okay, so let's look at cheer factory. And it's telling me there that there's abstract class more chair with abstract methods instantiated D error message is not that clear when used in the IDE like this, but at least it's telling me that there's some problem with small chair. And also when you press F1 and you run linting from the VS Code IDE, it only checks the files that are open in the IDE like this. So that's just a small caveat. If you're using Pylint like that in the IDA, but actually Pauling runs better when you run it from the command line. So if I was to do a polling check on small chair like this, DO Pylint factory, small chair dot p-y. It actually tells me that method get dimensions is abstracting class armchair but is not overwritten. So Pylint has told me at design time or development time before I even run the program using Python, that there was a problem in the code. And there's no point in running the code. We can look and see there's a problem. If I was to run the code python factory client dot p-y, I was telling me there's a problem. Can't instantiate an abstract class. Small cheer with abstract method get dimensions and you eight weeks, there's a problem. Okay, so let's fix up the code. So just press Control zed and save, and then press F1 again and re-run linting in the IDE. So the error is no longer there. Okay, so the next thing, abstract interfaces are not instantiated directly in your scripts by instead implemented by subclasses that will provide the implementation code for the abstract interface methods example. In the last video, we didn't create armchair, but we credit a small cheer that implements the methods described in the ICT year interface. Okay, So the abstract interface method is a method that is declared but contains no implementation. So these two things together are really saying that you don't need to use ABC Meta classes and interfaces. You've credit in your final part in code, your code will still work without them. So let's look at this. So if I just remove the armchair interface from small chair. So now we look at the UML. Small chair is no longer implementing ICT year, but it will still work because I have the correct method there already. So it's not good to mentions here there's actually being executed. It's get dimensions in the small chair class that gets executed. So let's just run that and prove that it still works. Factory client PY, and they would go and it works. But at the same time, if I create a small chair and I forgot to add get dimensions or even spelled it incorrectly. Getting dimensions. And I press F1 and run linting will the IDA hasn't picked up there's any problems if I run the lintel on small chair like I did before. Pylint of factory small chair. While it's telling me there's an unused import, let's just tidy that up because I'm not using that anymore. And there's not a Pylint arrow missing functional method docstring. I'll just put something there that's pilot suggesting that. And let's try it again. Pauling factory small chair. Okay, so it tells me 10 out of 10. So right now there is a problem in that code is going to break, but we don't know that because their ID hasn't picked it up and neither has pilot. So let's try to run that code. Python factory client PY. And it tells me small chair object has no attribute get dimensions, right? So that's the benefit of using ABC Mehta. Okay, So let's add the interface. Press F1, run linting. Now the idea he's told me as a problem and the same thing with Pylint, pile into factory small chair PY method get dimensions is abstract in class but he's not right. So there we go. It doesn't matter that I haven't get dimensions is spelled incorrectly. So now I need to fix up this code and press F1 and linting. And there we go. No error is detected in the IDE or Pylint. I go on a trailing newlines. Let's just fix that one. Pauling doesn't look extra white-space, so unfold old, if just a format. There we go, Pilots small cheer 10 edits in. Excellent. And that should run Python. They'll go, That works. Okay, so let's look a little more closely now. This interface shear here where we import ABC Mehta and we also import the abstract method. That's because I'm using it just here. It's that abstract method decorator which is telling the IDE and Pylint that it must be overridden in the implementing class or inheriting class. So I can take that away instead. And I chair and that as well and also remove that because it's now unused and press F1 and run linting. So we have no problems there, but we still do have a problem. If I was to steal, forget to implement the dimensions method in the implementing class and 40 S, Okay, so F1 Pylint or 12, no problems detected. Now, what's happening now because of the removal of the abstract method decorator down here, it is inheriting the existing get dimensions, which actually doesn't do anything. So firewalls to run that Python xy factory client p y, it returns none. Small chair is now inheriting the get dimensions from my chair, which is not really an abstract interface anymore. You could say print, please implement. And there we go. We get an error at runtime saying please implement, but it's still not. Tell me a design time of the potential problems. So let's put ABC metabolic. Add the Meta class equals abc meter to the armchair abstract method. F1, run linting. And now we see the era at design time. There's a problem with small chair, okay? And we go IBC metal. That's what it's used for. It's a tool you don't need it. Your code will still work without it, but it's just very useful. One, run linting, I go. So the other benefit of using abstract Meta classes like that is it also helps other developers, so you might be working on your code that they need to conform to a particular interface. And also note throughout my code examples in the rest of the course, I will prefix interfaces with a capital I. So see here it says Share, and you'll see that throughout all remaining code as well. That is an interface. When I'm intending it to be an interface, that it will have an I in front of it. Okay, so the next little detail to be aware of here is the static method decorator here. Now, an abstract interface method doesn't contain any body, so there's no code and print anything or add numbers or run other path instructions is just a docstring is just a string saying it's a static interface message so it doesn't need to contain anything. So I'm using static method to enforce that if I took static method away like this. Now telling me there's a problem with the get dimensions function. It's saying method has no arguments. So it's expecting that I should at least have a self-reference, because methods inside a class by default expect at least a reference to itself. So that is now saying, okay, but having that self suggests also that I should be using that self somehow in the method body. So it's actually uselessly is so if you use the static method decorator, you can then just get away with that. So that's actually correct. It's just a static method, get dimensions. It actually doesn't do anything and that is okay. So that's why I use static method in this case here. So it doesn't matter that it contains nothing, just a docstring that does nothing because the inheriting class will implement the code in the abstract method. Get dimensions. Small chair, there we go. That's the actual get dimensions message. The actual body obligate dimensions method implemented in the small chair class, I guess that was ABC middle, and I'll use IBC meadow in almost all the examples in this documentation because it helped me at design time to make sure my code is correct. Excellent. 8. Abstract Factory: Okay, let's look at the abstract factory design pattern. Okay, so the Abstract Factory Pattern adds an abstraction layer over multiple other creational pattern implementations. So we've looked at factory, that's a question I'll patent. So build a prototype and a singleton. But in order to keep it simple, I'll just create an abstract factory over to factories. So it's just an extra abstraction to help you group factories and return products which are similar. For example, chairs and tables that we'll have two different factories apps, or you can even have chairs from different factories. Now the parts of the Abstract Factory are very similar to the factory. There's a client in the factory. It's known as the concrete creator. So same thing. There's the Abstract Factory, which is a layer over top of the other factories. There's the concrete factory, which is one of the sub factories, abstract product, which is an interface to the products of the factories employed to and the concrete product, the object finally returned. So let's look at the UML. Okay, So what we have in this section is a factory. And then down here there's another factory. So these are two different factories, factory I and factory B. And that's the factory method there for factories and factory B. And in the concept it's all about just creating object, creating object, grading object and the interface which saying that any factory that the Abstract Factory uses a or B must comply to the Abstract Factory interface. And it's just great object is very simple. And then there's the chlorine application. Okay, so in the code, there are three scripts. There is the Abstract Factory concept PY, which imports factory a and factory B. There is the interface with the crate object of set it up as a static method, abstract method I'm using ABC metal is the Abstract Factory, and we can ask six possible products from the Abstract Factory. And depending on the name of the product, it will, or the US factory a, factory B. And there's two examples, and there's the script for factory I, which is very similar to the factory concept is the same script essentially, but the class name is factory a. And then if we go for the Data Factory be exactly the same except the class name is factory B. So these are potentially completely different factories, perhaps from different APIs or different endpoints on the Internet or different libraries. Okay, so open up the code and I'm in the Abstract Factory folder this time. And there's a lot of falls in there to start with, we're looking at abstract factory, concept factory, and factory B. Okay, So these are the three files that are part of the first section of this abstract factory tutorial. There's the code there. We can see factory. And down here the client product, Abstract Factory, create object IB. And then I'm just printing out the class name so that we can see that it is a factory, a, factory B. At this point in time, the method exposed by the Abstract Factory doesn't really indicate to the client which factory is going to go to. Although we can tell pretty obviously it's going to go to a factory a and we be, It's just, this is conceptual. So we can run that Abstract Factory, Abstract Factory concepts. And then we go, the first product return is a type of factory a, concrete product B, and the second product is a type of factory be concrete product C. So we can say, well give me an AA and BA like that and we go, factory eyes, concrete product a, factory B's concrete product a. And here is the logic to decide which factory is going to go to. So in the abstract factory there. So that's really how to think of it as another abstraction over existing factories which might have similar products or products that you can group in some way. And not only do they need to be factories, they can be other creational patterns such as Builder, Prototype will singleton. But for this example, I've just used the factory because that is going to be the easiest way to imagine it. But I think after completing those sections, that will make sense. Okay, So just really quickly use when you want to provide a library of relatively similar products from multiple different factories, okay, So you want the system to be independent of how many products are created. This is the same as the factory. You don't know how many products you're going to have until runtime could be anything 0 or many of all kinds of types. Okay? So like I just said, it fulfills all the same use cases is a factory method, but it is essentially a factory for other creational patterns implementations, okay, So the client implements the abstract factory interface rather than all the internal logic of the factories, then this allows the possibility of creating a library. The Abstract Factory differs the creation of the final products objects to its concrete factory. So classes just like the factory, because it's using factories, you want to enforce consistent interfaces across products and you want the possibility to exchange product families. So anyway, so the simplest way to understand it is just a factory for factories. So in the next video, I'll create a use case example, which builds on the factory use case. So we have two factories. One that returns chairs and tables. Okay, Excellent. 9. Abstract Factory Use Case: Now for the Abstract Factory example use case. So the example is you may have a furniture shop. You sell many different kinds of furniture. You sell chairs and tables. And they are manufactured at different factories using different unrelated processes that are not important for your concern. You only need the factory to the liver. So basically the client down here in the UML doesn't need to be concerned about the workings of all the things that go on in the factories to down here we're using the, the Abstract Factory to manage those two factories. Okay, so very similar to the concept example, except within the context of chairs and tables. So small chair, medium, big, etcetera. Each of the pieces of furniture, they have a common attribute, white with depths, and a common method get dimensions. So furniture factory, they can get the chair and the chair factory or get a table from the table factory. And from the client perspective, the client doesn't know about the differences between each of these factories. So it's going to use the get furniture method. So client get furniture and the factory will decide depending on which furniture that is, whether to go to the chair factorial, a table factory. So source code open up Abstract Factory, client.print. This is the client part of the application. All of the other files, such as furniture factory, have been split up further into other files and other imports. So this chair factory table, factory chair, factory, small chair, medium gym, big share as a big cheer, et cetera. You can see how you can import KML file quite small and compact like that and just have the more new folder and your client, it's very similar to the concept example. I'm just creating two different kinds of furniture. Furniture factory get furniture is time. It's a small chair, would just print out the class and then run the Common get dimensions method on it. Same with medium table. So let's run the factory example. So python, abstract factory, client dot p-y. There we go, prints out small chair and a medium table. So with different dimensions, 40, 40, 40 is a 110, 1760. And we could have a big table and a medium chair if we like. There we go. Meme share in BigTable. So there's nothing new really in the abstract use case example, just the fact that it's being used within a new context of chairs and tables. Okay, So looking at the code in more detail, such as the furniture factory here, I've introduced a new concept and that is exceptions. So in the next video we'll talk about exceptions or exception handling. Okay, Excellent. 10. Exception Handling: Okay, let's look at a new cutting concepts. Exception handling your Python code might reduce errors, happens to everybody. It's hard to perceive all possible errors, but you can try to handle them in case anyway. So use the Troy excepts and optional finally, keywords to manage error handling. So in example code, if no chair or table was returned, exception error is raised and it includes a text string that can be read and written to the console. So down here in, get furniture in the actual code, and get furniture if the code gets to this point here, it means we haven't actually found a chair or table. So I raise an exception. No factory found or I could decide no furniture found. And then in the except down here, if I get an exception or put into a variable E, and then just print that out. And the code actually isn't ever going to get there if we find finish it because we are returning here before we even get to there. Okay, so let's try that out. Will request a wooden table and we'll see what kind of error we get. So inclined dot p-y. Let's look for a wooden chair and ROM Matt. Point dot PY says, No factory found. Okay, so is why asked to do so? We've got to that point or just raise an exception saying no factory found. So did printed that out. Now, don't always have to rise an exception like I did in that case, there are some exceptions will just happen if there is wrong input of some sort. So to demonstrate that, we'll use this small piece of code here. So I copy that. I've copied it to the clipboard now and we'll go into the code. Bottom here is just create a new file called test.py and paste that in. So Control S to save. Now it's run that Python test.py and my ID is only told me there's a problem here, but we're going to set a problem when we run the program, okay, an unknown error occurred. I'm just printing out, except an unknown error occurred. The actual problem is we have an undefined variable, but my program, when I run it, it printed, an unknown error occurred because I just did that in the broad exception here. And finally, we can see what finally does. Finally just gets run anyway. So this is optional, get caught even if there is no error. So let me just do print one, prince one, and it also runs the finally lawn. Now what I've done here versus what I was doing here, where else? Manually raise an exception and then catching that exception here is an exempt keyword here, any exception at all. I'm just going to print that out. So this is I brought exception. And this is actually a broad exception as well because the exception is actually a base class. But we'll come on to that in a moment. Instead, what I can actually do is capture a specific kind of error so far, just add a new except here we'll catch a undefined variable exceptions. So in poison, that is called a name error. So except name error. So this is a particular kind of error that our program has detected and that's a name error occurred. A name error occurs. So this time it's not actually going to get that line. It's going to take the name error, a name error occurred, and to finally lawn Ren also, once again it's optional. A name error occurred. Okay, So you can add exception handling for as many types of errors as you like to read more about all the different kinds of errors that you can get in poison. Well, there's lots of them. You can read the official Python tutorial on errors. So let's look at the code again to see what I've done. I've got a Troy except I have no finally in this sample code, but I also manually raise an exception, and it's called exception, a broad exception, and then just print out the custom texts that I've decided to ride out in the test here, I've got a different kind of exception. Myvar happens because I haven't declared the variable and debug it a name error, I'll print out a NameError, otherwise, any other kind of error went down on non error occurred. But even so, let's just demonstrate what happens if I declare myVar. Myvar equals 0 initialized now, okay, 0 and the fondly law install reign. So you will see try except, maybe multiple excepts, and finally, throw out other people's code. Okay, now another small detail, this is known as a broad exception. Exception is a base class. It's best practice not to use the exception base class to try and find more specific errors or even rise more specific errors. So I'll just show you that if I just do Pylint on these furniture factory fall here, Pylint, abstract furniture factory, the pile and error catching too general exception, exception, broad exception. So while there's still works, and we can see that it works because I'd just do a search for wooden table before we can be more specific and particular kind of error that you could raise here is a value error. Value error with our text string as well too, I could say, except value error as a print a, we're looking for a value error and falling back to an exception error. And it's just run. Abstract factory client says No factory found. So value error works now, but we haven't fixed up the silent era or the Pylint warning just yet. Let's do the Pylint check says still catching too general exception, exception. So it doesn't matter, I can just remove that. And Pylint is now happy to entertain. So they are options. And you can see the code does exactly the same thing. But instead of me saying raise exception error and catching the exception error, I'm just using a value error that fixes the pilot warning. Okay, so excellent member read more about areas here. If you look in the next section, we'll talk about the buildup at Excellent. 11. Builder Pattern: Let's look at the builder design pattern. Now the builder pattern is also a creational pattern whose intent is to separate the construction of a complex object from its representations so that you can use the same construction process to create different representations will demonstrate that guy. So build a patent, tries to solve how can a class create different representations of a complex object? How can a class that includes creating a complex object be simplified? Okay, so we'll demonstrate those two points as well to the building. The factory patterns are very similar in the fact that they both instantiate new objects or runtime. The difference is when the process of crony object is more complex. So rather than a factory returning a new instance of object a, it cause a buildup. The constructor method object a dot construct. So that goes through a more complex construction process involving several steps and both return an object or product. Okay, so product, that's the product or the object that is returned and that you can use. And the client and the builder builds the concrete product and implements the AI Builder interface is the Boolean to face there. The interface to the concrete builder should implement. And a director has a construct method that when call grades to customized products go the UML diagram is declined. And as a director, and there's the director which is like a convenience class which calls the builders construct method here. And the builder can then go build Part a, Part B, Part C, or none at all, or part C In part. I shouldn't really matter in what order or even does it at all. And then finally, we get the product back, the director and then the client. So anyway, the source code, the client creates a director. Yeah, the client calls the directors construct method, which then meninges each step of the build process. So the director saying build Part a or Part B directed and returns a proxy the client. Alternatively, you could create a specific method to retrieve it later, we'll see that in the example use case. So here's the code. You're going to open up Visual Studio. So build a concept wise in there, build a folder there, build a concept. So if we look at that, there is the interface here with several methods. Build Part a, Part B, Part C, and a method to get the final product. So get resolved, we're trying to final products abstract, aesthetic, the builder class, which implements the AI Builder. When you instantiate a new builder, you will call the init method, which will create a product. And this product down here is just a minimal object that contains one attribute called parts, which happens to be a list as the two square brackets there, we'll talk about lists in the next few videos. Okay, so back to the builder class. These are the implementations of the methods as outlined in the interface. And they don't do much in the concept example. They just appending a letter to the products parts list. Okay, So the director, we have a construct method, construct some attorneys to final products. So return builder, accrediting new Builder, which we'll call the builders init method, which creates a product. We can then build Part a, Part B, Part C, and get the final result down here in the client that's redu product director, construct, print product dot parts. So from the client perspective, it's really simple. That's Control single quote to open up the, so I'm going to pass in the order. They were a concept of PY and there we go. It's just printing out the list or the parts of the product. So product parts atmosphere list. So here I've essentially just built Part a, Part B, Part C. If you look at those methods again, they are appending to the parts list and a, b, c. So we see a, B, C. Now what the building you should, I'm for each of these methods here to be able to be called independently or in any order. For example, I can comment out build party and C, and that will still work. Actually, I have to fix up the formatting a little bit there. So Build part, I get result. Okay, so it just returns a or I could just say Build part B, go get resolved or I'm pressing Control zed now. Or it can also be done in any order. So CIB, control, if to get rid of that white space, there we go, see a Python is very whitespace sensitive, so you might find those unexplainable errors some time. I'll just show that to your Properties control zed on Visual Studio Code, it shows me like a very faint gray indicating there's a whole lot of spaces they have. Now you wouldn't expect that to really be a problem, but Python tree, so that's a problem. So if I save that and run that again, we'll see the error again. So unexpected character after line continuation character so that we get That's slash day. I'm just continuing the line to the next line. That's an alternate way of saying that. So works. So pause and Xc, I go. But sometimes paul, it might say the line is too long. So in that case, you can do things like add a line continuation character like that, and the line carries on to the next. Okay, So if we go down to the summary, down the bottom here. So the builder pattern is a creational pattern that is used to create more complex objects. Then you'd expect from a factory, sequence each of the steps there and we'd get the final product. The builder pattern should be able to construct complex objects in any order and include exclude whichever available components it logs. So we saw that we can remove an option if we like, or we can remove them altogether. Now we'll just return an empty product with no parts, okay, So for different combinations of products that can be returned from a builder uses specific directive, create the B spoke of combinations. So down here, I've created one director, but we'll see the use case at all quite different directors that will return different combinations of the builder. So you can also use the Abstract Factory to add an abstraction between the client and the director if you like. So basically if we go back to the abstract factory and the factory concept there, Let's say hypothetically that factory I was a builder and you go create object and you'd call its constructor method like so. Okay, so in the next video, we'll look at a use case of the builder pattern. Well, quite different kinds of houses. Excellent. 12. Builder Use Case: So let's look at the builder example, use case, and we'll use it with, in the context of a house builder. There'll be multiple directors. They can create their own complex objects. And note that the three directors down here, the igloo director, will not use all the methods of the house builder. The builder can construct complex objects in any order and include, exclude whichever parts that likes. There's a client application. It aggregates some directors which will construct their own particular kind of house using the house builder, which provides a set of functions that are all optional. And there's the house objects which will be returned back to the client, the source code, we order client. Why in Visual Studio code? So build a client PY, and I've got this three directors, construct, construct, construct. So we've now have an igloo castle and a houseboat. And I'm just calling one of their methods construction, which actually just prints out a string of the elements of the construction. So we'll see that. And so down here in the terminal, Python build a client.print EY, There we go. It's deconstruction method. There's printing out this line. This is a ice Eagly with one doors and 0 windows. This is a sandstone castle. That's the castle with 100 doors and windows. It has by construction, would houseboat with six doors and windows. So it's the same builder, but it's produced these different kinds of products. Okay, so let's look at these individual directors more closely. Igloo director is calling several methods. If I can compare that with the class will director, the castle director also calls the CIT number of windows with different properties. So you can see that there is a different stays in the house Botha about using different methods of it and then getting the final result. And within the house dairies, one method call construction, which prints out just using an f string. This is a self.age war material, self.age building type with self.age doors. There we go. And you can see that working down the bottom there. So let's look at how these directors are working now. So each of these directors that I built as one method called construct static method. When I use this in the client, you see here igloo director is a class that I'm calling one of its methods directly. So I'm not saying give me an igloo director and then construct. I'm just saying, let's just call the igloo directors construct method directly. So the constructor method is a static method inside the class. We don't need to instantiate it here, the directors, so IGA director straightaway has no init method, but it has one method construct which is a static method. If I took that static method away, like that, I then get an error saying method has no argument. It will be expecting me to type in self. And then if I go back to the client, It's now telling me that is not instantiated, so I'd have to call it like that. So then what's happening now is igloo directors being instantiated and Dana's calling constructs. So let's try that. Okay, works. But if I go back to UCLA, director self is unused. I'm not actually using software anywhere, so I take that away and convert it back to a static method so the class can be used directly without instantiating it. I'm just using its static method, their core construct which instantiates a new house builder and gets the result like this. So very good. So that's one option you have if you want to minimize the amount of code that makes up your classes. And another thing which I mentioned in the previous video, a director can also provide a method for the client to retrieve it later. So I'll show you that igloo director here in a static method instantiating the house builder and we're setting all the different properties of it and then getting a result. We didn't have to do it like that. We can say house build a house builder and then say house builder, dot set, building type, igloo, house builder. Or material ice now spilled a set number of doors, one, and then return house builder dot get result. And we can see that working. There we go. The Igloo has printed out. Now the benefit of doing this is if you wanted to construct a product over time, for example, this director could be a wizard in an application. You could do some things, you could do some other things. So your product is being built over time. And then finally at some other point, you then just return the final product anyway, controls it. Okay, So there's a use case of the builder design patent where I've drawn three different directors which do different things. They use the same construction process but with different properties and perimeters end, what is output is something that is quite different but related in some way, as you can see down here, when I'm printing out the representations of it. Okay, so in the next video, we'll look at the new coding concept of the Python list. 13. Python List: Okay, new coding concepts, Python list, this time in the file builder, build a concept PY, I create this list here. Self.age equals a new list. So down here, there it is there two square brackets that indicates a Python list. The list can store multiple items. They can be changed. They can have items added and removed. They can be reordered, they can be prefilled with items when instantiated, and it's very flexible. So I'm going to use the Python interactive console his time. So I'm going to use the inbuilt terminal in Visual Studio Code, you could just open up PowerShell command or Bash, whatever you wanted to just type in Python like that and press Enter. So those three arrows, destine interactive, shell and l. So we can just type Python code directly, as I discussed in one of the videos at the beginning of the course. But anyway, what I'm gonna do is create a new list. So here I'm incredible new list called items. So items equals square brackets like that. Now we can just print out items by typing items and it's an empty list. We could also say print items, but the default behavior in the interactive shell just calls the internal printed as a string function case. So let's append two items to that list. First one, I'm going to append a string, appending a string with single quotes in it. So that's the string, but it's got single quotes in it, so it's quite a complicated little string. Okay, another one. These aren't real words, they're fictional words that probably good for you. Some examples. Let's look at items now. Item says two items in it to both strings. We can add some more items to that by using extend. Extend, we'll add them to the end. So let's look at items again. I mean added to the end. Now note here that these first two are wrapped in inverted commas like that. That's because they contain an inner quote, whereas these ones are just wrapped it into single quotes. That's the default behavior. But since the string is little bit more complicated, It's got a single quote and it already, it's wrapping it in double-quotes, but they're still strings. So we can reverse. Let's reverse that. List. Items dot reverse. Now we're going to look items now gets reversed. We can remove one of the items. So we'll remove a boy name. So items remove yanked. There we go. It doesn't exist. Now, let's insert a new word. So I'm inserting at position 1 folk, so it should say super fluidity folk worst. Okay, let's look at that items. Super fluidity folk worms shouldn't have. Let's append worst items. Okay, so we'll look at different kinds of collections later on throughout the course. But one thing to note here about lists is that you can have duplicates. So worms, whoops, they're duplicates. Let's count how many worms are in their items count worst, there are two wimps in there. Okay, Let's check the length of the list, looking at how many items in the list. So length of items was five. Let's change the item at position 2. Now, the list is zero-based, so that's 01 and that's two. So it's going to change the value or the item at position today which is worst. So items to now equals bag most items. And I go back nice. So that's a list. 14. Prototype Pattern: Okay, the prototype design pattern and the prototyped design patent is good for when creating new objects requires more resources than you want to use will have available. You can save resources by just creating a copy of an existing object that is already in memory. Example, a fall you've downloaded from a server may be large, but since it's already a memory, you can just clone it and work on a new copy independently of the original. So now you have two objects in memory, but you only went to the disk network once, right? So in the prototype Patton's interface, you create a static clone method. They should be implemented by all classes that use that interface. So how the climb method is implemented in the concrete class is up to you. You need to decide whether a shallow or deep copies required. Now this is quite important about copying and all repeated many times in the code. And as I'm talking, but a shallow copy copies and creates new references one level deep and deep copy copies and creates new references for all levels. In Python you have mutable objects such as lists, dictionaries, and sets, and any custom objects you credit. Mutable means changeable. So the inner attributes of any of these objects, they can be changed to a shallow copy will create a new copy of any object that you want to clone, but all the internal references of that object not be copied. Our point to the same memory location. For example, if you copied a list or climbed a list, you would have two lists, but the elements of the list would be identical. So if you change the element in one list, you'd be changed in the element in the other list as well. And that's the shallow copy. A deep copy will also create new copies of all the elements inside the list or dictionary, etc. So whether you want your objects to be shallow copied or deep copied depends on your situation. A deep copy is slower to perform since it's going to traverse all the object hierarchy and any objects. Whereas a shallow copy is much faster, maybe that is enough. It depends on your situation. Anyway, it's just important to understand the concept of shallow versus deep copy, okay, So terminology and UML, the prototype interface, and it goes a prototype interface as a clone method. And if you have an object that you want to copy, you can implement the prototype interface on your class so that your object now has a clone method and decline is like your application or anything. We'll use it in source code. Now, we're going to experiment with the source code and try out the different ways of copying. By default, we will show a copy, the object that you've asked to the client. Now the objects that you want to copy can be anything from number, string, dictionary, or anything you credit. Okay, So in prototype, prototype concept of PY or the type of prototype concept there is the prototype interface has one method clone. I've set it up as static abstract. Now there is a class of anything. I'll give it any attribute, I call IT field, and I'll give it a clone method. It needs to implement the clone method because I'm implementing the prototype in the class just there. Okay, So down in the class where I implement decline method, this section here, return type itself is the same as saying, give me a new instance of MyClass. So top of self is my class. So return a new MyClass. And the init method of my class requires a field, so there is self dot field, so that's what we're seeing. So when you create decline preds a new instance of the class using the same value that is infield. And in my class, I've overridden the built-in string methods, so it prints a custom version of my object. So down here, the client object, MyClass, and I'm just passing in a list of numbers for now. And then I'll print it out and then clone it into a new object called object 2. I'll change. Property of object 2 and then print out both of the objects 12 again down here, demonstrating that he was a shallow copy. So let's do that. So Parson prototype, prototype concept. Okay, So here, this is a result of overriding the in-built string method. I'm returning the ID of self of this instance of this class or ID prints out the memory ID or the memory location of the object in Python's memory. I'll talk more about that and one of the next videos. Anyway, I'm just printing out the value of the field, the type of the field. So it's a type of class list, okay? So we can see here object has a memory ID of ending in I DO 32 object, one ending in 80, 32 object to, ending in 680. So these are two different objects in memory. But when I first created object one, I set it as 1234 down here, object to I changed field. One. Field is a list that is position one in the list 2, 1, 0, 1. But because it was a shallow copy, it also changed value one in object one as well. So there we go. So I changed object to yield one to 101, but it also changed object one's list 2, 1, 0, 1, shallow copy. Next up to the code, to the client method, comment that out and we'll now use self field copy. This is also a shallow copy inside Python, but it translates to being a new copy of fields. So it's what I call a two-level copy or two level deep copy. So in this situation, this will work. Okay, so let's run the concept again. Okay, so an object to, I'll sit position one in the list to be 101, but at this time it hasn't affected object once copy of the list. Same as the original. Yeah, just to demonstrate that that really is just a two-level copy, I'm going to initialize object one with a list containing an analyst. So here in the second element their position 1 because a zero-based 0, 1, 2, 3, then a crate that as being 5, 6, 7, control all F2 format. So this list contains numbers plus an inner list of numbers. So down here in object to after I've created the copy, I'm going to change the first position there, which is going to be 1 0. I'm going to change that to an eight now because this is not a deep copy, it's a copy of a shallow copy. It is also going to affect object one's list. So let's try that out and try it again. So prototype concept p, y, okay, So if we look at that object, one field 156734 are then modified object to I change the value at 1 0, which is there to an eight, but it also affects objects one copy of the audio. So doing backwards, I've created a class of anything and I've implemented a clone method on it by using the prototype interface. And then inside the class, I've implemented my own copy method there. So I started off just being a real simple shallow copy, but then used the Python version of shallow copy. So self.view copy. So all objects in Python we'll have a copy method that you can use. So how you implement the clone method for your particular object can depend on many things. I have only just credit one attribute for my class status field. So I mind is copying one attribute when I run the clone method. Now in the next video, I'll do a deep copy and I'll copy different coins of objects within my class as well. So anyway does understand so far I've been doing a shallow copy and then I need a copy of a shallow copy, which should result in a two level copy. The next video, we'll look at a deep copy. Excellent. 15. Prototype Use Case: Okay, now for part two on this section about prototype, pattern example, use case. So in the example, I'll create an object of class document and I'll clone it using three different methods. First, shallow, the two level shallow and afford cursive deep method. The object will contain a list of two lists. I'll create four copies and h times some part of the list is changed on the clone. And depending on the method use, it can affect the original object. So when climbing objects could understand whether your using a deep versus shallow concept copying. Okay, so here's my document. It's a minimal class. It has a name and a list containing two lists and has a client method because it implements the prototype interface. Okay, So prototype client PY, and in the code prototype client p-y, this is the client here where I create an original document of class document with the name original. That's the list with two lists of numbers I printed out and then print a new line. So let's look at document, document dot p-y. It is a class that implements the prototype interface concrete class. When you initialize it, you initialize it with name and the list. It has a clone method where you can select the mode. So the mode equals 1 doc list, which I used down here we are returned the new document type of self I call the initialized method passing in Name and docList is self list. Oh, he's my two. Doc list equals self list dot copy does using Python's internal shallow copy method, which will result in a new instance of document, but also a shallow copy of self list. And then finally, I'll use copy, dot-dot-dot, deep copy. Now, deep copy, you don't get by default in this version of Python, you need to import the copy library specifically for that. So I've imported copy and it gives you two methods. One which is similar to what we're using so far, plus a more specific deep copy method. Make a deep copy and there's more information if you're worried about, if you like. And down the bottom, I'm eyeballing the Python in-built string methods or prints out a custom representation of my document showing the memory location of this particular instance, right, so let's run this example and see what it looks like. So prototype Client dot p-y, okay, so it's credit the original document and that's the memory ID. There's the original document, nine being original. We can see that there. And that's the list 12345678. I'm printing it out and that line and then printing a new line. Then after they occur, the Copy document copy one original document dot clone using number one, that's the shell method, document copy one dot name equals copy one. So that's what we see here. We see the new copy with a different memory ID, so it's a different instance. Then the original further down, I modify the list in copy 11 to a 100. So list1, because it's zero-based, that's this one here, position or index two, which is third one next to zero-based, now equals to a 100. It's also affected the list in the original. Okay, so moving on, I create a new copy document copy to original document clone using the copy of the copy method that's mode to my two doc listicles, selfless copy using Python's internal shallow copy method. Okay, so when we look at copy to copy two has a new ID is different than the original and it's also different than copy 1s IID, but document copy to list one. I replaced the whole list, 9, 10, 11, 12. Okay, so you see that down here. So in this case, replacing the whole list works when you use the shallow copy, SOP replace list completely and that works that didn't affect the original copy, so the original is still untouched now. Okay. So moving on to copy three now. So document copies three, original document client to a two level shallow copy again, I name it to copy three, but this time instead of replacing the list, I'm going to replace an element within the list being 1, 2, 3, 4, so 1, 0, that's this one here. But since I use method two, which is the copy of the shallow copy, it has the same memory ID references as the copy sites actually affected the original as well. So the original has been changed again. Now in version 4, I'm using methods three, which is the deep copy, which is a recursive copy method which you get from importing the copy library from Python and use a lot this copy deep copy self dot list. So if we look down a copy for where I have modified the list or the inner element of list 1, 2, 5, 6, 7, 8 down here. There hasn't affected the original. That's a lot to take in, but I save that didn't make much sense. Then experiment with that and using the ID mass. And you can see that every copy method gives you a new copy of the instance. But depending on which method of copy you use, a certain level of copying of the attributes happens. Summary, just like other creational patterns, the prototype is used to create an object at runtime, prototype is credit from knowledge that is already instantiated. Imagine using the existing object as the class template to create the new object rather than calling a specific class. Now the ability to create a prototype means you don't need to create many classes for specific combinations of objects. You can create one object that has a specific configuration and inclined nice version mean times, rather than creating a new object from a predefined class definition. So you can create something modified, Kleiner, modify that you have ten different objects, all the different attributes. Okay, so the next rewrites the same thing. You have a sophisticated object that was randomly credit from many factors and you want to clone it rather than reapplying all the same functions over and over again until a new object matches the original. Okay, so a prototype is useful for new want to credit copy of an object, but credit that object may be very resource intensive. Example, you can create a new house boat from the builder example or client, an existing house bite from one already credit. When designing your clone method, you need to consider which elements should be Shall I copied or which are deep. In the next video, we'll talk about the Parthenon ID function, which I've been using to print out the memory location of instances. Excellent. 16. Python id() Function: Okay, a quick one on the Python ID function, okay, the path of the id function returns the memory address of an object. It actually returns the memory address of anything that can be used in Python. Now, I've been using DID function to test whether objects are considered unique in parsing or as a new instance, a quick example, I've got a new script here, test.py and the root of my project, I don't have anything in it, but I can print the ID of something. I'm just gonna create a quick class called chest with a value in it. I'm going to print the ID of that class, ID of test. Now I'm going to execute it. And the ID of that class is that number there. Every time I rerun Python, python them all sauna and new ID for that OID will remain constant throughout the lifetime of the process and the lifetime of that class. I can also instantiate that class. I didn't instantiate a day. I just printed a reference to the class itself so that I'm instantiating the class. Now MDRD is different. We can also put those into variables. So I equals a test that is a reference to the class B equals test, that is also a reference to the class C equals test. This is a new instance, the school's test, and that is a new instance. So what we'll see as I printed out the IDs for each of these, is that the first two have the same ID. They are references to the class, and these next IDs are references to instances of the class. Now, we can also test the days of the methods or attributes in a class. So do that. Just setting abcd, et cetera to be the value attribute now, and I'm going to print the ID of that value attribute. And they actually all point to the same thing. They will all point to the same value as one. Also, we go 20, they all equal the same thing. So Python considers one test value and instance of test value, another instance of test value or weakling the same thing. So ID is good to know whether something is unique or not. Because to create a init method inside this class to fine in it's self and just pass. I can also printing out the ID or the init method, their comment those out. I'm going to say C equals a reference to init. And both instances in it methods pointed different memory locations. It's creates something custom like method and see how that looks. I'm going to look at, Okay, and let's have a look at that. And the IDs are different. Now I'm going to convert that into a static method. Give that a test and the IDs are the same. So that's an introduction to the id function inside parcel everything and pause and has an ID and you can just query those just by printing it out, ID, whatever. Also know that even simple things like numbers 123 will have their own IDs. So those IDs that are different and every time you start parsing, those IDs will be different. Even none has an ID, but none seems to be always the same number, doesn't matter how many times you start poison or a good path naughty function. In the next section, we'll talk about the singleton. Excellent. 17. Singleton Pattern: Singleton design pattern. Sometimes he didn't object in an application where there is only one instance, we don't want there to be too many versions. For example, you have a game with a score and you want to adjust it, you may have accidentally credit several instances of the class holding this score object, or you may be opening a database connection. There is no need to create many when it can be used in the existing one, sorry, memory. And either use case is a User balance. You might want to adjust a user balance. You need to ensure that your reference to the User balance is a singleton. Otherwise you'll be updating different valences potentially. So to enforce this kind of safety inside your application, you can use a singleton. So even if a second was created due to some unforeseen event happening in your code. You're only ever going to have one instance, okay? So there's singleton can be accessed globally, but it's not a global variable. It is a class that can be instance at any time. But after its first instance, any new instances will point to the same instance as the original, which is actually a class. It's not really an instance, but we'll look at that in more detail in a moment. So for class to behave as a singleton, it should not contain any references to self that use static variables, static methods, and class methods. Okay, So a client application here is a class, any class, and it uses the new method to ensure that all references to this class point to the original class, I'll demonstrate this singleton, singleton concept PY. What makes this class a singleton is the vector I have a static variable in it, which is really optional if you have variables in your classes or not, I have a static method and a static class, which we can use static variables within your class, say class dot value points to that, whereas the static method, it doesn't actually use any in a variable, so I don't need to declare it as a class method or even add the class reference to it. So down here is just two different ways of using methods inside this singleton class. Now also here I have this new method. When a class is created, you have the option of overriding the new method with your own. So what I'm doing here is with new and getting the reference to the class and returning the reference to the class, what this does is prevents the class from actually being initialized. So if I look down here in the client here, I'm actually calling the singleton four different times. First time, I'm going to just print out the ID of the Singleton in memory. I'm going to create an object one, which is an instance of singleton of India, the idea of object one, and we'll see points the same memory location as the singleton object to. I'll do a copy, deep copy of object 1. So I'm trying my best here to create a new instance of object one by doing a deep copy. And we'll see yet still object two will point to the singleton objects three, just to show that it still works, will still point to the single set. So let's run that Python singleton, singleton concept, the IDs of all of those different ways of using the singleton or point to the same ID. So look at deep copy for a sec. These import copy is not about creating a singleton, is just because I'm using deep copy down here just to try and prove the point that it's a singleton. Now if I took just this section away so that it doesn't override the new method to return the class like so, we'll see that the four different ways of using the Singleton result in different memory IDs. They no longer singletons. So that's what, that just really simple little code is doing. Forcing every time singleton is referred to, forcing it to return a reference to the class of singleton. There we go. These are all the same, okay? And to show you what I'm doing here with this init, doing this prevents it from actually being called. If I was to try this, now, it actually wouldn't print in it. Okay, so these two lines here are preventing this class from actually being instance. So if I took that away, like so in it would now actually be caught in it. In it, it's being called down here where I create object one, which is an instance of singleton and objects 3, which is an instance of singleton. Okay, So put that back and that now becomes useless, and it's back to being a singleton. So the singleton really is about a class that doesn't have any reference to self. So you can use that to enforce that there's no reference to self. And if you need methods in that class, you can use a static method. Decorator doesn't need any reference to class or self or a class method. And you can use the class method which has a reference to this class, which means you can then use its own static variables. In this case, it's called value. So we can print class values. So Excellent. Okay, now, just to summarize that quickly. So variables declared at clause level are static variables and can be accessed directly using the class name with the other class tending to be instantiated first. So class is a reference to the class, self is a reference to the instance of the class. So singletons aren't really instances. We can just use the static reference to the class instead. So I knew gets cold before in it, new has access to class level variables in it references self that is created when the class is instantiated. So by using new and returning a reference to class, we can force the class to act as a singleton. Class to act as a singleton. It should not contain any references to self. Excellent. So in the next video, I'll show you a use case of the Singleton pattern and there's a UML diagram there. Slump. 18. Singleton Use Case: Okay, now time for the singleton use case in the example, there are three games credit. So this is like a game engine which manages multiple games. They're all independent instances, credit from their own class, or they all share the same leaderboard. The leaderboard is a singleton, doesn't matter. Hello guys are credit or held. A reference to leaderboard is always a singleton. So each game independently adds a winner, and all games can read the altered leaderboard regardless of which game updated it as the leader board contains a table of winners, which is a dictionary. There are three games, 123, and there is a game interface with an ad winner method. So add, add, add, add, add. When there's a client application which is managing the three independent games which are all using the same leaderboard. Hey, source code singleton client.print, I mean VS Code singleton client.print. Why? It is the three games, game one, instantiating a new game, one, dime, one at winner with a score of two and name Cosmo game to a new instance to game to add winner the score k3, k4, Shawn, game three is a new instance of game theory and winner with a score of one, ME dime one, print a leaderboard. Time to put delete a board, game three. So you have to, leaderboard was actually a singleton. That would be the same result printed three times. Okay, so let's look at Game one. Self.age leaderboard equals a lot. So I'm importing little board from leaderboard, same with game to importing leaderboard 93 actually inherits everything from game to game two on creating the leaderboard and adding d at winner method, which comes from the game interface game three, inheriting game to game three will become its own instance. Okay, so interface game days. A method must implement add winner leaderboard, turning a reference to the class every time a new leader board is created as to class methods, one which is print, it's a class method because he refers to one of the class attributes being table there. So class table, same with AD when arts class method because it refers to class table. Table is a dictionary more about dictionaries in the next video, let's run that example. Singleton client.print. And he had a little board has been printed out three times. And each time it is exactly the site because all three games, we're effectively just using a leaderboard Singleton. In summary, to be a singleton day must only be one copy of the singleton no matter how many times or in which class it was instantiated. So you want the attributes or methods to be globally accessible across your applications so that other classes might be able to use the singleton. You can use singletons and other classes as I did with delete a board, and they will all use the same singleton regardless. So you want controlled access to a sole instance. For a class to act as a singleton, it should not contain any references to solve. So here I'm using class method for that. And as in Singleton concept, I can also use a static method. In the next video, I'll introduce the Python dictionary that's there. There's two curly braces. Excellent. 19. Python Dictionary: Okay, new coding concepts, Python dictionary in the file singleton leaderboard dot p-y, the last video, accredited dictionary. Let me go with the curly braces into a variable called underscore table. Now those curly braces are indicating a Python dictionary. You can create a dictionary by either using curly braces like that or saying dict or dictionary is similar to a list, except that the items are key value pairs. A dictionary can store multiple key value pairs. They can be changed, can be added and removed, can be reordered to be prefilled with key value pairs. And when instantiated is very flexible on the list since Python 3.7 dictionaries are ordered in the same way that they created. I'll show you that the keys of the dictionary unique. You can refer to dictionary items by key, which will return a value. So let's open the Python interactive console. I'm using PowerShell this time, Python, okay, So I'm in the Python interactive console, but it's three greater than signs there. Now, I'm going to copy that line there. Right-click. So I paste in items equals a new dictionary. That's the curly braces. These are the keys a, b, c, d, e, f, g, h. I need the values 1, 2, 3, 4, 5, 6, 7, 8, 9. Press Enter. And if I just write items, it shows me the dictionary that's in memory, ABC123. So I can refer to one of those dictionary items by key. So let's look at the value in items. Item's ABC and it's 123. Same thing with g, h I and 7, 8, 9. So we can change the value at icky. So I'm going to change the value of df. I'm copying that right-clicking sought pasting items. Df equals 1, 0, 1, 1, etc. It doesn't matter if I use single quotes or double quotes. It's the same. Okay, so it's print items and we go df now equals that long number. You can add new key value pairs and remove them also by using the key. So let's add a new one. Items JKL equals something else. It could even be letters a, B, C, D, E, F, G. Let's print items and we go, JKL is a string. So the keys can be strings. They can also be numbers, but the values can also be strings or numbers or other lists or dictionaries or any object. So let's remove an item while using the key. So I'm going to pop D if pop D if that should remove D if they're items, and it goes down under there, when you use pop, it returns the actual value so you can get the value of the item that you're actually popping. And you can order dictionaries alphabetically by key. In order to show that example, I'm going to recreate items dictionary a, b, C, G, H I DFS. So it's not already alphabetically ordered. Items a, b, C, G, H, I, D, E, F is created already ordered in the way that it was crowded. Now I'm going to reorder it alphabetically by using this line here. Dict sorted items, stocked items. There we go, a, B, C, 1, 2, 3, 4, 5, 6 choice now reorder. So excellent, that was an introduction to the dictionary and that was only just a surface. So continuing on, the next section is about structural design patents. And we'll start off with a decorator. Excellent. 20. Decorator Pattern: Okay, the decorator pattern, the decorator pattern is a structural pattern allows you to attach additional responsibilities to an object at runtime. So the decorated pattern is different than the Python language feature of Python decorators in its syntax and complete purpose. It is a similar concept in the way that it is a wrapper, but a decorator pattern is intended to be applied at runtime dynamically. So the decorator pattern adds extensibility without modifying the original object. The decorator forwards requests to the enclosed object and can perform extractions and you can nest decorators recursively. That's probably the most important feature about a decorator. Okay, so let's look at a party integrator for a moment in the source code, decorated degraded concept P1, decorator, decorator concept PY, these two lines here, these are Python decorators, this static method, an abstract method. While they both are wrappers for the method, yeah, they're not intended to be added or taken away dynamically at runtime. And also, it doesn't make sense to use them recursively like that also. So going back to the documentation, looking at the terminology component interface, that's an interface like other interfaces we've seen so far. There's a component, could be any component, but it implements an interface. And then there's a decorator which also implements the same interface. Now the client can create a component or it can create a decorator which is composed of the component. You can also create a decorator which is a decorated composed of the components so recursively. Okay, So going back to the code, there's the I component, that component and a decorator there. So degraded both implement the same I component, which has a method, method. So they both have a method method. Now a decorator, when you initialize it, you pass in a reference to the object that you're wrapping. So self.age object equals the object could be anything, but it needs to be something that complies with the component interface. Because down here in the method, you will then call its message. So let's look at the client code here and let's run that and see what it does. Python decorator, decorator concept. So it prints out component method. So sometimes I'm creating component and then I'm going print component method, component method of a year just returns the words component message. So I'm printing that out here. I'm decorating component, which is this one up here, and then calling a method on a decorator. So that wraps component method in decorator method and brackets like this. So that's what I'm doing here and the f string. Now, since it can be used recursively, I can also decorate the decorator. So like that, It's decorate, decorate component. Let me see decorate a method, decorator, method, component method, and so on. Okay, So another important factor to note is that the original component was not changed. So if I print component method again, down there, it's still component method. So these decorators didn't change the internal object at any point. Digest rapid. So the next video, the use case example, the decorator, I'll add decried as the alae to add and subtract numbers and do it recursively. And as many times as you like. Excellent. 21. Decorator Use Case: Okay, the decorator example, use case. I'm going to create a custom class called value that will hold a number, then add decorators delay to add and subtract the values. The adding the subject right, is, can accept integers directly, a custom value or other add and sub decorators. So the ads Southern value, add value and sub down here all implement the I value interface and can be used recursively. Now, the I value interface doesn't do much other than just override the Python string dunder method. I'll talk about the string dunder method in one of the next videos. But for now, what it will do is the number that each of these instances will contain. So source code, decorator, client, decorator, client. There are three values, a, b, and c. And add is a decorator, which will add a and b in the first instance space. So let's look at all these. So the interface value as the one method, but it's important that the sub, the value in the ad or implement that one method because I will use it later on, but just to print out whatever self.age value equals and the case, let's look at the value itself. This is the component will be decorated multiple times. So initialize value equals value or value will hold an integer. In this example, let's look at AD. With ad, you pass in two values. Now with ad, you can either pass in an instance of value or an integer. I'm using the attribute price and method here to help me decide whether or not the values that are passed in our integers or an instance of value, but all do a video on get attribute as well. So for now, don't be too concerned about the details of that. What was really happening is when you use the add decorator, it sets up value being the addition of value 1 and value 2, four sub, it's the same except it's value one minus value to. So there's not a lot of code, although it is quite complicated to look at if you've never seen it before. But if we go back to the client, we can see a, a bean. See I've set up as values, value 1, 2, 5, and in the first line, I will just add those numbers and print the results. So Python decorator line dot PY and one plus two, a plus b equals 3. So it's pretty simple. Now, like I said, I can pass it a number, 101, so one plus 100 I'm adding, so I'm adding those two numbers. So that's using a decorator. Now the original a doesn't change, it's still equals 1 k, So this sub as well. So C5 minus 1 equals 4 anyway, so now I'm going to solve an addition so AD CB and then subtract a phi that six. So adding c plus b seven and subtracting 1 equals 6. So you get the idea. We can look at all those the same time, okay, it's 3101, et cetera. Sometimes I'm using numbers and sometimes I'm using the results of previous decorations, so as sub ad like that. And finally, I can print a, b, c, one-to-five. They haven't changed. So you could have an application that has an object and you allow the user to click tick boxes or press buttons. It adds a new decorator to the object all the time, but the original object hasn't changed and then you can just take away those decorators again if you want. So I recommend having a look at the code. I'll discuss get attribute in one of the next videos and also the string dunder method. Now to summarize, so use a decorator when you want to add responsibilities to objects dynamically without affecting the object, you want the option to later removed the decorator from an object in case you no longer need it. It is an alternate method to creating multiple combinations of subclasses. So the decorator compared to using static inheritance is more flexible since you can easily add, remove a decorated at runtime. If we go back to the UML and we go down to The extends inherits. Decorate is use composition, which is not the same as extending inheriting. So for example, fancy car inherits car. So fancy car, when it was built, was built from a copy of car. So fancy cars, attributes and properties are now independent of the original car that it was inherited from. So you can modify fancy car, but it doesn't affect the original car. Any further inheritance of car by other objects will have their own copies. Also. Now, with composition, which decoration is using? Fancy car is wrapping car. It's not creating an independent copy of car that it can modify for itself. So that means if any other objects are also composed of car, changing cart will affect all of them. Now, whether you prefer composition versus inheritance is up to you. It's an argument on the Internet. It's been going for many, many years. They both have their place. So the decorator is about composition. So if we go down to the composition, UML here, aeroplane and when they are different objects, but with composition, many airplanes could be using the same wings. So in reality that sounds wrong. Airplane doesn't have its own copy of wings in composition, it is referencing an already credit instance. And there actually could be other objects throughout your application which are also composed of another object, okay, structural decorator, summary. So inheritance versus composition is a big argument on the Internet. They both have a place. Okay, so we've seen this decorator supports recursive composition. So there's a number, we're going to have the number, and I can have the number again. The original number hasn't changed. The first halving of the number hasn't changed. And then we can have that again, just composition. So a decorator shouldn't modify the internal objects, data, or references. This allows the original object to stay intact if the decorator is lateral moves. Okay, so excellent. In next videos, we'll talk about to get attribute, Python function and the string dunder method. Excellent. 22. Python __str__ Dunder Method: Coding concepts, the dunder string method. It when you print an object, it will print out the objects type in memory location in x k. So that piece of code will print out that. So we can test that. Just copied that to clipboard. I'm going to my test.py script, paste that save and test dot. Okay, So it's printed out main example class object at a hex representation of an instance of example class. So you can override that default behavior of poison to print something custom. And that's by implementing the string dunder method. Or dunder is short for saying double underscore. So dunder methods of predefined methods and parson that you can override when you run implementations. So let's just copy that section there. Okay, so instead of printing out that, it's just going to print out something else because I'm overriding it defined string self case. So xy, it now says something different. It could even be self.age ABC. And because I'm trying to print a string, but actually ABCs and integer, I'll do string. Like so I go 1, 2, 3. So that's what I'm doing in the decorator code for add some returning string self-value, whatever self-value equals. So with the value self-value and goes to the string dunder method was also overridden in the prototype concept coat just down here where I'm formatting ID self looks quite hard to read, but that's the outputs. So when I'm printing object one and object two in the code, I'm overriding the default behavior of Python to print something more custom. And that was IT DID field equals type equals. So that's the ID. Field equals time equals excellent. The string dunder method is used throughout the entire course, so you will see many examples of it like so. In the next video, I'll talk about the Git attribute function. 23. Python getattr() Function: Okay, in this video, I'm going to show you how I'm using to get attribute function in this sub and add clauses are used to get attribute method like a ternary operator. So I'm getting the attribute, object attribute. If it's not there, I'll use a default value instead, okay, So when initializing the ad and subclasses, you have the option of providing an integer or an existing instance of values sub or add classes. So for example, the law and the subclass value one equals attribute value one, value or value one. Okay, so if value1, when it was passed into the function, had an attribute of value, then I would use that. Otherwise I would use value one. Now that's saying that the value passed into the function could have been an instance of value or it could have been an integer. Okay, so let's look at the code. Okay, so the value class down here, self.view value, the y I use it is intended to be an integer. So if I just comment that out and then print type of a value up here and then run it. Decorator, Client dot p-y is show me as a class of integer. That's good because I've printed these value using an integer. Now down here where called the acidic writer. I've also passed in an integer. So if I print the type of 100, that's also an integer. So if we look at the ad decorator, it's adding two integers. So value one, I'm are they using value one dot value that indicates that the value one is either an ad or a sub or a value object. Or if it's not those, it must be an integer, which means I'm using that number. So then by added to it, it just okay, So if we've got a client again, that means that in the code, I was able to add or subtract numbers, as well as values, as well as decorators doing down here. So if I take away that get attribute and use it without that. So if I was going value, dot value and adding value to dollar value, this no longer supports the option of me passing in an integer. So let's run that. Client says Yeah, attribute error, int object has no attribute and value. But if I was to do that, that would be okay. But since I used the get attribute function, which gives me the option of either passing in an Ad sub or value or an integer. Now because that's how I'm using it. I can add a number or two numbers or a number and a value, or a number of value and Decker, right? Okay, so anyway, experiment with that. That's why I'm using Git attributes because it gives me those extra options in the decoration functions that I'm done here as well. So excellent. In the next video, we'll look at the A-delta. Excellent. 24. Adapter Pattern: The adapter pattern, sometimes classes have been written in. You don't have the option of modifying their interface to suit your needs. What I mean by that, the methods that you are calling are completely compatible with what you want them to be or how your client needs it. This happens if you import third-party libraries or you're using an external API from somewhere across the network. Anyway, the point is, it's out of your control to modify that. So what you need is built and adapt on top of that, the depth to help us to solve how can a class be re-used that does not have an interface that a client requires. Happen classes that have incompatible interfaces work together. Alkane an alternative interface be provided for a class. Okay, so you've got two classes that are similar, but they have different method signatures. So you create an adapter over top of one of the methods signatures so that it's easier to implement and extend in the client. So in a debtor is similar to the decorator in the way they also acts like a wrapper to an object. It is also used at runtime. However, it is not designed to be used to recursively, okay, so it's an alternative interface over an existing interface. It can also provide extra functionality that the interface being adapted may not already provide. The adapter is similar to the facade which we'll talk about in the next section. But you're modifying the method's signature, combining other methods and or transforming data they exchange between existing interface and the client. The debtor is used when you have an existing interface, it doesn't directly mapped to an interface to the client requires. So basically the adapter is used when you have an existing interface that doesn't directly mapped to an interface at the client requires, then you create the adapter that has a similar functional role, but with a new compatible interface. Terminology, the target, the domain-specific interface or class that needs to be adapted. The target in this diagram is class B. Class B needs to be adapted in this example so that it's compatible with class, say, so the adapter interface, the interface of the target that the adapter will need to implement. So the adapter needs to implement the interface, a interface for it to be compatible with declined the adapter, the concrete adaptee class containing the adaption process. So that's class be adapter and the client down here. So in the source code there are two classes, class a and class B with different methods signatures, they both have different interfaces. Now let's consider class site provides the most compatible and preferred interface for the client. So the client would rather the class B at the same interface as class a. Okay, so let's look at the source code. Adapter, Adapter concept, PY, okay, So adapter, Adapter concepts, There's interface, a method a, and Class a implements interface as it just prints method a interface be as method B. Class B as a method B prints method B. Class B adaptor implements interface. When we initialize it, Class B adaptor is composed of class B when we call method I because it implements interface a, we then redirect that call method a onto class B's method B. So the client doesn't know that that's what's actually going on behind the scenes from the client's perspective, the interface for AMB, them become identical. So what I'm doing here is doing the same thing twice. In the first example, I'm creating two items, so I'm just putting them into a list, class I, which is an instance of class a and class B, which is an instance of class B. I'm just putting them into a list for no reason other than just to iterate them. So before the adapter, if I want to call the method on class B, I need to check if the instance of the item is a class B first, and then I will call item method B for item in items. Otherwise, item method a. Method a, from the perspective of the client, is the preferred method signature of accessing these objects. Now this is the conceptual example. So it's very basic, just showing you the concept of deductive. Okay, So then down here in this section, instead of creating class B, all Craig class B adaptor instead. And then for each of the items, and whether item is class a or class B doesn't really matter. The adapter will redirect that method I onto class B's method B. So if we run that Python and depth, depth the concept of p-y, it's doing the same thing twice. It's printing out method a and method B. That's that section of code. It's calling items method B or better a, items metadata. Then after implementing the class be adapter, the client doesn't need to know about the specifics of class B anymore and handle that particularly use case like I was doing earlier. It will just item.name if today and that's what's happening there. Okay, So that's a very simple idea of the adapter. And really adapter is used when you have an existing interface or doesn't directly mapped to an interface that the client requires. So then you create the adapter that has a similar functional role but with a new compatible interface. So in the next video, we'll talk about the adapter use case, where I'll use it to manufacture two different types of cubes that have different methods of creation. So u cube B as different methods and attributes in Dubai. And we'll see how I adapt that. And excellent. 25. Adapter Use Case: Okay, in this use case, I have a system which produces cubes. The system is quite complicated as well established, it works and it's very busy and it's just producing cubes for clients based on width, height, and depth. And manufacturer method call is made width, height and depth, and a cube gets built and delivered. It's a very complicated system, and that's the situation. So there we go. There's a cube there. That's the corner cubes or producers. For example, the system works perfect. It's a well-oiled machine, but the manufacturer of the cubes can't keep up demand. So I've had to go out and organize another supplier, Cuba, be over here. Now Q base interface for creating the cubes is different. They require a top-left front coordinate and a bottom right back coordinate. Whereas the company that I'm already set up with, for example, needs width, height, and depth. Now they produce identical cubes, but the interface is just different. So I'm going to need a quite an in-depth data for the current system because redeveloping the current system is going to be too expensive and take too long. And also telling the second manufacturer of the cubes to change their interface. Well, that's not going to happen either. So the adapter is perfect for this situation. Now this isn't, doesn't exist in real life. This is just example code to help you understand a good use case of the adapter. So look at the source code. It's adapter client, ANY adapter client PY first thing we'll do is execute the code to see what it does. So Parson adept, line dot p y. Okay, So we can say that that was happening slowly over time. So it's simulating orders being made through a system. So it's decided that company I was busy. So I would try Company Bain, Company B was busy, so I tried company a, and company a was no longer busy so he could produce a cube Guys dimensions. Then the next order came in company I was busy, so a toy company, B company base building a cube, but those dimensions and et cetera, and just goes on. So you've company IES busy. We got to company B and company B is busy, we try company I. So that allowed the hypothetical company to produce twice as many cubes. So let's look at the code in client pay war. It's a basic loop that is producing five cubes. And if the counter is less than the total number of cubes will keep looping. So that's a while loop, okay, so width, height, and depth, cube success is cubed dot manufacturer width, height and depth. So start off with q by if success then SQ by was manufactured dose dimensions counter equals counter plus one, it wasn't a success. Then we try company B cube equals QB be adapter interface to the method to create the cube is exactly the same success, success. So that's the point there of using DQ be adaptive because the system that was requesting cubes was taking in width, height, and depth pay so brilliant. And down at the bottom, I'm just simulating some kind of delay in orders. Time sleep for 1 second. And this is a loop and that's just a simulation of orders coming into a system and being delegated in a round robin fashion to the next available manufacturer. So if I look at the diagram again, cube uses the manufacturer width, height, depth function, and Q B has a different method. Create top-left, front, bottom Lloyd back. So interface cube, a manufacturer width, height, depth, interface QB creates a different method name, different signature, top-left, bottom-right, back. Both hypothetical companies can produce identical cubes, but they just use a different method. Okay, so QB be adapter is composed of a cube B, but it has the manufacturer width, height, and depth method as described by the cube of ice interface. And then down here, when I get those arguments, are then do a conversion into what QB need. So cube has a correct method with top-left front and bottom right back. Excellent brightness of a cube iss manufacturer method. It's deciding here whether the time difference between the last manufacturer request was a certain time ago, which is actually this 1 second. Otherwise, it's returning false, which is busy QB, very similar. That's the correct method. It does a simple time check to see if it's busy or not. Q b cannot reproduce a cube once every two seconds. Otherwise it returns false. And there's QB adapter and there's the client. So that sit, you can have a test of that. And it's from that again to show you what it looks like. And there we go. Five cubes have been manufactured, and they have been manufactured by I, b, i, i and be excellent. So use the adapter when you want to use an existing class, but its interface does not match what you need. The adapter adapts to the interface of its parent class for those situations wanted he's not viable to modify the parent class to be domain-specific for your use case. So it was just much faster and quicker to write an adapter then to redevelop the existing systems. So adapters will most likely provide an alternative interface over an existing object class or interface, but it can also provide extra functionality to the object being adapted might not already provide. Adapter is similar to the decorator, except that it changes the interface to the object, whereas a decorator adds responsibility without changing the interface. This allows the decorator to be used recursively. So an adapter is also similar to a bridge, which we'll discuss also light up and they may look identical after the refactoring has been completed. However, the intent of crowding the adapter is different as a result of refactoring existing interfaces and systems because you have complete control over all of them and you're going to do a refactor, whereas the adapter is something do you have to make fit into the existing environment that is not viable for your change. And there's many reasons for that. Sometimes the length of Thomas going to take us a problem or sometimes it's just not your responsibility or your code or et cetera. So excellent, the adapter pattern. In the next few videos we'll talk about the new concepts that were introduced. There was the past and is instance, which was introduced in the concept of PY down here and where I was mentally checking the type and also the Python module, which is very useful as well for having a clock sod your processes Excellent. 26. Python isinstance() Function: A Python is instance function that are used in the adaptive concepts. Just down here is instance item checking if an object is an instance of class B is instance, okay, it returns true or false. Okay, So let's open the price and interactive console is instance one an integer true? One is an integer, is instance one a Boolean? False. What about a string? False. What about is one, our list? False? We can take lots of things. Is true a Boolean? So is through a boolean, it's true. What about is IBC a string? Yes, it's true. Now, we could also check an object against multiple types. So is IBC a string or an int true? It's one of those. Is it a Boolean? Or it's false? And you can see down here is instance ABC, a list, dictionary tuples, set or string. True. If I took away the string, it's a false. And so I've used it to test one of my custom classes. So just copy that. I've copied it to clipboard going into test.py class, my class, nothing to see here, it's just empty. Class I equals MyClass. Let's print a type of MyClass and then we'll print is instance class a boolean which is going to be false, is instance class a, a MyClass, and that'll be true. So let's run that past and Robin to save it. I go test.py. So class, my class, that's that line there, prince, that is instance class a ball false is instance class my class true. So it's just a very useful little option that we have when running code is to test whether something is an instance or not. So in the adaptive concept here, if the incidence of item in this list was a class B and I call him method be otherwise so item as an excellent. In the next video, we'll look at the Poisson module that was also introduced in the adapter pattern example. Excellent. 27. Python time Module: A new coding concepts, the time module. Now the time module provides time-related functions that are outlined in more detail at this official documentation. So I recommend looking at it when you need extra information about the time module. But anyway, ON going to introduce a lot of the basics to so far. And the last two examples of the adapter pattern, I was using the time to sleep for a second at a time as the process was running to simulate some time delay. And also always using it to measure the time difference between one event from the next. So in this part of the code from cube a dot p-y, I was taking it timestamp and actually just taking the integer part of the timestamp and comparing it since the last time that I had recorded. And if the time difference was greater than 1 second, then I would execute this section of code inside the if statement. So basically what I'm doing use if the time is greater than 1 second and do that. Now, also, I was using it to sleep. So timed or sleep one that says sleep for 1 second. So you can see a couple of examples in the code of using time. And these are very common usages of time throughout my code, where I'll just compare the time difference or make sleep. But time can do a lot more than that. Okay, so down here, I have a whole lot of examples that I'll go through. So I'm gonna use a Python interactive console. Okay, So I've opened up PowerShell and I'm just going to go into pious. And there we go. And I'm going to import time, the import time and right time dots sleep one. This will sleep for 1 second. And then it gives me the prompt again. Okay, let's try that, but with five seconds. Okay, So the current Python process slept for five seconds. So it is locked for five seconds waiting and didn't give me back control. Okay, so let's get the current time of my system. And that is a float of the number of seconds since epoch. By epoch time is a time since the 1st of January 1970. It's a time reference that most computers will use. Wikipedia page epoch time is first of January 1970, 0000, 0000, 0000. If I run that again, there we go. The time is different. So every time I run it, it's different. Now, I can put that into a variable. I'm going to say ts equals Time.deltaTime I'm using ts is a timestamp, so print that out now Ts, that was the value of time, time when I credit Ts. So that's not changing. That's going to be a number that I'll use throughout the rest of this video. Okay, so I can measure the time difference between now and Ts Time.deltaTime, which is now minus ts equals 39 seconds ago, now equals 43 seconds ago. So that's essentially what I was doing in the adapter example to work out whether the cube manufacturer was busy or not k. So the type of time that number there, I'll just show that it is a float because there's a class float. And in the example, I was using just the integer part of the time. So for that I was using in time times. So we go, That's just the integer part of time, time. Now you can print out time as a human-readable form that we're more used to seeing and that's using C time there. So time, C time Friday, March, etc, 20, 21. I can print out the c time for the epoch which is 0, Thursday, Jan 1st, 000, 001, and 70. Or I can print it out for a number of I've stored somewhere else or even a timestamp that I recorded before at 946. So I can also change the formatting of that output there by using these different directives. Percent a present the hour, minute second, there's more information here on this official time documentation page is a directives sent a locales abbreviated weekday name like ALS, full week dynam, HLR, etc, as a 24 hour clock. So it's pundit. We can see here that by default the year is there, but I've moved the year down to there. So we can also do other things as well, like put separators enough alike. I go for a hyphen 12th of March. Very good. Now one thing to note, the time string F time function, we can override the time that we're custom formatting. But the second parameter needs to be a tuple or a struct time. So for example, Time dot HGMD to. So now time GM time is the time expressed in seconds since the epoch as a struct time codes. So let's look at that. So if I was to talk time, GM time, like so it's come back as a struct that's not the same as the integer or float that I was using before. So if you want to pass in a custom time value to string of time needs to be in a structured format just a little bit more about the time struck before I demonstrate that, if I want just one portion of that GM time or that struck on there, I can say give me 0, which is the year 2021, give me the value at position 2, which is 12. Tim day 12, or I can say, Give me one of these key values being the time weekday there for is a Thursday or TM, year day, the 75th day in the year. So going back to string F time, printing out a custom version of that timestamp. I can put in timestamp there and the GM time function. Then we go for a 12 March 2021, 946. That was the time written as a string, a custom string of the timestamp that I credit at the beginning of the video. Now my computer is using GMT. But if you were in a different time zone of the world, you could use another function called time, local time to produce a times dropped off, set your time zone. And if I had a different time zone on this computer, then that would produce a time based on my current local time. But I'm using Windows and I don't want to change the time on my clock because it will affect other programs. But this next section of the video, I'm going to use Linux, which when I start the Python interactive console, will allow me to change the time zone for this session only. Okay, So for that import time and OS, so I'm going to get the current time zone for my server here. So time zone is 0. Now this server is actually New York, which is a different time zone, then GMT. On my servers, I always use GMT or UTC because I think it saves a lot of problems. I consider local time zones to be a client problem, not a server problem anyway. So let's look at the time zone name for my server in New York and as UTC, UTC is Universal Time Coordinated. Now if you're going to run the systems that need to work internationally, I recommend using UTC and any local specific datums should be handled by the client, not the service code. So let's put out a custom format of a particular time as a number 123456789. Okay, so time dot local time, time string format time, a custom string format of a particular time that I've created. For a second again, 1970, that he's written offset UTZ, which is 0. If I was to add a percent down there, we see plus zeros 0000 for the time zone. Okay, So now to change the time zone using OS environment, tease it or change it to America, New York now to commit it. Now it's a reprint that out. It's now using AST ADT's. So Time Zone, Time, Time Zone 8800. So let's do that. Lon again this string F time up here and compare the difference. There we go. So fraud a second agenda and 7517 36 versus 10. 36. So my local Python session is using America, new York time, AST, ADT. And to show that this only affects just these current price and session, I'm going to exit it, okay, and just reentered again, parse them and import time. And right, time dot name, it's back to UTC. Excellent. Okay, So for different time zones, visit this Wikipedia page and you can get a time zone for your region. Now if you're using Windows, you can change the time zone using the TSO command. Now I don't recommend using that location is running on your Windows Server already, since it will affect the system time globally. So a Windows command prompt, util slash G, GMT Standard Time. I can get a list of time zones and we go and I can change one of those before. Like, I'm not going to do that. Excellent. So the Poisson module, it can be used in a very simple things such as making a process sleep, or comparing a time difference between different events. Or even much more complicated things which I've only just touched the surface on. Okay, so excellent. In the next video, we'll look at the facade. Looks like. 28. Facade Pattern: Now the facade pattern, sometimes you have a system that becomes quite complex over time as more features are added or modified, it may be useful to provide a simplified API over it, and this is the facade. The facade pattern is essentially an alternative, reduced or simplified interface to a set of other interfaces, abstractions and implementations within a subsystem that may be full of complexity and or tightly coupled. So it can also be considered as a high level interface that shows the consumer from the unnecessary low-level complications of integrating into many subsystems. Now the facade is probably one of the easiest at all, the structural, it's really just a layer over existing systems. So the facade UML diagram, there are five subsystems here or with different methods, and they do different things. Method a, method B method, see cetera. But instead of giving documentation for all these things to a client developer, that could be a little bit overwhelming and not all that information would be necessary. So what you do is you create a simplified facade over all of that, which just maps I, I am B2B in some way. And it's just a list of just the important methods. For example, subsystem seeker 20 methods. You're going to need to provide one in the facade. So that's a lot less overwhelming for the client developer now versus the adapter, the debtor is more complicated, then the facade is almost the same as well, except the adapter is about having to change things or even mix things together a little bit more, whereas the facade is just really a one on one relationship. Okay, so let's look at the source code, okay, facade, facade concept, PY subsystem class I has a method, subsystem class B has a method. This one needs a value subsystem class C is another method and a value. This is just conceptual. This is showing the point of the facade. So there's the facade layer here, which is really just a layer over the other subsystems. So we have a specific method there which calls subsystem class I, et cetera, B and C, probably the simplest step of all the structural patterns. So right in the beginning, you could say that it was hypothetically complicated for a client developer to code into subsystem a, B, and C. After the facade, you can give them the reduced interface and say, This is how you do it. Now, you could argue that this actually looks easier, but I'm just showing you that that's really all the facade is. Sort of run it. Python, Assad, assad concepts. There we go. Same thing. The first one is calling the subsystems directly, and the second set is using the side. Now when creating the facade, you could actually create it as a singleton. And other option is you may have a set of quite complicated subsystems, but the client that you bought on doesn't need all that information. So you can create a facade specifically for their use case, a reduced set of the subsystems. Excellent. In the next video we'll look at the facade use case, which demonstrates the benefit of the facade. A little more Excellent. 29. Facade Use Case: Okay, The facade example use case, okay, So there is a game engine API, that's the facade. Now it's layout on top of all the other backend systems. Now this is not a real system, but it's just an example of the components that a system like this, my episode, the backend systems such as the reporting, service, game engine users and the wallets. They're all interacting with each other. And you could develop a game client that will connect and use all those things, but it just makes more sense to create a facade layer that just cherry picks just the required from these other subsystems and written specifically for a particular client. Now, you can have many different clients. You can have mobile clients, web clients, presentation clients, and whatever you can think of reporting clients, but they could all be using maybe their own facades. In this case, this facade is pretty good case. So we can say get balance that will come from the wallet API, game state that will come from a game engine API get history there will come from the reporting API, change password come from the user's API, submit entry and go to the guy mentioned API and register user to the user API. So, so that's an example of a more complicated facade when we run the code. So facade client.print, facade, client.print. I'll just run it. Python facade, client rpois. It's simulating the events of a game engine. So you can see guy open, there are some entries, some reported events that happens throughout the user registration and entry, submission and the game clock counting down by one. So it's just a very small section of time that might happen through a game. Anyway, this is about the facade. So the facade was the game API, which provides the selection of just the methods that it needs from each of the subsystems. So I'm importing all the subsystems, uses wallets, game engine, and reports from this image. While its reports uses game engine and create a new game API facade or give balanced and goes off towards give balanced game state goes off to game engine, good game state, git history for Paltz, good history, et cetera. And it's just like that next facade. And there's not really anything too complicated going on in there. It's just a message comes in and a message goes out. And this really just is a singleton without making it a singleton deliberately, because it's just implementing static methods. And other thing you might notice here, these extra, these are called type hints, this colon string and this output decimal. These are type hints. I'll talk about toppings in one of the next videos. And also there is this decimal import, and I'll talk about that in the next video. So let's quickly look at the watts, the wallets is quite complicated. I've set it up as a singleton. So the wallets is using the reports system as well. If I look at the game engine, the game engine is using the report system, wallets, and discipline reports is using time. It's also a singleton, uses, etc. So all these subsystems are pretty much entangled with each other. But at the sod is a much more simple layout for any client developer to develop into. Let's look at the summary. So use it when you want to provide a simple interface to a complex subsystem, you want to lay your subsystems into an abstraction that is easier to understand. You Abstract Factory and the facade can be considered very similar. And abstract factory is about creating an interface over several creational classes of similar objects. Whereas the facade is more like an API layer over many creational, structural and or behavior. So the facade would be returning objects or it could be just providing I2, several other systems. So the mediator is similar to the facade as well. We'll talk about the mediator later. The facade is not intended to modify or loan balance or apply any logic. Also another important point, the subsystem does not need to consider the existence of the facade to the subsystems will work without the facade, whereas the mediator is more like a two-way adapter for input and output, but we'll look at more of that later anyway. So a facade is the minimal interface that could be implemented as a singleton, which I've said. And the facade is an optional layer. It does not alter the subsystem. Subsystem does not need to know, but the facade and could even be used by many other facades credit for different audiences. So I alluded to in the UML diagram, for instance, this guy APIs of Assad that could be written for a mobile and a web client or desktop client. Whereas you can create another facade which is even simpler, which could be used for AI presentation display of some source such as a television graphics school board or game school board on a website, doesn't matter. It's kind of like you would write the facade, thinking about what Carnegie information the client would name versus giving the client developer access to everything. So excellent. In the next video, we'll talk about the Parthenon decimal module and how I've used it in this facade example. Excellent. 30. Python Decimal: Okay, new coding concepts to pause and decimal module to the decimal module provides support for correctly rounded decimal floating point arithmetic. If representing money values and poison, it is better to use the decimal type rather than float. Floats will have rounding errors versus decimal in the facade source code, I was using decimal in many places. So submit entry decimal five, if balance as a decimal, submit entry, user wallets adjust balanced decimal. The wallet value was a decimal, decimal 0, or use it everywhere throughout this facade example use case. Now floats will have rounding errors versus decimal. So for this, I'm going to open the Python interactive console PowerShell. So if I was to add 1.1 to 0.2, there we go. There are all these extra zeros and S3, right the end. That's a floating-point precision problems. So 1.1 to 0.2 actually equals 3.3. So if I import decimal from decimal and then add decimal 1.1 plus decimal 2.2, it's now 3.3, even though it's written like that decimal 3.3, it's still considered a number. So I could go decimal 3.3 times 25 and its decimal 82.5. But don't do this, don't multiply a decimal by a float. You'll have problems. And also when declaring a decimal, be careful to declare as a string wrapped in these single quotes or double quotes and not as a float. Otherwise you'll get an unblock that. So if I was to convert that to a string, there we go. 3.63 does now correct? So decimals use them if you're going to manage money using Python and don't use flights, so you get a floating point error problem. Excellent. In the next video, we'll talk about typings. Excellent. 31. Python Type Hints: New code and concepts, type hints in the facade use case example, I've added type hints to the method signatures and class attributes as these things here, clock int, I'm saying the clock should be an integer entries. I'm saying it's a list of tuples of string decimal. That's a more complicated example. Also down here get balanced. I'm saying user ID is a type of string and it returns a decimal case. You get the balance of the user, and you get a decimal back at register user, new user. The new attribute is a dictionary of strings, string, and it returns a string back. So these extra things you see here in the code, you'll see this colon and also this arrow looking combination of characters and a type hi pins. Now, python doesn't enforce type hints and they are optional. Python and we'll ignore them. So you can just leave them out if you don't want them, though, however, where they are beneficial is in the IDE of your choice or other third-party tools such as type checkers. So let's just look at a few examples again, start time, I'm saying is an integer clock entry. So I'm saying as a list of tuples, string, decimal, if I go down to wallet, so I'm saying was, is a dictionary of string, decimal and uses, I'm saying is a dictionary of string and a dictionary of strings string in methods. So I can say new user is a type of dictionary string, string and it returns a string. So that's where you'll see it and it's safe to delete them if you don't want or even declare users just simply as a dictionary if you wanted to, since python ignores or the type hints and just bring them back. Now since in this aside example, I was using decimal. I want to enforce that only decimals are used throughout the code and no one's using integers or floats by accident in the game API, for example, when you get a balance, he returns a decimal. Or if you submit an entry, the entry must be a decimal, for example. So in order to meet, to make my code more robust and to ensure that only decimals are used wherever money is referenced, I can use the type hints plus I can also install an extra program called my point. My point is a type checker and it will use the type hints in your Python code, even though Python will ignore them when it executes. So you can install my product is I already have it, so it's not doing anything. That's a requirement already satisfied. But I can run my PI on a Python file. So my Pi facade client PY file, their Enter, it goes and checks all the type hints throughout the code and tells me, well no issues found one source file, but note that my pie is actually checked all of the imports as well. So in client I've imported from decimal, decimal game API, Game API as well, and et cetera. These other files also import as well, okay, maybe I imports from those. So for example, if there was one part of the code where I wasn't using decimal. And so in-game engine, for example, game engine, let's just say I was adjusting a balance here, but instead of passing in decimal minus one, I just used an integer minus1. And I ran my pile on my code again. So my Pi facade client PY is told me that as a problem, a game engine line 44 argument too, but just balance of wallets has incompatible type int expected a decimal. So very good sort of whack and say my code that I have problem there, I'm not using decimal, it's quite easy to forget these things. So just balance for go to definition. Mountain needs to be a decimal, very, very good type hints. So if you're ever working with money in Python, and I recommend adding type hints to your code and also using my Pi to check the consistency as well. Because Python will allow you to change the types of attributes when code is run. So because Python is not type-safe by default, so there's two things I recommend their type hints and checking using my pie and excellent. In the next video, we'll look at the bridge pattern and excellent. 32. Bridge Pattern: Hi, the bridge pattern. And the bridge pattern is similar to the data except in the intent that you developed it. The bridge is an approach to refactor already existing code, whereas the adapter creates an interface on top of existing code through existing available means without refactoring any existing code or interfaces. So the motivation for converting your code to the bridges that he may be tightly coupled. There is logic and abstraction close together that is limiting your choices and how you can extend your solution in the way that you need. So example, you have one car class that produces a very nice car, but you don't have option of varying the design level or outsourcing responsibility of creating the different components. So the bridge pattern is a process about separating obstruction, implementation. So this will give you plenty of new ways of using your classes. So for example, there's a car, and that car has an engine or wheels and everything else. And that is one class that gives you all that. So after the bridge, you can create your car and you can delegate engine a or engine B, etc. So the British didn't exist before, but after the separation of interface and logic, episode can be extended independently of each other. So I can work on the car independently of working on the engine. Also, the application of a bridge in your code should use composition rather than inheritance. So here I'm using composition on creating a car and it's now composed of an engine place. So another example, car, car, we pass in the engine rather than class car inherits an engine though. So in this method, we can choose the engine at runtime. So a bridge implementation would generally be cleaner than an adaptive solution that was bolted on since it involved refactoring existing code, rather than layering on top of legacy or third party solutions that may not have been intended for your particular use case. Okay, let's look at the terminology and the UML and k. So we have an abstraction interface, that's it down there. The abstraction interface, a refined obstruction, a refine obstruction be the implementer interface, the concrete implementers eye, and be a case of the britches down the middle there. So originally the refined abstraction, the concrete implementer would have been part of the same glass. Now both of those things have been separated. So this is the abstraction versus the implementation Onto the source code in the concept demonstration code, imagine that the classes were tightly coupled. The concrete class would print out some texts to the console after abstracting the class along a common ground is now more versatile. The implementation has been separated from the obstruction and now can print out the same text into different ways. So the benefit now so eat refined obstruction and implemented can now be worked on independently without affecting the other implementations. So bridge rich concept in VS Code bridge, bridge concept. And it is find abstraction I, which implements our abstraction, find abstraction B, which implements our abstraction. And they both have a method because they implement abstraction when you instantiate them, you also tell it which implemented it's going to use. So when you initialize it, you pass in the implementer. So there's an implemented interface, it just has a method. So concrete implemented a and B. One method does that and the other implemented BY does something slightly different. So there's a refined instruction i, which is composed of the concrete implemented. Now refine obstruction B is composed of a concrete implemented BY, so we pass in the sector the same information, but they will do different things. This one they're parse and bridge, bridge concept PY, okay, So they get the same information, but the implementer has done it in different ways. Now one thing we're thinking about here is that refined abstraction I and refined abstraction B are actually both exactly the same choice whether you want to split up the refined obstruction further like this. But if it is not adding any benefit, then you could just get away with having one refined obstruction. Because in my case, in his concept example case, both refined abstractions are doing exactly the same thing, but the implementer is different. So I go still works. So refined obstruction. So that would change this UML slowly. That composition would be part of refined abstraction a day. So they're the choices that you have. Okay, so in this lesson, there is a new concept about Python, args. I'll talk about that in one of the next videos coming up. But in the next video, we'll look at the bridge use case. Excellent. 33. Bridge Use Case: Okay, bridge example, use case. In this example, I draw a square and a circle. Both of these can be categorized as shapes. The shape is set up as the abstraction interface down here. That's the abstraction interface. The refined abstractions, square and circle and I go square and circle, implement the shape interface. So when the square and circle objects are credit, they are also assigned day appropriate implementers being squared and momenta and circle implemented. They are an H shapes draw method is called, the equivalent method with the name momenta is called a square and circle are bridged and each implementer and abstraction can be worked on independently in the future. So let's code bridge client PY VS Code bridge client p-y. This for classes circle as a fine obstruction circle implementer, square, square implemented. So could draw square root. Let's run that. Bridge client PY draws a circle and a square. That's the implementers doing that. Okay, Let's look at the code. It's actually very similar to the concept, except there's the circle PY for an obstruction and it's very similar to the square root fine obstruction. They are both the same essentially, but the option is there to work on them independently in the future if you need them. Okay, So summary, use when you want to separate a solution where the abstraction and implementation may be tightly coupled and you want to break it up into small conceptual parts. Once you have added the bridge obstruction, you should be able to extend each side of it separately without breaking yellow also wants a bridge obstruction exists. You can more easily create extra concrete implementations or other similar products may also happen to be split across similar conceptual lines. The bridge pattern is similar to the data, except in extent that you developed it for the bridges and approach to refactor already existing code. Whereas the adapter adapts to the existing code for its existing interfaces and methods without changing the internals. Excellent. So the next two videos, we'll look at the args argument and the tuple, which was also introduced in the original rich concept. Down here. Excellent. 34. Python Tuple: New coding concepts. Tuple. Tuple is similar to a list, except that the items in a tuple are ordered, unchangeable and allowed duplicates, okay, for example, or create a tuple items, items equals Alpha, Bravo, Charlie, L5. And I can print all items from Robert Kelly Alpha. Now see us parenthesis and not a square bracket or a curly brace. And you decide now tuple versus a list tuple is immutable, that means it can't be changed. A list is mutable, you cannot change, at least you can append items and you can take things away and you can reorder them by a tuple. You can replace a tuple but not append to it. So I'll just show that to you compared to a list so far was to do ID of items. That's the ID. Now I'll create a list, just a sample list, lst equals 1, 2, 3 for example. And now print the ID of list lst, okay, now I can append to the list. So LST dot append or, and print the ID of list and the number is exactly the same. But if I was to change the items tuple there, I could say items equals. I'll add a Delta and then print the ID of the tuple there, the items, the number has changed. The item ID of items up there was that number, and now it is that number. So the original tuple has been replaced completely, which is pretty much what I just did down there. You cannot append or delete from a tuple once as credit, it's like a constant. The only option you really have to change it completely. So the tuple is immutable, whereas the list is mutable, list is changeable. Will the elements in the list of change and the original list ID can remain the same. Consider it as a very reduced functionality list. And there are examples of tuple here and there throughout the course, you can also get a tuple item by index if you like. So items 0 or one. Decartes say items 1 equals Zulu. For example, tuple object does not support item assignment, so I'd have to rebuild it completely, recreate that whole line. Zulu. And now items has been changed. Body is now being given a new ID, okay, because it's immutable and also you can get the length of the tuple. So it's just a very reduced functionality version of the list is one way to look at it. Excellent. In the next video, we'll talk about the args argument. And that's that and that was used and the bridge concept, they've method args, Excellent. 35. Python *args: New coding concepts, the star args argument or asterisk args, or any number of positional arguments, args, okay, so the args argument takes all the arguments that was sent to a method and packs them into a tuple. So it's useful when you don't know how many arguments or what types will be sent to a method. And you want your message to be able to support any number of arguments and types being sent to it. If you want your message to be strict about what types dedicate except, then you can specifically set it to accept list dictionary sit in tuple and use type hints and my pie if you want. But the args argument there, the star args like that is another common option. A. You will see throughout source code examples on the Internet, okay, So copy all that code there and paste it into test.py in your project. And if we look down here at my method, when I'm calling my method, I'm passing in anything. So here happens to be an int. Int could be a string of ABC, doesn't matter to be anything. Here, another one. Now when all those arguments arrive at the myMethod method, it will pack all those arguments into a variable called args. Args will become a tuple. And actually the RDA has told me that already, but we can verify that by printing the type of bogs down here and iterating through the logs and just printing out each one. So let's run that. Paas and test.py. There we go. Print type, args, class tuple, and then for each dogs, I'm just printing it out. One, ABC 3, and 4. So there you go. That's what that is doing. It's packing whatever you send to my method into a new argument or variable called args. Now I've used that in the bridge concepts code. Okay, so up here in the bridge concept code, down here, my interface abstraction wanted args down here in the refined obstruction, or I get those arcs and then I actually just send it off to the next method, the implementer method. So if we're going to enter the implementer, the implementer also accepted dogs. Here, I'm just giving you a type hint of tuple, which was actually unnecessary. But it's there just to show you. And in the concrete implementer, I get those args and I just printed out and same thing down here and implemented B for argonauts. I've rented out. So that's what you're seeing. You can send any of the primitive types, even an instance of a custom class. Just to show that I'll print type of egg. Instead, I'll also print a dictionary now. So a, one, B, three, C, for example, need to put that in quotes. And the last one is a dictionary. So anything you like, and in any order. Now send a list. Take tuple, dictionary and a list. Excellent. And also since it's a tuple, you could say print, dog's one, like that. 123, print args, 0. And that's the dictionary. Excellent. It's very common for people to use that syntax stocks, but you can actually use any name you like. For example, I can say my tuple. Print my tuples 0, and we go and I'll print my tuple 1. So read that as pack all the positional arguments into my variable called that excellent pause and star args argument. 36. Composite Pattern: The composite design pattern is a structural pattern. Use for hierarchical management allows you to represent individual entities, their leaves, and groups of leaves at the same time, the groups are called composites. Structural design pattern lets you compose objects into a changeable tree structure. So it's great if you need the option of swapping hierarchical relationships around at runtime and allows you to add, remove components to the hierarchy and provides flexibility of structure. So examples of using the composite design pattern can be seen in a file system directory structure where you can stop the hierarchy of files and folders. Example, Windows File Explorer, I have three, takes ballsy, their leaves, and two folders there, composites. I can take two of them there. Okay. You can get folded, be put into a folder. A I can even take them out again and change the order with that into a, a, into B. That's the composite pattern used as a file system. And also it's commonly used in drawing programs where you can group, ungroup transform objects, and change model objects at same time. For example, I have four shapes here. I can click both of those and group them. They are now a composite of two shapes, k. So the terminology, the component interfaces and interface that both the leaves and the composites, which are the groups of leaves or other composites all implement. So that's, hey, get the tree structure where a composite can contain a leaf or multiple leaves and also can contain other composites. So in the source code, two leaves, leaf a, leaf B, and two composites, 12 leaf is attached to composite one, are then changed my mind and intentionally fade a composite to then attach composite one to composite to leaf B is not attached to any composites. So composite, composite concept of PY, I'm in Visual Studio Code, composite composite concept. There is the component interface which is shared by the leaves and the composites. I have two methods. One method is just an example method called method alone is called detach and are used to attach to manage how leaf or a composite knows who its parent compo cities. So let's look at this further down. He is a leaf. So a leaf can be added to a composite but not a leaf. When you add a leaf to a composite, we create a reference for the parent ID and I just printed it. There is also a detached method which can be called if the leaf is part of a parent already. If so, we just delete that reference to the existing parent before we assign an experiment. So composite, composite is little more complicated because it needs to have a list of other components which could be leaves or composites. And they all implement the AI component interface. So paranoid with printing out the information for components into components, we run the components method, okay, so we can attach first, I will run detach if any component has a parent or not buy, then change the components reference to the parent being DID of this composite, then append this new component to the components list. So that's the client section there. Leaf a, leaf be composite one, composite two, and then I just print out their IDs so that we can see them. Composite one attached. Then changed my mind composite to attach. So in this attach method, we see that leaf a has been detached from its existing parent and attached to the new parent, composite to attach composite one, leaf B is not attached to any composites. And then we can call composite to method, which will print out the hierarchy. So let's execute that highest composite, composite concept. Leaf a. Leaf B comes along, comes a tube and say that leaf is the ID, it has no parent. So this first line here is May printing out Leaf be method which just prints out its own ID and its parent, sorry, to 64, to 64, that is linked be, the next three lines are printed out from disk composite to myth. It's printing out itself its own ID. So 736736, composite two is current parent is none, but it has two components. Then, as you can see, its own method, method for components subcomponents, it runs component method. So that's what the next two lines are. Leaf. That ID for 56 is leaf I, which is part of the first composite, composite two. And there is also another composite under composite to called composite one. So eight eighty, eight eighty is composite. And we can see here that it has no components under it. But both the leaf and the composite, their parent ID ends in seven 36, so that is composite. So that's what the component concept example is showing. That you can create leaves and composites and you can reorder them, okay, Excellent. Okay, So the next video, we'll demonstrate the composite example we use case Excellent. 37. Composite Use Case: The composite example use case now, very similar to the composite concept, except on simulating a false system with a root object, which is a composite microarrays, several files which are leaves, I create more folders, opposites, then Adam and then China hierarchy. Okay, So if I look at the example code here, you can see it's a file system or give it a name of root files, false, attach, credit folder, etc. And i then DIR the file system and prints out to the console. Now, it's just a hypothetical file system. It's not a real force system. So no real files are going to be graded or moved around on your server. Now, I then decide to move folder a in its contents into folder B. So Folder be attached to a and then DIR again. Okay, So the code structure is very similar, except I've put everything into their own imports. The main difference here is the output. As the composites go further down the hierarchy, more dots are drawn like so. So it begins to visually represent a file system structure as well. And so how I do that in the code in folder, which is the composite fall is the leaf for every component in self components, I run DIR method, which is similar to the method method and the concept example, but make indent a larger string each time. So indent starts off with nothing by default. And then as the hierarchy moves further down in debt becomes larger by two dots. And that's what we see here. Okay? And so to run it, Python composite client.print. And there you go, print it out and see, excellent. So there's the first DIR. I then move folder a. Folder B is folded a now under affordably and then DIR again, excellent. So the next video, I'll introduce conditional expressions, ternary operators. Excellent. 38. Conditional Expressions: New coding concepts, conditional expressions, ternary operators in composite, composite concept p-y, this line here, and the leaf does look quite strange. Parent ID equals ID, self reference to parent. And then if self reference to parent is not none else naught. Okay, let's look at that in VS code. There's the line there, it's actually one line, but do you auto formatting has made it into two lines and also pilings prefers lines not to be so long, so you can also read, it'll be like that. So parent ID equals the ID of self-reference the parent. If self-reference the parent is not, none else, none. This is how you read it. So its value if true condition, so if that condition evaluates to true, then that's the value else, value if false. If you've done other programming languages before and used if-else statements are usually written if something equals true, then that else that the orders being swapped around a little. So I'll just run some examples of that. Now, I'm going to create a variable sum equals bright. So I'm going to go new variable called sun is bright equals true, but only if son equals bright else false. Okay, so let's sprint. Sun is brought true. So sun is broad equals true. If x1 equals brought, else false, then other one, ice is cold equals true. Ice temperature rise temperature equals col. If IC is col equals true, else hot. So ice temperature because cold if icicles cold equals true, else hot and sprint ice temperature, cold. Another one, current value equals 99, danger equals 100. Alerting equals true if the current value is greater than equal to danger, else false. So let's see what alerting equals, equals false. Okay, So following this link down here, Let's look at the official documentation for conditional expressions. Expression x if see elsewhere, first evaluates the condition C rather than X. If C equals true, x is evaluated and its value was returned. Otherwise, y is evaluated and its value is okay. So when we go back to the code, when you see something like this, where the line doesn't quite make sense intuitively, it's possible there's a conditional expression. Okay, So the next section, we'll look at the floor away to next level. 39. Flyweight Pattern: Fluctuate design pattern fly and the term Floyd white means light, not heavy. Okay, so instead of creating thousands of objects that share common attributes and result in a situation where a large amount of memory or other resources are used, you can modify your classes to share multiple instances simultaneously by using some kind of reference, the shared object instead. A good example just got to flow. It is a document containing many words and sentences and made up of main letters, rather than storing a new object for each individual letter, describing its font, position, color, padding, et cetera. You can store a lookup ID of the character in the collection and then dynamically create the object, proper formatting, etc, when you need to know. So this approach saves a lot of memory at the expense of some extra CPU as you create the object of presentation time. So the flow a patent describes how you can share objects rather than creating thousands of almost repeated objects unnecessarily when you talk about the fly white, there is two terms that are often used. That's intrinsic and extrinsic. Intrinsic means, including are the attributes of a fly, white that are internal and unique from the other floor whites. For example, a character code extrinsic are the external attributes used to present the floor white in terms of the contexts where it will be used. For example, many letters in a string can be right aligned with each other, each new position, that's an extrinsic attributes. So terminology and UML, the fly way to interface, the interface that all fly weights should comply with is a floodlight factory, which will decide whether a floor weight can be retrieved from a cash or a new one needs to be credited at runtime, context is where the fluids will be used. This can be a word document or HTML document, Notepad. It would be the place in the application where it is used and you can have multiple things in an application which will be sharing fly weights or source code, a context is created using the string abracadabra as it is output. And it asks the flow rate factory for the next character to flog at factory will either return existing fluctuate, we'll create a new one before returning it. So abracadabra as many re-used characters, so only five fly weights need to be created. Fly weight fluid concept of PY. I'm in Visual Studio Code Weiwei concept of PY. Okay, So the flow rate interface for this example is very minimal. It doesn't do anything. There is a fluctuate self dot code, code flow, right? Factory. This factory has a static variable called fly whites, which happens to be a dictionary of int fly weight. And so there's the fly right there, and int is the code. I'm using. Type hints here. It's unnecessary if you don't want to use taught minutes. Okay, so I've set these factory up as a singleton as well with two class methods, get fluctuate and getCount. As I get a fly weight is the eternal static flow weights doesn't already have a fluctuate in it. For these code, I'll create a new one and return. Getcount is interesting to note the end, how many fly weights were created? Context, it could be anything. This holds the references to the floor waves in a particular order and converts the code to an ascii letter. It could be anything. It's just where the fly weights are used. This is a client which creates the context. These contexts, hypothetical context needs a string, so I'm passing in a string or printing out the context by using its output method. And then I'll do some statistics on okay, so let's run that fluctuate flow weight concept. Okay, So down here, 58 print context airport. That's that abracadabra has that many litres. So the length of abracadabra, so live and lead us to flow at factory has that many getCount flow whites. So five flyways, so only five new flyways needed to be credit rather than a living. Now this is a very minimal example anyway, he doesn't use a lot of memory. So where these would be more beneficial is, for example, in the real fonts system in your computer where you'll compute and C Windows fonts will have a folder full of different fonts. Now, each of the letters in each of these fonts is a set of instructions. And rather than having thousands of copies of those for every single letter in a document, it will use a fly white patent to have a reference to the information used to draw that character there. So the font system in your computer as an example of your operating system using the flat white pattern. In the next example, we'll look at the example use case where I expand on the floor away concept code to include more contexts. Excellent. 40. Flyweight Use Case: Okay, The fluctuate use case example. Take an example of a dynamic table with three rows and three columns H. The columns are then filled with some kind of text and also chosen to be left, right or center aligned the letters of the fly whites and only a code indicating the letter is stored. The letters and the numbers are shared many times in place. So this makes sense. Now the columns are the contexts and they pass the extrinsic values describing the combination of letters, justification left for ADA Center and the width of the table column that is then used for the space pending. So this example should make it clear are the differences between intrinsic, extrinsic, what the context is. So since it's a table of three rows and three columns, three columns times three rows, ends up being nine cells. So the cells will actually be the contexts, okay, so the UML, you can see the table as a row, and there's a column, three rows times three columns. Columns will all use the fly way to factory. And the factory will either decide to write new flow away or use one from the cash pay source code, fly away to client PY Galloway to client pay. Why? There's the columns there and with the IDs being three columns, three rows, 123. These are the contexts. And they've all got different letters in them. Some share lead us to fly white factory isn't going to create anymore fly weights that it needs to. So further down here I'd modify some more extrinsic attributes, justification and the widths of the columns. Okay, I draw a table and then print out the statistics similar to that. Python fluctuate Client dot p-y, we go, so it's drawn a table. The classes here describe what's going on this the table class. I'll let you look at those in your own time as rows. And each row has columns as a column. And each column will refer to the low-wage factory floor away and decimal formatting. So I'll let you go through the code in your own time if you want to. But we can see down here the flight factory has 12 fly weights. So even though there is probably over 30 characters in there, I need 12 objects needed to be crowded. Okay, so that's an example of the fly white. Okay, the next video we'll talk about the new cutting concepts at being string justification. How I used that to create a column width and align the text either left, center, or right. Okay, so excellent. 41. Python String Justification: New Cutting Concepts, string justification in fluctuate column PY, there are command center, left, justify it, and right justify. Okay, So down here where it gets data or create a blank string, read short for return for data in self data, I make read longer and longer each time depending on the response of the Floyd victory. Then in these next three conditional expressions, only one of them will resolve to true. And that is if justify equals 0, 1, or 2, that was set up. He went, I initialized the column justified default equals 0, justify a lie the center justify the return string, left, justify the return string, or right, justified to return a string. So that's what's going on those three lines. There's three conditional expressions. You excellent. So in order to try that out, you can one that using the Python interactive console. First one, cross string a, b, c, d, e, f, g dot center. And I can use 20 spaces to decide how that is centered. Now we go and that's what I'm also using as my column width in the last video to make the table appear rectangular. And the one right justify and left justified, right? They go quite simple little string functions that you can use there. Do you might find useful one day, Excellent. In the next video, we'll talk about the proxy. Excellent. 42. Proxy Pattern: Proxy design pattern is a class functioning as an interface to another class or object. Proxy could be for anything such as a network connection and object in memory, a file or anything else. You need to provide an abstraction between tops of proxies, virtual proxy, an object that can cache parts of a real object, and then complete loading the full object when necessary. This first example, the proxy concept will be similar to a virtual proxy. So remote proxy can relay messages to a real object that exists in a different address space. You may have used Engine X as a reverse proxy once or twice if you work in web development, that's an example of a remote proxy. Our protection proxy ploy an authentication layer in front of a real object. If you're running web services, you can add authentication in front of that using various libraries and a smart reference proxy and objects whose internal attributes can be overridden or replaced or demonstrate a smart reference type proxy in the example use case. So additional functionality can be provided at the proxy obstruction if required, which is what these types of proxies are really doing. Example, caching, authorization, validation, lazy initialization, and logging. So the proxy should implement a subject interface as much as practicable so that the proxy and the subject of P identical to the client. Okay, So terminology, a proxy is the object with an interface identical to the real subject and act as a placeholder until the real subject is loaded or as a gatekeeper applying extra functionality, the subject interface, this is the interface implemented by both the proxy and the real subject. So the real subject would have some kind of interface. So your proxy has to support that interface. So the real subject, the actual real object that the proxies representing the client, the application, the users, and creates a reference to the proxy, okay, So UML, in this example, the client will create a proxy and make a request to the real subject. The first time the request is made, it will cache some data so that the second time to proxy calls the request, it will take the data from the cache. So the proxy will call the real subject multiple times and won't know that there's a difference. What is actually going on behind the scenes, case, a proxy, proxy concept of PY, Visual Studio Code proxy proxy concept. Okay, so Subject interface has a request method is a real subject and the real subject has some enormous data. Now this is hypothetical. It's only three numbers in a list, but imagine this being something that warrants the presence of the proxy, okay, So proxy also implements I subject. The proxy in this case, will act as a cache for the enormous data and only popular denormalized data when it is actually necessary. And that will be only when it is actually requested from the client the first time. Now, when on your slides or proxy, I'm creating a place holder for normal data and then also indicating to the proxy what its real subject, All the address of the real subject or anything like that. Okay, so request, at some point in time the client will call the request method. If enormous data is not already populated with something, it will get the enormous data from the real subject by Corner Rule subjects identical message, and then it will return the enormous data. But if enormous data does equal something, which means it's already been called once, then I'm going to return from the cache. So it's a pretty basic proxy. This kind of thing can save on server loaded. For example, enormous data was very resource intensive. So to try it out, whites and proxying proxy concept. And I go, I'm creating the subject, printing the ID to shine that it exists. Print subject dot requests. So subject or request pulling data from the real subject. So I'm printing that they're pulling data from a real subject. Later on, I then do subjects request again, and this time I'm pulling data from the proxy cache. Both times, I'm just printing out the value of enormous data as well. So as we see here, 123123, 0. So that's just a very simple example of a proxy. In this case, the Roxy is acting as a placeholder until it's actually necessary to fill it with some data. You might use something like this is in an application that shows a lot of images, but you don't want to download all those images from the web server in one go. So you can use placeholders instead. And then when it's actually time for the client to load it, it will load that graphic. So imagine a Word document with images in it and the image placeholder exists but is only loaded into memory when it is in view. So that's one type of proxy described in the Gang of Four ends. In the use case example, I'll create a smart proxy where I'll change the internals of the instance to be using methods from a different class. Excellent. 43. Proxy Use Case: All right, proxy, use case example, this will be a smart reference proxy. In the example, I dynamically change the class of an object. So I'm essentially using an object as a proxy to other classes. In my classes, there is a method, Tell me the future, which when called, will randomly change the object to use a different class. Now this is based on Greek mythological character named Proteus. When you ask Proteus to tell you the future, it changes its form. So that's what this is doing. So in my client application down here, I create a line which implements the oil Proteus interface. And if you asked a line to tell me the future, it will change its form randomly to either a serpent or a lipid. And then the same thing again, if you ask the serpent, tell me the future. It will randomly change itself to whether a lawyer or lipid. And same with the limit. Now is we're just demonstrating this a smart reference proxy. The actual instance that I cried first doesn't actually change, but the internal references to the new methods will update. So let's open VS Code and Proxy client PY. So acquire line proteus. Proteus. Tell me your form and it will say warm alone. Now I say tell me the future and then it will change to something we didn't know what it is. So we'll say Tell me your form again. So just to run that python proxy, client.print, okay, so on the form of a lion, now in the form of a serpent line, a lipid line. So it's random every time, each time you run it, it'll be different. Okay, so what's actually happening? They interface Proteus, a Greek mythological character. I can change too many forms. Tell me the future. Proteus will change form rather than tell you the future. Okay, So let's look at line. Tell me the future. Self dot class equals lipid, Lipid if random into 01 else serpents server, that is a conditional expression. If random returns 0, it will be a lipid. Lipid. If it returns, one will become a serpent. Serpent. Then class method Tell me your form. So loin, serpent and lipid, We're all very much the same except which new class the instance becomes spending on the random number. That's, it's very, very small amount of code. But as you can see, the methods when you call tell me your form down in client, tell me your form. So Proteus hasn't changed, gives a different result every time. So very small example, but anyway, let's look at the summary, okay, so a proxy forwards requests onto the real subject when applicable, depending on the kind of proxy, a virtual proxy can cache elements of a real subject before loading a full object into memory. So like the first example, I loaded the enormous data into memory. You could have an object with several properties where some are loaded into memory and you slowly build up the object over time. Using the proxy or protection proxy can provide an authentication layer. Commonly you would use an engine X proxy for that, but you can actually get libraries to add authentication layer in Python. So proxy can perform multiple tasks if necessary, a proxy is different than in an adapter. The adapter tries to adapt to existing interfaces that aren't compatible, whereas the proxy uses the same interface as the subject. Okay, so it's also very similar to the facade, except that you can add extra responsibilities. So the facade is a very simplified proxy, its side. So if you take the facade of why the system would still work, which is the same as the proxy, but the proxies adding extra responsibilities to warrant the existence of the proxy. Now similar to a decorator, decorator adds responsibilities, but a decorator is Britain to run recursively as like I did in the ad and they submitted and the decorated section. Now the intent to the proxies to provide a stand-in for when it is inconvenient to access a real subject directly. So that's the proxy versus the facade. So the proxy design pattern may also be called the surrogate design pattern. You may have seen it excellent. In the next video, I'm going to talk about the class attribute that was introduced here in the lipid serpent and loin cloth. So that one there, Excellent. 44. Python __class__ Attribute: Okay, you're cutting concepts, class attribute. You can change the class of an object by executing self class equals some other class. And I did doing this does not affect any attributes. Credit during initialization. Example, self.age instance attribute equals abc since the object itself hasn't changed. I'll demonstrate this in the example below. I need the references to its methods to static attributes have been replaced with the methods and static attributes of the new class. So this explains how calling tell me the future and tell me you form from the proxy use case, produce different results after changing self class. So Blow is some code to demonstrate our changing and instances class does not affect any instance self level attributes. So let's copy this code To Clipboard using that arc on there. I've opened into Visual Studio Code. I've got test.py. I'm going to paste that, save and let's look at it. Now. At the beginning, I'll go a class called Class I with a static attribute called a. It has an init method with self, self dot instance attribute equals i. I've got an instance method which uses self. So instance method I will just print that now goes static method, which prints static method. I go to class method, which prints class method I. So I'll create a new instance of class I, and then I'll change its claws to be class B. And we'll see that the class method, static and instance method and the static attribute or update To Class B's version, which will print B's. But the one that doesn't change is the self instance attribute at pace. So down here, I equals class. I am going to print out the ID of I and predict all the attributes of it and call its methods. And you will see that that will all come from class I down here are then change IS class using the class dunder attribute to class B or print Id of I again, and the ID will remain the same, but the static attribute will be different. The instance attribute with the same instance method would have changed same with the static method in the class, missed it. So Python test case, so the IID, so the same static attribute, ICT, static attribute B. And so that changed instance attribute I, instance attribute I didn't change, that's self dot instance attribute I see in class BY itself, instance attributes should equal B, signaling. That's because it's using self instance attribute. And continuing on instance method be static method BY clause method base. So when you changing a class, just be aware that anything that was created during initialization or that you reference voice self does not change. Now down here in the instance method, I'm actually just going to print this instead. So instance method, self instance attribute and do the same with AI. And we'll see that again. Okay, so still says instance attribute for B. So there you go, some little detail, but changing and instances class at runtime. Excellent. The next video we'll talk about circular imports. Excellent. 45. Avoiding Circular Imports: Alright, you're coding concepts, circular imports normally in the examples. So far, I've been importing modules using the form from module import class. So you'll see that for instance, factory client from Jeff Factory, import chair factory. And it's like that all through the code examples in the course. But more specifically in a proxy section, I import the line module. So Proxy client, so Proxy client PY from line, import line. Now the law in module itself also imports lipid and the serpent modules that in turn also re-import the line module again. So lipid imports line and serpent impulse line. Now this is a circular import and occurs in some situations where you separate your modules into individual files. If you see how I've been doing the concept version of the code, usually putting into one file. And then when I demonstrate the use case, so usually split them up into separate files. Okay, so circular imports will prevent the Python interpreter from compiling your PY files into bytecode. So the error will appear like, you'll see most likely due to a circular import written in the error message. Okay, So to avoid circular imports is you import a module using this form. So just type import module versus from module import class, say import module. And then when you actually go to use the class, you say your object equals module dot class name. So looking at the line circuit in lipid classes, for example, if I go to leopard, this is already fixed because I'm importing line and down when I'm using it, I'm saying use line, dot line. But before doing this, it would have been from Lyon import lion. So down here, I would say just use the line class now falls to try to compile that. Saying, Hi Ethan, proxying client.print y, I get the circular import error. Okay, So the way I'll fix that is by saying instead import lion, muster name of the file down here, lined up PY and then down here when I go to use it, I'll go line hotline networks, but now that will execute them good and excellent. I mean, we could do the same thing with from interface proteus, Proteus. So I could say import interface Proteus plus lipid interface proteus. Proteus. Excellent. And it works excellent avoiding circular imports. In the next section, we start looking at behavioral patents and we'll go to Command Excellent. 46. Command Pattern: Okay, now the command button, command pattern is a behavioral pattern in which an abstraction exists between an object that invokes the command and the object that performs example a button will call an invoke that we'll call a pre-registered command. Now the receiver will execute. So a concrete class would delegate a request to a command object. Instead, I'll be implementing the request directly. Okay, So the command patent is a good solution for implementing undo redo functionality into your application. And you'll find it being used in GUI buttons, menus, macro recording, multi-level underrated networking. You can send whole command objects across a network or batched parallel processing or thread pools transactional behavior. So you can undo reader wizards. So the terminology in UML is a receiver object that will execute the final command and invoke a, which sends the command to the receiver measurement invoke as a button. Then out of the command objects which implement the arc command interface di have an execute method or an action method and contains all the information that is required to execute command on the receiver. The reason for this is that you can have multiple invokers. For example, you could load a file and it would re-execute a whole bunch of commands that were executed the day before using a user interface, such as replying a set of commands in the source code, I call it instantiates a receiver that accepts certain commands that do things. So the client then creates two command objects that we'll call one of the specific commands on the receiver. So the client encrypts your vocal example, a user interface or buttons and registers both commands into the invokers dictionary of commands or list of commands the client doesn't call the receivers commands directly or via the univocal, and that then calls the register commands execute method. So this abstraction between Mocha command and receiver allows you to add extra functionality such as history, replay, undo, redo, logging, alerting, and any other useful things that may be required that are now possible because of that extra abstraction between the vocal and the receiver. Volcker and the receiver. Back to the source code command, command concept, though. So I've opened up in Visual Studio Code, the command interface has just the one execute method. So Dean vocal, there is an invoke which has methods to register commands and execute commands. So it also has a dictionary of commands that when we register the commands, we'll give it a name and a command and it puts it into the dictionary. That's the key, that's the actual command. And that command contains everything needed to execute the command on the receiver. So down here, there's the receiver. It has two commands, every basic that I need, anything. If something says Run command one, it will print executing command one sound was run command to executing commands. These are the command objects, okay, so Command one implements all commands, so it hasn't execute method. When you initialize the command, you tell it who the receiver is going to be. So this command is composed of a receiver. So when you want it to execute method, the receiver will run Command 1, command 1. Now I've called this command, command one, and it's very similar to Command 2, is composed of a receiver. When he calls execute method, you will tell the receiver to run command to k. So this is the client section down here. Okay, So the client creates, a receiver, will create some commands telling them how the receiver is accrediting Volcker, we're registers commands in the invoke, so there's 12. And now at anytime we lock, we can go invoke, execute one, invoke, execute, cetera. So to run that Python command command concept of the war, It's just printing out executing commands one to 12. So this is the conceptual example. It's concentrating just on the abstraction between the invoke and the receiver. Okay, so in the next example, an example use case. I will improve on that example by using it in the context of a smart light switch, which logs history and you can replay Excellent. 47. Command Use Case: Okay, the command pattern, use case. This will be a smart light switch, your lights, which will keep a history of each time one of its commands was called Andy can replace commands because of the command interface, you could extend this light switch in the future to be called remotely or automated depending on census. So the UML, the switch is the Joker and the law, it is the receiver. And there are two commands, or switch on command and a switch off command. You could have multiple commands to give a slaughter command if you wanted to, which had variable settings. Anyway, they're both implement the switch interface. Now, the switch invoke a here has two extra functions, show history and replay, last case, so we'll see those. So the source code in Visual Studio Code open command client. Okay, So there's a light and a switch, a switch on commanders, which all command, that's the receiver with a lot of the commands, switch on command is composed of a receiver. Switch has two commands on and off. So we can now start flicking the switch on and off, on, off, on, off, on, off the show, the history. And let's replay the last two. So if you run that command client P1, you can see here turned on, off on and logged a time and a lot on and off. And then I replayed the last two. Excellent. So the interface switch, just as the execute method, that's the off command, the receiver has its own turn off method and a turn on method. So the scope to the receiver being the light occurs. So it's just printing on load off switch, which is invoke. It has its own dictionary of commands, but it also has its own list of history. So each time a command is executed, self.users three append the current time and the command name. Okay, So then later down and replay last number of commands to replay commands equals self history minus number of commands. So I'm saying give me the last two commands from the list then for command and commands, self commands execute. Now when I'm re-execute these commands in the replay function, I'm not adding them to the history again, if you wanted to, you could run the execute method instead of just running the commands, execute directly. Summary, each command should be stateless, okay, so don't manage state of a receiver inside the command, the receivership manage assigned state with the command should change that state. Now, there can be one or more invokers that can execute the command at a later time. So while you might be tempted to have a client that can call a receiver's message directly. If you do it via the Volcker, you didn't have all those extra options such as underrated, replaying, cetera. Okay, So the command pattern is similar to the Memento, which we'll talk about later in the way that it can also be used for undo redo. However, the Momento is about recording and replacing the full state of an object or receiver, or even a large portion of the state. Whereas the command pattern executes commands that change the state, such as draw, turn, re-size, save, cetera. And finally, as a simple example of using the command is program, we'll be using the command pattern behind the scenes. So if I copy that and paste it, I can press Control Z undoes, Control V to paste again, I can move it, I can resize it, I can rotate it. Now, each of those different things that I'm doing are being executed via the command interface, which means that the application was able to create a history of it that I could undo and redo. Excellent. So in the next video, we'll talk about the single leading underscore that I've used in this section. Plus, you may have seen it in some of the earlier sections as well. Excellent. 48. Single Leading Underscore: Okay, new coding concepts, the single leading underscore. Now the single leg underscore, you'll see it starts with an underscore and then you've got the variable name or attribute name. So when you used in your class variables or attributes is a useful indicator to other developers, to this property should be considered private. Now, private in C-style languages means that the variable field property or attribute is hidden and cannot be accessed outside of the class. It can only be used internally by its own class methods. So pause and does not have public private access a concept. So the variable is not actually private and can still be used outside of the class in other modules if you want. Now, it is a useful construct a, you will see other developers used as a recommendation not to reference this variable directly outside of this class, but use a dedicated method or property instead. Okay, so open Visual Studio Code in this switch dot p-y here. When I initialize it, I've got self underscore commands and self underscore history. You should consider those as private variables. So while it's okay to use those inside of the class itself, and I do. So commands history is used everywhere. You won't see me using it outside of this class. So if I go to client.print, iron reference, underscore history or underscore commands directly. I'll use it via a method, and that method doesn't have an underscore in front of it, so then you can consider that public. So I've also used that in the fly weight down here, in the fly way to factory dot p-y underscore fly weights, which indicates that you might see that variable being called directly outside of lightweight factory class in case a single leading underscore today in the next section, we'll look at the chain of responsibility pattern. Excellent. 49. Chain of Responsibility Pattern: The chain of responsibility pattern, behavioral pattern used to achieve loose coupling in his pattern, an object is passed to a successor and depending on some kind of logic, will or won't be passed onto another successor and processed. They can be any number of different successes and successes can be reprocessed to recursively, okay, so the chain of responsibility passes an object through a series of successes and D can be used recursively. Now this process of passing objects through multiple successes is called a chain, okay? So the object that is passed between a successor does not know about which successor will handle it. It is an independent object that may or may not be processed by a particular successor before being passed on to the next. So the chain that the object passes through is normally dynamic at runtime or Dagan hard-coded, each successor will need to comply with a common interface that allows the object to be received and passed on to the next successor or used recursively. So terminology, handler interface, that's dean to face that all the successes must comply to the concrete handlers. That's the successes. And the client is where the channel responsibilities used k source code in this concept code, uh, China's created with a default first successor and number is passed to the success and then does a random test. And depending on the result, will modify the number and then pass it on to the next successor. The processes randomized and will end at some point when there are no more successes designated. So open the code. I'm going to Visual Studio Code, China responsibility and a chain of responsibility concept dot p-y. Okay, let's run it. Chain instead of me typing out the whole folder name chain of responsibility, I could just type a few letters and then press tab to see a tab and it fills in the rest of the text. Okay, So that was the dissolved quite quickly. Let's do another one. Okay. The number this time is 000. Each time it's randomized. This time it was in the chain for quite a long time before it gave me a final result, okay, minus 1.25. So each time you run it, it's going to give you a different result. So the handler, That's the interface, it just has a handle method with a payload attribute, successor one handle. We do a random test. I printed out the payload. I do a random number tests between 12. If the number equals 1, then I'll add one to the payload and then successor one dot handle payload again. And that's recursion or if test equals to subtract one and I'll send it onto successor to, successor to handle payloads. So his successor to I print out the current payload value to it on the test between 13. If test equals 1, I multiply it by two and then pass it on to success of one. Handle payload test equals to 0 divided by 2 and then successor to handle payloads. So what is actually happening is the payload is passed into the first successor down here at the start method. So chain, that's an object that will start the chain over Start Method by sending a payload. So payload equals one chain dot star payload. And the first thing it does is sends it off to success, a one to handle. But depending on the results of random numbers that are the loops back around a success of one or onto successor to and successor to then either puts it back to 6 or 1, or back into a successor to. But if the test here equals three, then it just finishes and returns to payload at the end. And that's what we see down here. Out. There we go. So that's a very simple conceptual example of the chain of responsibility pattern. Just so that you can see the parts of it and you can see how an object is passed through successes and potentially recursively, and at the end you get an output. Okay, so the next example, we'll look at the example use case where I'll recreate an ATM. Excellent. 50. Chain of Responsibility Use Case: Okay, The China responsibility example use case in the ATM example below the Chinese hard-coded in the client first to dispense amounts of fifties and then 20s and then tens in order. Okay, so this Chinese hard-coded versus being dynamic, since it ensures that there's a minimum number of notes being dispensed. So otherwise it might dispense five tens when it would be embedded to dispose 115. Uml, there's a client and there's an atm, dispenses a chain that is composed of dispensers, 10, 2050 for each denomination. And all the dispensers implement the artist Spencer interface, which describes who is the next successor. So dispense a fifties next successor is going to be expensive 20, and its next assessor is going to be expensive 10. And then there's the handle which processes the amount passed into it as it goes through the chain code, source code, client dot PY. So ITM dispense a chain is much ONE. What we'll do is we'll enter an amount and we'll use input. So I'll talk about import in one of the next videos. And then we ATM chain handle the amount per atm dispenses a chain composed of three different dispenses 50 2010. So chain one, I'm hard-coding its next successor to be changed to change to I'm hard-coding its next successor to be changed three to one, that's credit. So chain one, end or a mess. So dispense a 50 which is chained one. The amount is greater than equal to 50, willing calculate the number of nights. So we're going to need, and if there's anything left over, we pass it on to the next successor. Else, if is less than 50, we just pass it on to the next assessor anyway, the amount and that's the same for 20 and 10 until at the end, we can spend the money. Okay, So let's run that. Python shine client.print, enter the amount. Okay, so that's now asking for user input. So we'll talk about that in the next few videos. 180 is a good number, so it's dispensing 350 pound notes, 120 pound and 110 now go spores. So, okay, So there's, I use case of the chain of responsibility patent. Okay, So summary, the China responsibility, the object payload will propagate through the chain until fully processed. The object does not know which success it or how many will process the next successor. And the chain can either be chosen dynamically at runtime depending on logic from within the current successor or hard-coded. If it is more beneficial, successes implement a common interface and makes them work independently of each other so that they can be used recursively or possibly in a different order, or use a wizard or dynamic questionnaire are the common use cases for the chain of responsibility pattern. Now in the next videos, we'll look at floor division and as just demonstrated, accepting user input, Excellent. 51. Python Floor Division: New coding concepts, floor division in the previous ATM examples in all the dispensers, I'm doing this division, division does double division character here. That's me doing flawed efficient because I want the number to be an integer, because I've printed out as an integer, I don't need to say 1 or 2 notes because by default, using one slash or result in a flood. So we can test that in the past and interactive console nine divided by three. This time, I'm going to use an online service from ripple. And here on the right, I have Python interactive console already in the browser. And I can just write nine divided by 32 only gives me 3. Okay, so I'm using Python 3 there. Now if I wanted that to be an integer, I could just say 9 divided, divided by 3, that means floor division. You can read more about that here at 0, 2, 3, 8. And that's just a very small subtlety that's now available in Python 3. Now, if you were using Python 2.7, which you can choose from this website, and 2.79 divided by three would give a different result. It gives an integer in Python 3, 9 divided by 3 gives 3. But before you say Python 2.7 is better if you were to do 10 divided by 3, it tells you it's an integer as well. So he's expecting 3, something else. So if I go back to Python 3 and go 10 divided by 3, well that's a more realistic result. So be careful when you're doing division of the version of Python that you're using, version three or version 2. So this course is about Python version three, excellent. In the next video, we'll talk about accepting user input. Excellent. 52. Accepting User Input: Cutting Concepts, accepting user input in the file chain of responsibility, Client PY above, there is a command called input. Okay, So that's it, the input and then a string written to the console. And then whatever is input gets converted to an integer and then put into a variable called amount. Now if you're using Python 2.7, instead of using the word import, use raw input instead, okay, and you can read about that data link. So just to demonstrate that, I'm going to use PowerShell of open Python interactive console. Okay, so input message here, and then I'm just going to add some space at the end, press Enter, and now it's waiting for me to type characters in. And when I press Enter, that gets output again to the console. So here, input enter, amount to withdrawal gets put into an integer. So you need to put in a number and then amount, okay, excellent user input. Now, you can use user input in any of your Python programs when you want to ask the user printing. Okay, Excellent. So the next section, we'll start looking at the observer pattern. Looks like. 53. Observer Pattern: The observer pattern, a software design pattern in which an object called the subject or observable, you might see it called manages a list of dependence called observers and notifies them automatically if any internal state changes by calling one of their methods, the observer pattern is very commonly used in a lot of frameworks that you'll find if you do web development. So the observer pattern follows as publish subscribe concept. A subscriber subscribes to a publisher and the publisher then notifies subscribers when necessary, observe up stores state that should be consistent with the subject, the observer on he needs to store what is necessary for its own purposes. Okay, So you will commonly find the observer pattern used in MVC frameworks, but you didn't have to use it in an MVC projects. It's just where you're likely to find it used quite often, so you will recognize it when you see it. Okay, So MVC projects have a controller which is a single source of truth, a model which is a link or relay between the controller and the view. That's the, the down the end of the presentation layer. So often if you separate logic and presentation, you'll find that the presentation layers will contain observers and the subject will be at the business logic side, you can place your observers and observables, aka subjects anyway you like, okay, so it's just one way to manage the flow of data from one component to the next also gives up a pattern allows you to vary the subjects and observers independently. You can reuse subjects and reuse observers. Most commonly you'll find the observer pattern set up as a push model where the subject pushes updates to observers, but observers can also request for updates from the subject if necessary. And another thing too, that observers can ask a subject for only a small part of the data that is relevant. That subject is decoupled from the observer so the subject doesn't store observer specific information about it terminology in the UML. So there are interfaces, so Subject interface and observer interface. So all observers must implement the notify method and subject or subjects implement at least a subscribed, unsubscribed in none of my methods. So the concrete subject is the observable, the object that is the subject, and the concrete observer, which is the observer in the application. They can subscribe or unsubscribe it anytime they wish. Okay, So the source code in his concept example, there'll be a subject to observers will be created. They could be across a network, but for demonstration purposes or within the same client, the subject notifies the observers. One of the observers unsubscribes the subject notifies the remaining server again about the new information. So observer, observer concept. Why in VS Code observer, observer concept dot PY and we'll run it harvests and server, server concept PY, okay, So there are two IDs here. So two observers were created and they got their notifications and then one of them left and then the remaining observe on with that ID go a second notification. So that's the client code, their credit subject observer I insert for B, they're both observers which are composed of a subject. So observer be subject, dot notify. This is the first notification. It's just a list of numbers. Observer B has now unsubscribed from the subject noun. Subject notify again, and all remaining observers wish there's only one, will get the second notification and his time as a dictionary. The observable interface with the subscribe, unsubscribe, and notify methods that the observable or subject should comply with. Subject when you initialize it, it's creating a sit. Now we'll talk about set in one of the next videos. But a set is perfect for the situation and I'll describe that later on. But the set will be a collection of observers. So that down here for observer in self observers, when we call notify, it will call the observers notify method and pass along any of the arguments that was supplied to notify dogs were just passing it on to all the observers in self.age observers, which is the set. Okay, so there's two methods to subscribe and unsubscribe. So an observer can subscribe where we add to the set or remove self observer's eye observer. When we initialized the observer, we tell it who its subject is or observable, and we subscribe to the observer. So the observable then notifies these observer, whereas time, okay, and that's what happens. We wanted. Excellent. So you can read that, test it out, and understand the relationships there. Now, note that the observer were subscribing to the subject and there were any number of observers subscribing the subject was notifying due to some event that could have happened. Now know that observers don't have to wait for a subject to notify them and observe. It can also ask the subject for the latest information required. The Observer describes a publish, subscribe kind of situation where basically there something set up to receive notifications from a subject when the subject has new information. Okay, so in the next example, we'll look at the example use case where I will use it in context of an NBC structure. Excellent. 54. Observer Use Case: Okay, The Observer example use case. This mimics the MVC approach described earlier. There is an external process called a data controller and a client process to hold the data model and multiple data views. Now the data abuse or a pie bar and table view. Just for the purpose of this exercise, the data controller will actually be in the same process as the client. The data model subscribes to data controller and the data views subscribed to the data model case. So the client sits up various views with a subscription to the data model. The data controller updates the external data and then the data propagates through the layers to the views. Okay, so if we look at the UML, There's the three views here that will run in the client pie graph bar graph, table view. They all implement the data view interface. They are composed of the data model, which implements the data model interface. So diploid bar and table or subscribe to the data model. And the data model subscribes to the data controller down here. So the data controller will be updated using some other hypothetical external process and notify the data model which then notifies high bar in a TableView. Let's look at the source code, the client dot p-y here and observe a client pay war. There's a data model and deploy graph bar and a TableViews are their own class which are imported up here. And they all are composed of the data model. Looking at this data model more closely is the data model.py there. When I create it, I'm hard-coding its data controller and subscribing to it. Okay, So back to the client. The data controllers look at that data controller. It has a collection of observers, which is going to be the data model. A data model has subscribed. It can also unsubscribe, end, can be notified. A data model again, also has a subscribe or unsubscribe and can notify its own observers. Now, if we look at the observers in a data model, I'm using a dictionary, the observers in the data controller, I'm using a sit. It doesn't matter what you would prefer to use. In this example, I'm showing you different ways of doing it. Where in the data controller where I'm using the set I can add and remove from the observers. I use the dictionary as the observers. It's a different kind of process in order to add an observer to the observers or takeaway. Okay, Excellent. Again, back to the client data controller is getting new data. So I'm going to notify all the data models where there's actually only one, which is just a list of 1, 2, 3. Okay, so that will then update the bar, the table and the pie graph automatically because everything has subscribed to the data model that is being updated it in this line here. And then in the next step, I decide to remove the bar graph from the client. So I call delete, which unsubscribes itself or like a bar graph view unsubscribes itself from its ARN observable, which was the data model which was set when it was initialized, declared back to client a bar graph view bar graph view data model. The data controller then gets updated information and then notifies the model, which then notifies the views. So we can quickly so that run twice and observer client.print. Okay, So pie graph drawing, bar graph, drawing, TableView, There's not a notification down here, 4, 5, 6, pie graph drawing, table view, drawing, looking at the diagram again, there's a data model which subscribes the data controller and the views which described the data model. Excellent. In the next video, we'll look at the Python set, which I have just introduced in this last section. Excellent. 55. Python Set: New coding concepts often sit apart and sit is similar to a list, except that the items in the set are guaranteed to be unique even if you try to add a duplicate. So I'll sit is a good choice for keeping a collection of observables, since the problem of duplicate observables is automatically handled. Ok, so you can't add an observable twice. So the observable isn't going to get the same notification twice. Okay, So second be instantiated brief field as 123, using those curly braces or using the keyword sit, as I did, just stop here in observe a data controller, PY observers equals a sit. Okay, So was in square brackets or lists for a list and parenthesis or tuple, tuple. Okay, so note that even though it's curly braces, It's not the same as a dictionary that also uses curly braces, since a dictionary items or credit as key value pairs, i, ae, one, b2, c3, go so far as to say I equals curly braces. This is going to be a dictionary. So Taipei is a dictionary. So if I wanted to be a set, I'd have to say I, the course set. So now type of I equals a sit. So sets are like I really reduced functionality, list or tuple. Now sets can be modified like a list at runtime, so they are mutable. So example items, Yankee Doodle Dandy dual. Now if I print items, it just says Yankee Doodle Dandy. So it's only giving me the unique items hasn't duplicated doodle. So let's add an item or items, add grandiose as print items again, Randy Yankee Doodle Dandy, and we can remove all items removed hurdle, sprint items, Grundy, Yankee dandy, excellent. So if you only want limited functionality and you want the items to be unique, then a set is perfect, Excellent. The next section, we'll start looking at interpreter excellent. 56. Interpreter Pattern: The interpreter pattern helps to convert information from one language into another. Now the language can be anything such as words in a sentence, numerical formulas, or even other software code, other languages. The process first is to convert the source information into an abstract syntax tree of terminal and nonterminal expressions that all implement and interpret method. A non-terminal expression is a combination of other non-terminal or terminal expressions. Terminal means terminated by there is no further processing involved on the expression. And IST route starts with a non-terminal expression and then resolves down each branch until all expressions terminated. So an example is I plus B, the I in b terminal expressions. The plus is non-terminal because it depends on the other two terminal expressions. So here's an image of the expression, 5 plus 4 minus 3 plus 7 minus 2. So the five, the four, the three, the terminal expressions and the operators are non-terminal because they depend on the numbers on either side. Okay, so at the bottom, I'm starting with two terminal expressions, the five and the four, the non-terminal plus loci that now exists as its own expression that fully terminates, go up, whatever the result of that was, I subtract, that's the next non-terminal using a three and then again plus 7 minus 2. So in this example, this is the root. So when you process this IST, everything will be resolved. Now the official interpreter pattern described by the official Gang of Four design patterns book doesn't state how to construct an abstract syntax tree. That is a different problem, involves different techniques. How your tree is constructed will depend on the grammatical constructs of the sentence that you want to interpret. Now the sentence remember, can be anything, numbers, words, computer languages. So in these examples, I will manually create an abstract syntax tree. And then in the next example we will be automated. You can see how you might approach these problems yourself. Now once the ice tea is created, you then choose the root node. And in this example is quite easy. It's actually that one right at the top of the diagram. And what that means is when you pass that into the interpreter, the interpreter will recursively resolve all branches until they all terminate. For example, if you passed in that one, all eyes were termini but not those ones there. So okay, listen to the terminology the client or look at first builds so as given an abstract syntax tree to interpret, so here's as other builds it itself or its given it. So if you manually creating it, your giving it, the context is a state that can be passed through each interpret operation. Now in the first example, I don't use the contexts. In the use case example, I do. It's an object or attributes or properties that H interpret method can use as it traverses through the interpretation. Okay, so the terminal expression is a leaf node expression. It's an expression of terminates, such as the numbers in the example before. Non-terminal is a composite of terminal end or nonterminal expressions. Abstract expression, an interface that describes the methods that all the terminal and non-thermal expressions should implement. Okay, so let's look at the source code. In the example, I will interpret the string five plus four minus three plus seven minus two, and then calculate the result. The grandma of the string follows a pattern of number, operator, number, so number operated number, right? Number. So it's very simple, grandma, yeah, I convert a string into a list of tokens. Can then refer to by index and then construct a EST manually by adding the non-terminal row containing two terminals for five and for a non-terminal subtract for the previous row, enter three, a non-terminal add for the previous row, and the seven are non-terminal, subtract for the previous row and the two, now the IST root becomes the final row that was added. And then I can then run the interpret method on that, which will then interpret the full IST recursively because HIST references the row above it. Okay, so there's the code interpreter, interpret conceptually why, okay, abstract expression, it has interpret method that all terminal and non-terminal expressions should implement. Okay, number is a terminal expression, it has an interpret method, and when you initialize it, it's just a value of integer value repro, this is overriding the representation dunder method, very similar to the SDR representation. I'll describe that in a later video. What you can see now is that it's just going to return a string version of the self-value. When I print the output at the end, add is a non-terminal expression. When you initialize it, you're passing in the left and the right to interpret method. You will interpret whatever was left plus whatever was right. Now this is recursive, so this is calling interpret method on whatever left was because lift is also an abstract expression, same with right. Subtract a non-terminal expression. So left minus right. Here, I'm just printing out a string. And this is the client, this is my sentence. I'm printing it out. I'm splitting it into tokens, which is a list containing a five, a plus or a minus 3, or print that out. And now I'm mentally create an abstract syntax tree from the tokens. Now, because I'm credit is manually, it is expecting a sentence to consist of 12345 terminals for non-terminals in this number, operator number order, okay, so AST, this is a type int. You don't need to use them if you don't want any case iss t equals a list ice tea append I'm adding, which is nonterminal, the number which is terminal token 0, number of tokens to so that's the 5 plus 4 section. Ice tea append, subtract whatever iss t 0 was, I S T 0. They're subtracting the number at whatever tokens for. So that's whatever the result of that is, minus three, et cetera, et cetera. So this is creating the abstract tree manually, okay, So the ice to route a is T pop. Pop is a method that you get with the list that removes the final element and put it into a variable. So a is two root equals AST pops. So it's taking the last item in the list. Now I is t root interpret, and since it's going to return a string, I'm just going to print that out. Okay, Now here I'm printing out the representation of the iss t root and that's where I'm using the repro functions here. I actually could just get away with using string by using reports so that you can see that that's also possible. Okay, So let's run that. Interpreter. Interpreter constantly war. There's my sentence, 5 plus 4, etc. That's it. Split up into a list. That's what I did here. I split the sentence into a list separated by spaces. Down here, I'm printing the result, which is a calculation of the sentence, which is 11. So mathematically that equals 11. And down here I'm printing out the representation of the AST root 5, add 4, subtract 3, add seven, subtract two. So these brackets and the words and the numbers coming from this representation method. Yeah, So bracket, so flip, subtract. So Freud, now remember the non-terminal expressions. Lift can either be a terminal or non terminal and the same with right. Okay, So excellent. Now as long as your sentence follows this format, you can do other numbers. So I can add 15 minus 20, minus 1 plus 77 was 22, For example. Let's draw that out. There we go. 89. So that is the concept of the interpretive method. I'm creating the abstract syntax tree manually. And as long as my sentence follows the same format, number, operator, number operator, and the I, two operators I have a plus and minus, then it will interpret. Now, if you want to experiment with this, you can add more operators like multiplication or division if you like. And that's the operator just there. It's actually being run on the result of each left and rights interpret. Or we can move on to the use case example, which expands on the concept example by creating the IST dynamically and also accepting Roman numerals. Excellent. 57. Interpreter Use Case: The interpreter pattern, the example use case. It expands on the concept example, but also accepts Roman numerals and creates the IST dynamically. So it's much more sophisticated than the first one. But if we look at the IST diagram, so that's the sentence passed in right down here. These four boxes of abstract expression, which consists of two non-terminals and terminals, it's 5 plus 4. And it will also convert that to a number version of that Roman numeral and so on. Vii equals seven. Okay, so the UML client abstract expression, everything must implement, interpret. There's a number that is a terminal expression, but add and subtract the sign from the previous example did non-terminal and so is Roman numeral. Let's non-terminals. Well, Roman numeral, It's interpret method. We'll go through its own interpretation process, where it converts the string version of Roman numeral into a number because the number is the terminal expression and every branch number, number, number, number, number, okay, So roman numeral one will extend the Roman numeral class boy, including these extra attributes, 1459 and a multiplier, Roman numeral 10, one hundred, one hundred, ten hundred will extend roman numeral one by using different values for the 1, 4, 5, 9, and multiple, et cetera. We'll see that in the code. So interpreted client, why interpreter, client.print. In order to create the ice take dynamically, I've written a parser called sentence parser, and that's the fall down there. And this will split the sentence into a list separated by spaces, then traverse the list, rating and deciding whether the left and the right expressions are terminal or non terminal expressions and building it dynamically. Now, it's quite a lot to understand. And for every sentence that you need to translate, depending on the grammar of that sentence, your pastures are going to be different. So this parser is written specifically for sentences of the form number or Roman numeral operator number or Roman numeral operator number or Roman numeral, etc. And at the end, once the IST has been created, I'm popping just the final one that was added, which is going to be my IST root. So looking at client again, that's the first sentence. And then later on you can test different kinds of sentences of different variation, different number of expressions, and even completely more complicated, just roman numeral expressions. Okay, So it's structurally very similar to the conceptual example, except the Roman numeral expression is significantly more complicated to assemble. So abstract expression, just interpret method. Everything must implement that there's add is subtract and Roman numeral. When you initialize it, you pass in the string version of the Roman numeral could be IV or the oil I end. This is the context that will be shared and the Roman numerals are in sequence of interprets. So self.contents is passed down all through its own interprets. And then finally, it returns a number which is a terminal expression of whatever self.contents one dot interpret equals. So self-talk context is a list consisting of the very first value being a string of Roman numeral and an integer that will slowly be incremented as it is interpreted internally in a science separate method. Okay, so we start off with roman numeral one hundred ten hundred down here, roman numeral 100 extends Roman numeral 1. So it's only just changing some of the static attributes and look at Roman numeral 100 got different static attributes. Whereas the multiplied down here Monday, because of the multiplier in revenue, or 100 equals 100, and that's the tens and the Roman numeral ones. And then there is a interpret method which raised the contexts from the args tuple. Now these selection of code here is quite hard to read. These sections here, our string slicing. Now I'll talk about that next video. So there's another one there, another one there, another one there. Okay, so it's a complicated little function I'll let you look at in your own time, but the output converting a combination of Roman numerals into a number. So let's look at that run. Python interpreter, line dot p-y. Okay, So the sentence 5 plus 4 minus 3 plus 7, minus 2 equals 11. So that's the list. Everything's split up by spaces, and this is the representation. So five add IV, which equals 4, subtract 3, add seven, subtract two. We can look at something a little different, just so you can see that it does work dynamically and we go same thing, 11, but this time the five is a Roman numeral. So as the three and the two are different length sentence and go a 114, say pi x, that's a 109 plus five, something a little more complicated, a 116. And then finally, one with just roman numerals, quite large ones. And I go, I mean, that's quite hard to read, but that's the answer there. Leet. Excellent. Now the summary, ice teas are hard to create and are an enormous subject in themselves. My recommended approach is to create them manually first using a sample sentence to help you understand all the steps individually and then progress to conversion to be fully dynamic one step at a time, just ensuring that the grammatical constructs still work as you continue to progress. So just one step at a time. Now the interpreter patent uses a class to represent a grammatical rule which is important. Okay, So I'm saying my terminal expressions, grammatical rules. So AD is a grammatical rule, Roman numeral and subtract or grammatical rules, and there's a class for each one. Now, i stays consists of multiple nonterminal and tunnel expressions at all implement the interpret method. Okay, so note in the sample code above the interpret methods in the non-terminal expressions all call further interpret methods recursively only the terminal expressions interpret method returns an explicit value. So that's the number class. So you interpret just return self dot value. Excellent. So the next video to buy new cutting concepts, the string slicing that I introduced in side, the interpreter use case down there. For example, Excellent. 58. String Slicing: New coding concepts, string slicing. Sometimes you want part of a string in the example code above what I'm interpreting the Roman numerals, I'm comparing the first one or two characters and the context with IV or CAM or many other Roman numeral combinations. If the match is true, then I continue with further commands. So here's some examples, context and looking at the first item in context, I'm then splitting a string looking for the first two characters. So if it equals class non IX, then I continue. Okay, so the format is string start, end, step k. So he's an example string test that Roman numeral, I can show just the first three characters. So test 0, so that's the start, three is the end. So the first three characters, 07, there we go. I can even start at number 3, 37. So I can even show the last number of characters. So if I say minus 4 colon, that will show the last four characters. To the end, we go Xc, Xc. That last argument for step. So I can say Show me between 08 steps to him, MMC, so M, M, M, c. Now if I leave out that loss character, you will use the whole string MMC x, so M, M, M, c x down there, which means I can also leave out the first character 0 is the default. Very good. So that also means dispersed example here, which produces MMM. If I was to leave that 0 off, that was still produce MMM. So the default is 0, whatever the last character is, one. So if I leave off and that it's the whole string, okay? So another thing you can do is reverse the string. So test colon, colon minus one. So that's step minus one and n, and the string has been reversed. So MMM, as he can sit, that's the correct way and that's the reversed way. And if you were to do just colon minus one colon, that will show all the characters except for the last character. So we go, so see the x is being chopped off. Yeah, that was working on a string. You can also do this same technique on lists and tuples. So let's test a list, okay, Test now equals a list of numbers. Okay, let's get test 003, 1, 2, 3, test for that any columns. This is just going to show the one item at minus four, which will be six. I can show the items between 25345292, That's step 2, 3, 5, 7, 9. Let's reverse the list colon, colon minus one, that is step minus1, using defaults to 0 and the list length. And let's get the whole list except for the last one and go 12345678 p.sits. So it also works with tuples. He falls to convert that to a tuple of tuples. Excellent, that was about string slicing. The next section, we'll look at the iterator. Excellent. 59. Python __repr__ Dunder Method: Hey, New Cutting Concepts that dunder repre, method, that means representations. So it's very similar to the string dunder method. You can overwrought it to produce a string representation of a class, okay, so a little bit of code, copy that. I'm putting it into test.py. I can run that test.py. It says I am repro, so it's just printing that out. I'm using exactly the same as ours using string in one of the previous videos. We are just now report gives you another option. For example, if you already were using string or the SDR done the message, then the STR dunder method would override the wrapper method. So let's do that. So this is ROMs string down there, so it's using that. So this is an alternative way of printing out the class information. So normally you use string for human-readable messages. But if you need something more complicated like some debugging information or you want to use some other information programmatically, then use the read method, but by default, you should use the string dunder method to print out custom strings. Now in the interpreter, in add, subtract and we're always using repro. That was unnecessary for me to do that. I could have just used string, but I just wanted to show you that the repre, option is there. So if there is a situation where you are using string and repro in the same class to get the specific output, we can use a dot repre or repro your object like so. I am repro IOM report by just printing the object by itself or the incidence by itself is going to use the string dunder instead. Okay, so excellent. 60. Iterator Pattern: The iterator design pattern. Now note before we start this that Python has an inbuilt iter function. Already. We can make something iterable, but I'm showing you how to do this manually if you ever need to do it manually. So the Iterator, we'll commonly contained two methods that perform the following concepts and its next and has next, okay, next returns the next object in the aggregate, which is a collection of objects. Hasnext returns a Boolean indicating if the iterable is at the end of the iteration or not, there are benefits to using the iterator. Either declined, can traverse a collection of aggregates. So objects without needing to understand the internal representations, end or data structures. So you can iterate anything. So you could create cars and iterate cars for example, okay, terminology. So the iterator interface has next and next and there's the concrete Iterator aggregate interface. And the aggregate could be anything, any object that may or may not have an interface. So source code in the concept, I'll quote for objects called aggregate, that's just a name amusing, and group them into a collection. Very minimal objects implement one method that prints a line. I then create an iterable and parsing the collection of aggregates. I can now traversed the aggregates through the iterable interface, iterator, iterator concept of PY and Visual Studio Code iterator, iterator concept PY. The iterator interface has next and next. This is the iterable concrete class. When you initialize it, you pass in the aggregates and set the index to be 0. Now, when we call next, if the index is less than the length of the self aggregates or create an aggregate to return equals self aggregates, self index, which is currently 0. We then increment the index by one and return the aggregate. If the index was equal to the self aggregates length are then raise an exception at end of iterator exception day hasNext returns a Boolean if the self index is less than the length of self aggregates. Here is my concrete aggregate as one method which prints and that sits interface very minimal. The client aggregates equals a list of aggregate as four. Okay, so note that this is a Python list and a pause and list is already iterable by default. But I'm showing you how to create your own manually anyway, using the iterable class just up here. Okay, so we can run that Python iterator, iterator concept and it's printing out the method and it's running the method for each iterable, iterable dot next. So wall interval has a next while true, then iterable dot next.me. So remember next returns one of the aggregates at the index. Next video, I'll create an example use case of the iterator where it was necessary for me to create my own iterate on Excellent. 61. Iterator Use Case: Okay, ESA radar example use case. One reason for not using the inbuilt Python data structures that implement iterators already or using the iter function directly operating system collection. We'll talk about IT in the next video, is in the case when you want to create an object that can dynamically create iterated objects, you want a custom order of objects or an infinite iterator. The iterator in this brief example will return the next number in the iterator multiplied by 2 modulus 11. So this is like a custom order of integers. It dynamically creates the returned object at runtime. It has no hasNext method since the result is modulated by 11. We'll look at the results no matter how large the iterator indexes. So it's using modulus. So it will also appear to alternate between a series of even numbers and odd numbers. So it's going to be a strange iterator. Okay, Also note that just to demonstrate that implementing abstract classes and interfaces is not always necessary, I've kept this example nice and brief. So there are no abstract classes or interfaces in it. The UML, it's a number wheel, it has just an x method, and that's the pseudocode, self index times 2 model-driven app source code iterate a client p-y, it's only a very small amount of code. It fits in the screen completely. Okay, this is the concrete aggregate number wheel. The next function increments index by one and returns self index times 2 mod 11 number. We'll create a new instance of the number we'll iterate on. And then for I in range 22, okay, So that means I'm going to run this 22 times the number we'll dot next, which returns a number. And then one thing you can also do with a print statement is instead of printing a new line at the end, you can overwrite what the end character is going to be. Here I'm putting a comma and a space, so it's going to print all the numbers in line. Okay, so let's run that Python iterator client. We go 2, 4, 6, 8, 10. Then modulus living kicks in, 13579, modulus living kicks in again, 0, 2, 4, 6, 8, 10, 12, 35. Okay, so it's just on this 22 times, then it's printing comma space instead of a new line after every time I call print. So that number wheel is an iterator. So I could create multiple number wheels. Number wheel, I num will be, and wherever they were in the iteration would be independent of each other. That's the first one and that's the second one started again, 2, 4, 6, 8. Excellent case. So summary, okay, there are many ways to create a routers. They are already built into Python and used instead of creating custom classes, if you need, use an iterator when you need to traverse I recollection. Or you want an object that can output a series or dynamically credit objects at minimum, and iterated needs a next equivalent method that returns an object optionally, you can also create a helper function that indicates whether a kneaded eraser is at the end or not. That was hasNext. And this is useful if you use the iterator in a while loop. Alternatively, if you are using the item method we shall discuss in the next video, then you can use a sentinel option to indicate if you are at the end of the iterator or not. Excellent. 62. Python iter() Function: Okay, new coding concepts. The parson item function on lists, dictionaries, sets and tuples are already iterable. So if you want basic iteration for use in a for loop, then you only need to add your objects onto one of those and it can be used rot away. So I'll just demo this, copy that and in test.py in my project, paste that and run it. Test.py. It just prints out 1, 2, 3 like that for name in names sorted, iterable. So you can instantiate an iterable on the list dictionary tuple offset. But if you would like to have an iterator objects where you can run the next method on it, then your option is to use the item function. So names here is a list. Now it's been wrapped in the iter function. So I'll just demo that. Sean Cosmo, ME. So next, next, next. Or you could say names dot underscore, underscore ITER, ITER and dunder method, which you get with lists, sets and dictionaries and tuples and also strings. So let's just print that. And I go Sean, Cosmo, ME Next, Next, Next. Now, if you try to print next again at the last one, I'll put that back to our so it raises a stop iteration error. So that's a, you know, you're at the end. So we get to the end of the iterator and you try to do next again, you get the stop iteration error. So in order to stop the stop iteration error, you can use the Sentinel parameter. Okay, so the usage iter object Sentinel. Now, when using a sentinel perimeter, the object that you pass in as the first argument than the item method will need to be callable. So for that copy this section of code, okay, so I've just copied to my clipboard, isn't that icon and we'll place that. I don't need that last comment. Now, there's a class called doubler is just has a static attribute called count equals one and a class method next, CLS count times equals to return class count. So it's just doubling 1248 each time we call it. Now, here I said the method needs to be callable. That's this double underscore call gear. That's saying that this double a class as a default call method, which is next, and that's the next day and that is needed for the iter function down here, the sense nor perimeter. Anyway, I'll talk a lot more about the core method in one of the next sections when I talk about the state down here. But for now we can just look at this and just understand that that double method is callable and the default method is next. So that means I can use wi with a sentinel saying 32 is the last value that the iterator can return. So here I'm going to create a list from the iterator and then prints it. So Python test.py. So when the list was created, it used the iterator, which is an orator stopping at 32. So 32 braces the stop iteration and then I just print out the list here, 2, 4, 8, 16. Okay, so that's the eater function down there. And that's how you'd use the Sentinel data point. And the next section, we start looking at the mediator. Excellent. 63. Mediator Pattern: The media design patent objects communicate through the media EDA rather than directly with a jaw. As a system evolves and becomes larger and suppose more complex functionality and business rules. That problem of communicating between these components becomes more complicated to understand and manage. It might be beneficial to refactor your system decentralized some or all of its functionality by some kind of mediation process, the mediator pattern is similar to implementing the facade pattern between your objects and processes, except that the structure of the media ADA allows multi-directional communication between the objects and processes. So while the facade is a structural pattern, and the mediator also employs structure in the Y that exists between two or more other objects or processes. It also allows changing the behavior of the interaction to make a more cooperative in some way. Example, the centralization of application logic, managing the routing behavior, caching, logging, etc. Okay, So terminology, media ADA, the coordinator of communications between the components which are called colleagues and the colleagues, one of the many types of concrete components that use a media item. So before colleague Juan and colleague to two different processes or instances talking to each other directly. Method 1, method 2, after the mediator, something in the middle that now implements both of the methods are calling to now close colleague one by media and vice versa. So it's like a two-way facade from the structural perspective. But this provides the ability to add extra functionality without modifying colleague one or colleague to, okay, so source code in exemple concept there are two colleague classes or use each other's methods. And instead of the colleagues cooling until its methods directly, they implement the media interface and call each other by the mediator. The system in this case, would work without the mediator, because the mediator in this example doesn't actually add any extra functionality. The potential is there and the future. For example, you could add II analysis or monitoring without needing to add specific support or knowledge into either of the colleagues gate. So in the example, the mediator is structurally acting as a multi-directional relay between the two colleagues. Mediator, magnetic concept, PY. Okay, I'm open Visual Studio Code is colleague one as method one and colleague T2 has Method 2. This is the mediator is composed of colleague 1 and colleague to improvise two methods. Colleague one method which is colleague to will call and colleague to method which calling one we'll call k. So decline mediator, a mediator, data colleague one wants data from colleagues who so data mediator colleague to method, et cetera. Let's run that path and made the ITA mediator concept. They've got a colleague one. Here is the colleague to specific data that you asked for talking to us. They call it one specific data that you asked for. So in these example of simulated the colleague 12 are in the same client, but total, imagine that colleague 1 and colleague to a different processes or different applications that need each other's information, but they would now go via a mediator to get that. So next video we'll look at the example use case of the mediator pattern, where we'll implement some behavior into the mediation process. Excellent. 64. Mediator Use Case: Okay, so now the mediator use case example. In this example, we'll implement some behavior into the mediation process cases before the mediation logic is added, consider that below is a series of components or subscribe to a central location being a subject. And they all implement the observer pattern. So three components of all subscribe to the subject, which I'm calling the mediator. It's very similar to the observer pattern, but what will happen is each component can notify the mediator, and the mediator will notify each one back through there, receive a message there. Okay, So each component is updated independently by external forces, but when it has new information, it notifies the subject, then notifies the other subscribed components. So if component too had an update until some media in the media then tells the other two. Now during the synchronization of the subscribe components without the extra mediation, the component that provided the new information would receive back the same message that it just not afford the subject of. So for example, compiler one says media articles and information. Here it is, the mediator, through its notify process would notify 123 back. Adding the mediation logic means we can exclude component one from receiving the same information back and just send it 23 instead. Okay, so There's some pseudocode describing that if component is not equal to the originator, then we'll send it back through there receive methods, okay, So mediator client PY in Visual Studio Code, mediator, client PY, There's a mediator, three components. I'm subscribing those components to the mediator component. One notifies that it's got some data called data a and component to notifies the media that has got some data BY and components react cetera, ask awesome data called data c. So let's look at that mediatic client. Okay, So component one, out data, a component to component, in, a component to out data be components three, component 13, see 21 in case. So let's look at the component. The component has a reference to the mediator when you create a self.name data, notify of the message. So some external event happens to the component decides it wants to notify the mediator of this new message. So that's what I'm going there. And when the media to receive that down here, mediator for component in self components. So that's every component that is subscribed that has added itself. If the component is not equal to the originator, then component received message. So, so it's very similar to the observer, but it's mediated in some way. So if I talked to mediation away, that is that line there, it's just going to notify every single component in any way through there receive method. And there we go. So Out component one, out dot i 2, 3 one will got inbound data back to component one. So it's assignment animation. So same thing component to our database components. So we got in database, so it's a wasted message. Same with components three, components, three. So, so little bit of mediation, they are on the return to message. And then do that again. And it's all good out, in, out, in. So it's one way of keeping components synchronized with each other is used the media dependent, okay, So summary. So I use a mediator to replace a structure with many-to-many interactions between his classes and processes with a one-to-many centralized structure where the interface supports all the methods of the many-to-many structure of either mediatic component instead, an example of where the mediatic could be introduced is here in the facade use case example in this diagram here, the game API, it was the facade for all these other components. But if you look at some of these components such as warts, is communicating directly with reports and uses, and communicating with wallets. There's a lot of many-to-many interaction going on here. In a real system. There's a lot more going on, but this is an example. So you can put a mediator in the middle there and make some of those messages go boy, or a mediator, if you thought that the mediator would be beneficial. Okay, so back to the mediator. A mediator pattern encourages usage of shared objects that can now be essentially managed unsynchronized. The mediator, patent crates and abstraction between two or more components that then makes a system easy to understand and manage. The mediator pattern is similar to the facade, except the mediator is expected to translate both ways. It's multi-directional between two or more other objects or processes I would normally interact directly with each other. Excellent. In the next section, we'll start looking at the momentum. Excellent. 65. Memento Pattern: Now for the Momento pattern throughout the life-cycle of an application and object state might change. You might want to store a copy of the current state in case of later retrieval example, when writing a document, you may want to auto save the current state every 10 minutes, or you have a game and you want to save the current position that you apply on a level with its score and current inventory, you can use the Momento pattern for saving a copy of state and for later retrieval if necessary. Now the mental pattern, the command pattern, is also commonly used for implementing undo redo functionality within your application. The difference between the command and the mental patterns, or undo redo, is that in the command pattern, you re-execute commands in the same order that changed attributes of a state. And with the mentor, you completely replace the state by retrieving from a cache store. Terminology, originator is an object in your application that has internal state, and this is the state. Do you want to take copies off and it changes. And it changes right now the caretaker, a class that asks the originated a crate or restore mementos, the care taken and saves them into cash or store of mementos. Okay, So that store can be a memory or persistent or something else. Momento is a copy of the internal state of the original data that can be later we stored back into the originator to replace this current state, we'd like an undo or redo the UML clone application originator. This is your object to be anything that has state and you want to save that state. It hasn't. Momento, which is a getter and setter, which is a new concept that I'll talk about in one of the next videos. The caretaker will take mementos of the originator and save them or take previous versions and replace them. So the caretaker is managing the state of originator and mismanage and saving and retrieval. Ok, source code. In the concept code, the client creates an object whose state will be periodically, we call it, the object will be the originator. Okay, Tycho was also credit with a reference to the originator division that is internal state is changed several times, is then decided that the caretakers should make a backup. More changes are made to the reach data, and then it is decided that the first backup should be restored instead, and then the second backup is restored. So, so momenta, momenta concept P1, Okay, I'm in Visual Studio Code Momento, Momento concepts PY, there is a memento class as a container of the state. It's very minimal. There's an originator. This is my object in my application whose state changes. I have a local copy of the state and I've credited property for the state. Now this is a getter and setter property. This is a new Python concepts that I'll talk about in one of the next videos down here of credit for a momentum which creates the momentum of the state. And this is also a getter and setter. Now getters and setters are more controlled way of accessing an internal attribute. We'll discuss the dataset as in one of the next videos. Okay, kids ICA, it provides a narrow interface, which is a simplified interface to the mementos. And this is how the application accesses the mementos. So it has a reference to the originator and is referenced to mementos. I'm storing the mementos in a list so you can store them in memory or on disk or in a database, or on an external API service, create, create some momentum. It's getting the Momento from the originator and that's using the Momento get our incidence just here. It's using the getter self mementos append Momento, goes into the list, restore, replace originated current state with the state stored in the safe memento Sacramento equals, let's get the one at index self originate up Momento equals this momentum. So the setter Momento sitter self.age equals Momento dot state, dot state. Okay? All right, Now the client quite an originator. That's my application object whose state changes. I credit caretaker, which creates a reference to the originator reached o