├── .DS_Store ├── .gitignore ├── Libraries └── argparse │ ├── argparse_example.py │ ├── argparse_example_2.py │ └── argparse_example_subparser.py ├── PROJECT-IDEAS.md ├── Projects ├── .DS_Store ├── Dictionary App │ ├── README.md │ ├── console_app.py │ ├── data.json │ └── tkinter_app.py ├── Flask App │ ├── app.py │ ├── main.py │ ├── static │ │ └── css │ │ │ └── style.css │ └── templates │ │ ├── index.html │ │ └── result.html ├── Library Management System │ ├── backend.py │ ├── books.db │ └── frontend.py ├── Python OOP Basics │ ├── Readme.md │ └── oop.ipynb ├── Snake Game │ ├── snake_game.exe │ └── snake_game.py ├── Telegram Bots │ ├── Grading.pdf │ ├── README.md │ ├── config.py │ ├── elizaa.py │ ├── guessa.py │ ├── repeater.py │ ├── repeatera.py │ └── send_doc.py ├── Tkinter Projects │ ├── README.md │ ├── Tkinter.txt │ ├── address_book.db │ ├── customers.csv │ └── examples │ │ ├── buttons.py │ │ ├── calculator_app.py │ │ ├── close_exe.py │ │ ├── converter.py │ │ ├── crm.py │ │ ├── database-1.py │ │ ├── dropdown-2.py │ │ ├── dropdown.py │ │ ├── entry-height.py │ │ ├── entry.py │ │ ├── file-1.py │ │ ├── file-2.py │ │ ├── file-3_with_audio_reader.py │ │ ├── file.py │ │ ├── frames.py │ │ ├── grid.py │ │ ├── howto.py │ │ ├── image_viewer_app.py │ │ ├── images.py │ │ ├── is_num.py │ │ ├── list_box.py │ │ ├── loading_page.py │ │ ├── menu_bar.py │ │ ├── menu_bar_frame.py │ │ ├── menu_bar_oop.py │ │ ├── menu_bar_oop_frame-1.py │ │ ├── menu_bar_oop_frame-2.py │ │ ├── message_boxes.py │ │ ├── my_calendar.py │ │ ├── new_window.py │ │ ├── photos │ │ ├── icon.ico │ │ ├── image.jpg │ │ ├── imge.png │ │ ├── python-file-1.png │ │ ├── python-file.png │ │ └── python.png │ │ ├── progress_bar.py │ │ ├── radio.py │ │ ├── scrollbar.py │ │ ├── sliders.py │ │ └── ttktheme.py ├── Web Scraping │ ├── coreyms_com.py │ └── webscraping.ipynb └── Website Blocker │ ├── hosts │ └── website-blocker.py ├── README.md ├── design_patterns ├── README.md ├── b_chain_of_responsibility │ ├── chain_of_responsibility.py │ └── chaining_method.py ├── b_iterator │ ├── generator.py │ ├── generator2.py │ ├── iterator.py │ └── iterator2.py ├── b_mediator │ └── mediator.py ├── b_observer │ └── observer.py ├── b_publish_subscribe │ └── publish_subscribe.py ├── b_strategy │ ├── strategy.py │ └── strategy2.py ├── b_template │ └── template.py ├── b_visitor │ └── visitor.py ├── c_builder │ ├── builder.py │ ├── with_builder_geeks_for_geeks.py │ └── without_builder_geeks_for_geeks.py ├── c_factory │ ├── abstact_factory.py │ └── factory.py ├── c_pool │ └── pool.py ├── c_prototype │ ├── deep_copy_vs_shallow_copy.py │ └── prototype.py ├── c_singleton │ ├── borg.py │ ├── borg_one_variable.py │ ├── singleton.py │ └── singleton_with_exception.py ├── delegation_pattern │ └── delegator_pattern.py ├── s_adapter │ ├── adapter.py │ └── adapter2.py ├── s_bridge │ └── bridge.py ├── s_composite │ └── composite.py ├── s_decorator │ ├── decorator.py │ ├── decorator_as_class.py │ └── decorator_with_args.py ├── s_facade │ └── facade.py ├── s_flyweight │ └── flyweight.py └── s_proxy │ └── proxy.py └── solid ├── 1_single_responsibility_principle.py ├── 2_open_closed_principle.py ├── 3_liskov_substitution_principle.py ├── 4_interface_segregation_principle.py ├── 5_dependency_inversion_principle.py ├── BAD_liskov_substitution_principle.py ├── BAD_open_closed_principle.py └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rustam-Z/python-programming/e38a2305df555768a5ab0fa5383f77b73544c4bd/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | venv/* 2 | .* 3 | __pychache__* 4 | *.pyc -------------------------------------------------------------------------------- /Libraries/argparse/argparse_example.py: -------------------------------------------------------------------------------- 1 | """ 2 | How to run: python argparse_example.py --name Rustam --age 20 100 200 --values 1 2 3 3 | 4 | 1. --name is a required arg (flag) 5 | 2. x, y are positional arguments 6 | 3. --age is an optional argument 7 | 4. Multiple Input Arguments 8 | 5. Mutually Exclusive Arguments, depending on one argument, you want to restrict the use of another. 9 | 6. Subparser 10 | 11 | https://towardsdatascience.com/a-simple-guide-to-command-line-arguments-with-argparse-6824c30ab1c3 12 | """ 13 | 14 | import argparse 15 | 16 | # Create the parser 17 | parser = argparse.ArgumentParser() 18 | 19 | # Add an argument 20 | parser.add_argument('--name', type=str, required=True) 21 | parser.add_argument('--age', type=int) 22 | parser.add_argument('x', type=int, help='The first value to multiply') 23 | parser.add_argument('y', type=int, help='The second value to multiply') 24 | parser.add_argument('--values', type=int, nargs=3) # Multiple Input Arguments, nargs='+ 25 | 26 | # Parse the argument 27 | args = parser.parse_args() 28 | 29 | sum_ = sum(args.values) 30 | 31 | # Print "Hello" + the user input argument 32 | print('Checking...', args.name) 33 | 34 | if args.age: 35 | print(args.name, 'is', args.age, 'years old.') 36 | else: 37 | print('Hello,', args.name + '!') 38 | 39 | print('Multiplication:', args.x * args.y) 40 | print('Sum:', sum_) 41 | -------------------------------------------------------------------------------- /Libraries/argparse/argparse_example_2.py: -------------------------------------------------------------------------------- 1 | """ 2 | Mutually exclusive group example. 3 | """ 4 | import argparse 5 | 6 | parser = argparse.ArgumentParser() 7 | group = parser.add_mutually_exclusive_group() 8 | 9 | group.add_argument('--add', action='store_true') 10 | group.add_argument('--subtract', action='store_true') 11 | parser.add_argument('x', type=int) 12 | parser.add_argument('y', type=int) 13 | 14 | args = parser.parse_args() 15 | 16 | if args.add: 17 | sum = args.x + args.y 18 | print('Sum:', sum) 19 | elif args.subtract: 20 | difference = args.x - args.y 21 | print('Difference:', difference) 22 | -------------------------------------------------------------------------------- /Libraries/argparse/argparse_example_subparser.py: -------------------------------------------------------------------------------- 1 | """ 2 | python user.py login --username D0loresh4ze --password whoismrrobot 3 | python user.py register --firstname Dolores --lastname Haze --username Doloresh4ze --email dhaze@ecorp.com --password whoismrrobot 4 | """ 5 | 6 | import argparse 7 | 8 | parser = argparse.ArgumentParser() 9 | subparser = parser.add_subparsers(dest='command') 10 | 11 | login = subparser.add_parser('login') 12 | register = subparser.add_parser('register') 13 | 14 | login.add_argument('--username', type=str, required=True) 15 | login.add_argument('--password', type=str, required=True) 16 | 17 | register.add_argument('--firstname', type=str, required=True) 18 | register.add_argument('--lastname', type=str, required=True) 19 | register.add_argument('--username', type=str, required=True) 20 | register.add_argument('--email', type=str, required=True) 21 | register.add_argument('--password', type=str, required=True) 22 | 23 | args = parser.parse_args() 24 | 25 | if args.command == 'login': 26 | print('Logging in with username:', args.username, 27 | 'and password:', args.password) 28 | elif args.command == 'register': 29 | print('Creating username', args.username, 30 | 'for new member', args.firstname, args.lastname, 31 | 'with email:', args.email, 32 | 'and password:', args.password) 33 | -------------------------------------------------------------------------------- /PROJECT-IDEAS.md: -------------------------------------------------------------------------------- 1 | ## Projects Ideas 2 | 1. Banking system with all banking facilities like – deposit, withdrawal, foreign exchange to any currency, availability of loans for purchasing vehicles, apartments, houses, setting up business, education loan, management of ATMs and all other features. 3 | 2. Airline flight reservation system (online booking of tickets in different flights for different destinations all over the world, cancellation of tickets, clear display of cancellation amount, refund of amount after cancellation, showing availability of all flights, showing flights timings for all 7 days of a week, seats availability, seat selection for travelers by giving the complete layout of the seating arrangement inside the flights, food availability/non-availability inside the flights, change of travel dates and amount charged.) 4 | 3. Taxi/cab sharing 5 | 4. University education portal (providing all information about under-graduate, post graduate and doctoral programs offered, facilities available, location & map, fee structure in all the universities) 6 | 5. Online exam management system (with total security of identifying the students during exam, monitoring the students’ activities during the exam, selection of different questions for each student, development of a large question bank containing hundreds of questions in each subject considering all courses taught at the university) 7 | 6. Library management system 8 | 7. E-content management system 9 | 8. Plagiarism checker & file management system 10 | 9. Hotel reservation & management portal 11 | 10. Restaurant management 12 | 11. Healthcare consulting system (doctors with different specializations for consultation, hospitals with all facilities for treating different diseases & abroad - one stop portal for all consultations and treatments) 13 | 12. Electronic health record management system with builtin security 14 | 13. Pharmacy - medical store management 15 | 14. Blood bank system 16 | 15. Online shopping and delivery system (like amazon) 17 | 16. Online car shopping 18 | 17. Tourism portal 19 | 18. World tourism portal 20 | 19. Higher education abroad portal 21 | 20. Job search/recruitment portal 22 | 21. Company resource management system 23 | 22. Attendance monitoring system with fingerprints verification 24 | 23. Face recognition - based attendance checking system 25 | 24. Aircraft communication and monitoring system 26 | 25. Ticket booking management system for concert ceremonies 27 | 26. All store stock management (inventory control) 28 | 27. Multiplayer gaming applications 29 | 28. City traffic monitoring and control system 30 | 29. Police traffic violation reporting & control system 31 | 30. The marriage function hall booking & food/music arrangement system 32 | 31. Any vehicle (car, bus, heavy vehicles for parties, functions, family picnics, long distance travel) booking portal 33 | 32. Teacher assisted program writing environment for students 34 | 33. Doctors reservation system for patients 35 | 34. Bus reservation & tracking system 36 | 35. Railway booking and train tracking system 37 | 36. Warehouse management system 38 | 37. Courier tracking, cargo and freight transportation 39 | 38. Online code testing system 40 | 39. Online quiz system (with total security of identifying the students during the quiz, monitoring the students’ activities during the quiz, selection of different quiz questions for each student, development of a large quiz question bank containing hundreds of quiz questions in each subject considering all courses taught at the university) 41 | 40. Land/house/apartment rental & purchase portal 42 | 41. Housecleaning, plumbing, electricity service & maintenance system 43 | 42. Human organ transplantation management system 44 | 43. Covid-19 tracking, testing, treatment & hospital management system 45 | 44. Cryptocurrency trading portal (exchange) allowing trading of all crypto coins using security, confidentiality and authentication 46 | 45. Parking management system 47 | 46. Online food delivery system (linked to all restaurants in different districts in different regions in some country) 48 | -------------------------------------------------------------------------------- /Projects/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rustam-Z/python-programming/e38a2305df555768a5ab0fa5383f77b73544c4bd/Projects/.DS_Store -------------------------------------------------------------------------------- /Projects/Dictionary App/README.md: -------------------------------------------------------------------------------- 1 | ## Dictionary application using Python 2 | 3 | This is your first project in Python. I suggest you to build different version of this project. For example: 4 | - Console application, you may also use `argparse` library. 5 | - Desktop application using `Tkinter`. 6 | - Web application using `Django`, `Flask` frameworks. 7 | - Telegram bot using `telepot`, `aiogram`. 8 | -------------------------------------------------------------------------------- /Projects/Dictionary App/console_app.py: -------------------------------------------------------------------------------- 1 | import json 2 | from difflib import get_close_matches 3 | 4 | data = json.load(open("data.json")) 5 | 6 | 7 | def translate(w): 8 | w = w.lower() 9 | 10 | if w in data: 11 | return data[w] 12 | elif w.title() in data: 13 | return data[w.title()] 14 | elif w.upper() in data: 15 | # In case user enters words like: USA or NATO 16 | return data[w.upper()] 17 | elif len(get_close_matches(w, data.keys())) > 0: 18 | yn = input("Did you mean '%s' instead? Enter Y if yes, or N if no: " 19 | % get_close_matches(w, data.keys())[0]) 20 | if yn == "Y" or yn == "y": 21 | return data[get_close_matches(w, data.keys())[0]] 22 | elif yn == "N" or yn == "n": 23 | return "The word doesn't exist. " \ 24 | "Please double check it." 25 | else: 26 | return "We didn't understand your entry." 27 | else: 28 | return "The word doesn't exist. " \ 29 | "Please double check it." 30 | 31 | 32 | def main(): 33 | word = input("Enter word: ") 34 | output = translate(word) 35 | 36 | if type(output) == list: 37 | for item in output: 38 | print(item) 39 | else: 40 | print(output) 41 | 42 | 43 | if __name__ == "__main__": 44 | main() 45 | -------------------------------------------------------------------------------- /Projects/Dictionary App/tkinter_app.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | from tkinter import messagebox, IntVar, END, TOP, RIGHT, NW, Y, SINGLE 3 | from tkinter import ttk # Normal Tkinter.* widgets are not themed! 4 | from ttkthemes import ThemedStyle 5 | 6 | import json 7 | import webbrowser 8 | from difflib import get_close_matches 9 | 10 | # Open the json file with db 11 | data = json.load(open("data.json")) 12 | 13 | # Bookmarks 14 | BOOKMARKS = [] 15 | HISTORY = [] 16 | 17 | 18 | class MenuBar(tk.Menu): 19 | def __init__(self, master): 20 | tk.Menu.__init__(self, master) 21 | 22 | self.frame = ttk.Frame(master) 23 | self.frame.pack() 24 | 25 | self.master = master 26 | 27 | # Create a Menu Item for Searching 28 | search_menu = tk.Menu(self, tearoff=False) 29 | 30 | # Create a Menu Item for Info --EightSoft dev 31 | info_menu = tk.Menu(self, tearoff=False) 32 | 33 | # Add the cascades for menu bar 34 | self.add_cascade(label="Dictionary", menu=search_menu) 35 | self.add_cascade(label="Help", menu=info_menu) 36 | 37 | # Searching 38 | search_menu.add_command(label="Search", command=self.dict_search) 39 | search_menu.add_command(label="Bookmarks", command=self.bookmarks) 40 | 41 | # Help 42 | info_menu.add_command(label="About", command=self.info_about) 43 | 44 | # Create frames for each new window --MenuBar-Cascade-Commands 45 | self.dict_search_frame = ttk.Frame(master) 46 | self.bookmarks_frame = ttk.Frame(master) 47 | self.info_about_frame = ttk.Frame(master) 48 | 49 | # Hide the frames when you switch the menu 50 | def hide_all_frames(self): 51 | """Cleans the screen after pressing the menu item""" 52 | for widget in self.dict_search_frame.winfo_children(): 53 | widget.destroy() 54 | 55 | for widget in self.bookmarks_frame.winfo_children(): 56 | widget.destroy() 57 | 58 | for widget in self.info_about_frame.winfo_children(): 59 | widget.destroy() 60 | 61 | self.dict_search_frame.pack_forget() 62 | self.bookmarks_frame.pack_forget() 63 | self.info_about_frame.pack_forget() 64 | 65 | # Create methods for Teachers 66 | def dict_search(self): 67 | self.hide_all_frames() 68 | self.dict_search_frame.pack(fill="both", expand=1) 69 | 70 | # Creating a Notebook 71 | notebook = ttk.Notebook(self.dict_search_frame) 72 | notebook.pack(pady=10, padx=10) 73 | 74 | # Initialize frame for notebooks 75 | self.frame1 = ttk.Frame(notebook) 76 | self.frame2 = ttk.Frame(notebook) 77 | 78 | # Place the frame on the screen 79 | self.frame1.pack(fill="both", expand=1) 80 | self.frame2.pack(fill="both", expand=1) 81 | 82 | # Add the notebooks 83 | notebook.add(self.frame1, text="Search") 84 | notebook.add(self.frame2, text="History") 85 | 86 | # ===================== Frame 1 =================== 87 | l1 = ttk.Label(self.frame1, text="Enter word") 88 | l1.grid(row=0, column=0, padx=10, pady=10) 89 | 90 | self.e1 = ttk.Entry(self.frame1) 91 | self.e1.grid(row=0, column=1, padx=10, pady=10) 92 | 93 | self.l2 = ttk.Label(self.frame1, text="", wraplength=250) 94 | self.l2.grid(row=2, column=0, columnspan=2, padx=10, pady=10) 95 | 96 | b1 = ttk.Button(self.frame1, text="Search", command=self.translate, width=30) 97 | b1.grid(row=1, column=0, columnspan=2) 98 | 99 | # ===================== Frame 2 =================== 100 | # Add a scrollbar 101 | scrollbar = ttk.Scrollbar(self.frame2) 102 | scrollbar.pack(side=RIGHT, fill=Y) 103 | 104 | self.list_box = tk.Listbox(self.frame2, yscrollcommand=scrollbar.set, width=50, height=50, borderwidth=0, 105 | highlightthickness=0, selectmode=SINGLE) 106 | self.list_box.pack(padx=10, pady=10, side=TOP, anchor=NW) 107 | 108 | self.list_box.bind("<>", self.from_history) 109 | scrollbar.config(command=self.list_box.yview) 110 | 111 | def translate(self): 112 | w = self.e1.get() 113 | w = w.lower() 114 | 115 | if w in data: 116 | self.l2['text'] = data[w] 117 | self.list_box.insert(END, w) # History 118 | HISTORY.append(w) 119 | 120 | elif w.title() in data: 121 | self.l2['text'] = data[w.title()] 122 | self.list_box.insert(END, w.title()) # History 123 | HISTORY.append(w.title()) 124 | 125 | elif w.upper() in data: # in case user enters words like: USA or NATO 126 | self.l2['text'] = data[w.upper()] 127 | self.list_box.insert(END, w.upper()) # History 128 | HISTORY.append(w.upper()) 129 | 130 | elif len(get_close_matches(w, data.keys())) > 0: 131 | yn = messagebox.askquestion("Hint", "Did you mean '%s' instead?" % get_close_matches(w, data.keys())[0]) 132 | if yn == "yes": 133 | self.l2['text'] = data[get_close_matches(w, data.keys())[0]] 134 | self.list_box.insert(END, get_close_matches(w, data.keys())[0]) # History 135 | HISTORY.append(get_close_matches(w, data.keys())[0]) 136 | 137 | elif yn == "no": 138 | self.l2['text'] = "The word doesn't exist. Please double check it." 139 | else: 140 | self.l2['text'] = "We didn't understand your entry." 141 | 142 | else: 143 | self.l2['text'] = "The word doesn't exist. Please double check it." 144 | 145 | print("Translated successfully!") 146 | 147 | # Bookmarks 148 | self.var = IntVar() 149 | c = ttk.Checkbutton( 150 | self.frame1, text="Add to bookmarks", 151 | variable=self.var, 152 | command=self.bookmark_it) 153 | 154 | c.grid(row=3, column=0, columnspan=2, padx=10, pady=10) 155 | 156 | # delete the last word 157 | # self.e1.delete(0, END) 158 | 159 | # For translate the words from History 160 | def from_history(self, *args): 161 | for i in self.list_box.curselection(): 162 | print('Translate from History:', HISTORY[i]) 163 | 164 | if HISTORY[i] in data: 165 | messagebox.showinfo("{}".format(HISTORY[i]), data[HISTORY[i]]) 166 | 167 | def bookmarks(self): 168 | self.hide_all_frames() 169 | self.bookmarks_frame.pack(fill="both", expand=1) 170 | p2 = ttk.Label(self.bookmarks_frame, text="Here you can find your bookmarks") 171 | p2.pack(padx=10, pady=10) 172 | 173 | # Add a scrollbar 174 | scrollbar = ttk.Scrollbar(self.bookmarks_frame) 175 | scrollbar.pack(side=RIGHT, fill=Y) 176 | 177 | self.list_box_1 = tk.Listbox(self.bookmarks_frame, yscrollcommand=scrollbar.set, width=50, height=50, 178 | borderwidth=0, highlightthickness=0, selectmode=SINGLE) 179 | self.list_box_1.pack(padx=10, pady=10, side=TOP, anchor=NW) 180 | 181 | self.list_box_1.insert('end', *BOOKMARKS) 182 | 183 | self.list_box_1.bind("<>", self.from_bookmarks) 184 | scrollbar.config(command=self.list_box_1.yview) 185 | 186 | def bookmark_it(self): 187 | if self.var.get() == 1: 188 | BOOKMARKS.append(self.e1.get()) 189 | print("Bookmarks: {}".format(BOOKMARKS)) 190 | else: 191 | pass 192 | 193 | # For translate the words from Bookmarks 194 | def from_bookmarks(self, *args): 195 | for i in self.list_box_1.curselection(): 196 | print('Translate from Bookmarks:', BOOKMARKS[i]) 197 | 198 | if BOOKMARKS[i] in data: 199 | messagebox.showinfo("{}".format(BOOKMARKS[i]), data[BOOKMARKS[i]]) 200 | 201 | def info_about(self): 202 | 203 | def callback(url): 204 | webbrowser.open_new(url) 205 | 206 | self.hide_all_frames() 207 | self.info_about_frame.pack(fill="both", expand=1) 208 | ttk.Label(self.info_about_frame, text="ABOUT", background='#c5e3e0').pack() 209 | ttk.Label(self.info_about_frame, text="EightSoft | Rustam-Z | Alimov-8").pack() 210 | 211 | link1 = tk.Label(self.info_about_frame, text="Source Code", fg='#215fdb') 212 | link1.pack() 213 | link1.bind("", 214 | lambda e: callback("https://github.com/Rustam-Z/learning-area/tree/master/app1_dictionary") 215 | ) 216 | 217 | 218 | class App(tk.Tk): 219 | def __init__(self, master): 220 | tk.Tk.__init__(self) 221 | self.master = master 222 | 223 | menubar = MenuBar(self) 224 | self.config(menu=menubar) 225 | 226 | 227 | def main(): 228 | app = App(None) 229 | app.title("My Dictionary App") 230 | app.geometry("400x400") 231 | style = ThemedStyle(app) 232 | style.set_theme("breeze") 233 | app.mainloop() 234 | 235 | 236 | if __name__ == "__main__": 237 | main() 238 | -------------------------------------------------------------------------------- /Projects/Flask App/app.py: -------------------------------------------------------------------------------- 1 | """Learning URLs""" 2 | 3 | from flask import Flask, redirect, url_for 4 | 5 | app = Flask(__name__) 6 | 7 | 8 | @app.route('/') 9 | def welcome(): 10 | return "

Hello World!

" 11 | 12 | 13 | @app.route('/dynamic/') 14 | def dynamic(num): 15 | return str(num) 16 | 17 | 18 | @app.route('/redirecting/') 19 | def redirecting(score): 20 | score = 25 21 | return redirect(url_for("dynamic", num=score)) 22 | 23 | 24 | if __name__ == '__main__': 25 | app.run(debug=True) 26 | -------------------------------------------------------------------------------- /Projects/Flask App/main.py: -------------------------------------------------------------------------------- 1 | ''' 2 | - Integrating with FLASK 3 | - GET and POST requests handling 4 | 5 | - Jinja2 6 | - {% %} for loop, if / else 7 | - {{ }} epressions to print output 8 | - {# #} comments 9 | ''' 10 | 11 | from flask import Flask, redirect, url_for, render_template, request 12 | 13 | app = Flask(__name__) 14 | 15 | 16 | @app.route('/') 17 | def welcome(): 18 | return render_template('index.html') 19 | 20 | 21 | @app.route('/results/') 22 | def results(score): 23 | # res = "" 24 | # if score >= 50: 25 | # res = "PASS" 26 | # else: 27 | # res = "FAIL" 28 | 29 | return render_template('result.html', result=score) 30 | 31 | 32 | @app.route('/submit', methods=['POST', 'GET']) 33 | def submit(): 34 | total_score = 0 35 | 36 | if request.method == 'POST': 37 | science = float(request.form['science']) 38 | maths = float(request.form['maths']) 39 | c = float(request.form['c']) 40 | data_science = float(request.form['datascience']) 41 | total_score = (science + maths + c + data_science) / 4 42 | 43 | return redirect(url_for('results', score=total_score)) 44 | 45 | 46 | if __name__ == '__main__': 47 | app.run(debug=True) 48 | -------------------------------------------------------------------------------- /Projects/Flask App/static/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: aqua; 3 | } -------------------------------------------------------------------------------- /Projects/Flask App/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |

HELLO WORLD!

9 |
10 |
11 |
12 |
13 |

14 |
15 |

16 |
17 |

18 | 19 |
20 | 21 |

If you click the "Submit" button, the form-data will be sent to "/submit".

22 | 23 | 24 | -------------------------------------------------------------------------------- /Projects/Flask App/templates/result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Final Results

4 | 5 | 6 | 7 | 8 | {% if result >= 50 %} 9 |

Congrats! You passed.

10 | {% else %} 11 |

You failed.

12 | {% endif %} 13 | 14 | 15 | -------------------------------------------------------------------------------- /Projects/Library Management System/backend.py: -------------------------------------------------------------------------------- 1 | import _sqlite3 2 | 3 | 4 | def connect(): 5 | conn = _sqlite3.connect("books.db") 6 | cur = conn.cursor() 7 | cur.execute( 8 | "CREATE TABLE IF NOT EXISTS book (id INTEGER PRIMARY KEY, title text, author text, year integer, isbn integer)") 9 | conn.commit() 10 | conn.close() 11 | 12 | 13 | def insert(title, author, year, isbn): 14 | conn = _sqlite3.connect("books.db") 15 | cur = conn.cursor() 16 | cur.execute("INSERT INTO book VALUES (NULL,?,?,?,?)", (title, author, year, isbn)) 17 | conn.commit() 18 | conn.close() 19 | view() 20 | 21 | 22 | def view(): 23 | conn = _sqlite3.connect("books.db") 24 | cur = conn.cursor() 25 | cur.execute("SELECT * FROM book") 26 | rows = cur.fetchall() 27 | conn.close() 28 | return rows 29 | 30 | 31 | def search(title="", author="", year="", isbn=""): 32 | conn = _sqlite3.connect("books.db") 33 | cur = conn.cursor() 34 | cur.execute("SELECT * FROM book WHERE title=? OR author=? OR year=? OR isbn=?", (title, author, year, isbn)) 35 | rows = cur.fetchall() 36 | conn.close() 37 | return rows 38 | 39 | 40 | def delete(id): 41 | conn = _sqlite3.connect("books.db") 42 | cur = conn.cursor() 43 | cur.execute("DELETE FROM book WHERE id=?", (id,)) 44 | conn.commit() 45 | conn.close() 46 | 47 | 48 | def update(id, title, author, year, isbn): 49 | conn = _sqlite3.connect("books.db") 50 | cur = conn.cursor() 51 | cur.execute("UPDATE book SET title=?, author=?, year=?, isbn=? WHERE id=?", (title, author, year, isbn, id)) 52 | conn.commit() 53 | conn.close() 54 | 55 | 56 | connect() 57 | # insert("The Sun","John Smith",1918,913123132) 58 | # delete(3) 59 | # update(4,"The moon","John Smooth",1917,99999) 60 | # print(view()) 61 | # print(search(author="John Smooth")) 62 | -------------------------------------------------------------------------------- /Projects/Library Management System/books.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rustam-Z/python-programming/e38a2305df555768a5ab0fa5383f77b73544c4bd/Projects/Library Management System/books.db -------------------------------------------------------------------------------- /Projects/Library Management System/frontend.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | import backend 3 | 4 | 5 | def get_selected_row(event): 6 | global selected_tuple 7 | index = list1.curselection()[0] 8 | selected_tuple = list1.get(index) 9 | e1.delete(0, END) 10 | e1.insert(END, selected_tuple[1]) 11 | e2.delete(0, END) 12 | e2.insert(END, selected_tuple[2]) 13 | e3.delete(0, END) 14 | e3.insert(END, selected_tuple[3]) 15 | e4.delete(0, END) 16 | e4.insert(END, selected_tuple[4]) 17 | 18 | 19 | def view_command(): 20 | list1.delete(0, END) 21 | for row in backend.view(): 22 | list1.insert(END, row) 23 | 24 | 25 | def search_command(): 26 | list1.delete(0, END) 27 | for row in backend.search(title_text.get(), author_text.get(), year_text.get(), isbn_text.get()): 28 | list1.insert(END, row) 29 | 30 | 31 | def add_command(): 32 | backend.insert(title_text.get(), author_text.get(), year_text.get(), isbn_text.get()) 33 | list1.delete(0, END) 34 | list1.insert(END, (title_text.get(), author_text.get(), year_text.get(), isbn_text.get())) 35 | 36 | 37 | def delete_command(): 38 | backend.delete(selected_tuple[0]) 39 | 40 | 41 | def update_command(): 42 | backend.update(selected_tuple[0], title_text.get(), author_text.get(), year_text.get(), isbn_text.get()) 43 | 44 | 45 | window = Tk() 46 | 47 | window.wm_title("BookStore") 48 | 49 | l1 = Label(window, text="Title") 50 | l1.grid(row=0, column=0) 51 | 52 | l2 = Label(window, text="Author") 53 | l2.grid(row=0, column=2) 54 | 55 | l3 = Label(window, text="Year") 56 | l3.grid(row=1, column=0) 57 | 58 | l4 = Label(window, text="ISBN") 59 | l4.grid(row=1, column=2) 60 | 61 | title_text = StringVar() 62 | e1 = Entry(window, textvariable=title_text) 63 | e1.grid(row=0, column=1) 64 | 65 | author_text = StringVar() 66 | e2 = Entry(window, textvariable=author_text) 67 | e2.grid(row=0, column=3) 68 | 69 | year_text = StringVar() 70 | e3 = Entry(window, textvariable=year_text) 71 | e3.grid(row=1, column=1) 72 | 73 | isbn_text = StringVar() 74 | e4 = Entry(window, textvariable=isbn_text) 75 | e4.grid(row=1, column=3) 76 | 77 | list1 = Listbox(window, height=6, width=35) 78 | list1.grid(row=2, column=0, rowspan=6, columnspan=2) 79 | 80 | sb1 = Scrollbar(window) 81 | sb1.grid(row=2, column=2, rowspan=6) 82 | 83 | list1.configure(yscrollcommand=sb1.set) 84 | sb1.configure(command=list1.yview) 85 | 86 | list1.bind('<>', get_selected_row) 87 | 88 | b1 = Button(window, text="View all", width=12, command=view_command) 89 | b1.grid(row=2, column=3) 90 | 91 | b2 = Button(window, text="Search entry", width=12, command=search_command) 92 | b2.grid(row=3, column=3) 93 | 94 | b3 = Button(window, text="Add entry", width=12, command=add_command) 95 | b3.grid(row=4, column=3) 96 | 97 | b4 = Button(window, text="Update selected", width=12, command=update_command) 98 | b4.grid(row=5, column=3) 99 | 100 | b5 = Button(window, text="Delete selected", width=12, command=delete_command) 101 | b5.grid(row=6, column=3) 102 | 103 | b6 = Button(window, text="Close", width=12, command=window.destroy) 104 | b6.grid(row=7, column=3) 105 | 106 | window.mainloop() 107 | -------------------------------------------------------------------------------- /Projects/Python OOP Basics/Readme.md: -------------------------------------------------------------------------------- 1 | # Object-Oriented Programming (OOP) in Python 2 | 3 | > TOPICS: `class`, `object`, `instance attributes`, `class attributes`, `inheritance`, `encapsulation`, `polymorphism` 4 | 5 | - `Classes` define functions called methods, 6 | which identify the behaviors and actions 7 | that an object created from the class 8 | can perform with its data. 9 | 10 | - `Instance` is an object that is built 11 | from a class and contains real data. 12 | Instance object consists of attributes and methods. 13 | 14 | - Attributes created in .__init__() are called `instance attributes`, 15 | which are spesific only for an instance. 16 | 17 | - `Class attributes` are attributes that have the same value for all class instances. 18 | You can define a class attribute by assigning a value to a variable name outside of .__init__(). 19 | 20 | - **Class**, which is a sort of blueprint for an object 21 | - **Instantiate** an object from a class 22 | - Use **attributes** and **methods** to define the **properties** and **behaviors** of an object 23 | - Use **inheritance** to create **child classes** from a **parent class** 24 | - Reference a method on a parent class using `super()` e.g. `super().__init__()` 25 | - Check if an object inherits from another class using `isinstance()` 26 | - **Polymorphism** allows the same interface for different objects, so programmers can write efficient code. 27 | 28 | 29 | ## References 30 | - https://realpython.com/python3-object-oriented-programming/ 31 | - https://www.programiz.com/python-programming/object-oriented-programming 32 | - https://realpython.com/oop-in-python-vs-java/ 33 | -------------------------------------------------------------------------------- /Projects/Python OOP Basics/oop.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "language_info": { 4 | "codemirror_mode": { 5 | "name": "ipython", 6 | "version": 3 7 | }, 8 | "file_extension": ".py", 9 | "mimetype": "text/x-python", 10 | "name": "python", 11 | "nbconvert_exporter": "python", 12 | "pygments_lexer": "ipython3", 13 | "version": "3.8.6" 14 | }, 15 | "orig_nbformat": 4, 16 | "kernelspec": { 17 | "name": "python3", 18 | "display_name": "Python 3.8.6 64-bit ('tf': conda)" 19 | }, 20 | "interpreter": { 21 | "hash": "4ea0e157563bacde0b7fd8dc93db6051c9678d5eadbd4117abf1a4cecbc8cd1a" 22 | } 23 | }, 24 | "nbformat": 4, 25 | "nbformat_minor": 2, 26 | "cells": [ 27 | { 28 | "cell_type": "code", 29 | "execution_count": 1, 30 | "metadata": {}, 31 | "outputs": [ 32 | { 33 | "output_type": "execute_result", 34 | "data": { 35 | "text/plain": [ 36 | "'\\n`Classes` define functions called methods, \\nwhich identify the behaviors and actions \\nthat an object created from the class \\ncan perform with its data.\\n\\n`Instance` is an object that is built \\nfrom a class and contains real data.\\n\\nAttributes created in .__init__() are called `instance attributes`,\\nwhich are spesific only for an instance.\\n\\n`Class attributes` are attributes that have the same value for all class instances. \\nYou can define a class attribute by assigning a value to a variable name outside of .__init__().\\n\\n'" 37 | ] 38 | }, 39 | "metadata": {}, 40 | "execution_count": 1 41 | } 42 | ], 43 | "source": [ 44 | "\"\"\"\n", 45 | "OOP Basics - Creating class and its instance\n", 46 | "\n", 47 | "`Classes` define functions called methods, \n", 48 | "which identify the behaviors and actions \n", 49 | "that an object created from the class \n", 50 | "can perform with its data.\n", 51 | "\n", 52 | "`Instance` is an object that is built \n", 53 | "from a class and contains real data.\n", 54 | "Instance object consists of attributes and methods.\n", 55 | "\n", 56 | "Attributes created in .__init__() are called `instance attributes`,\n", 57 | "which are spesific only for an instance.\n", 58 | "\n", 59 | "`Class attributes` are attributes that have the same value for all class instances. \n", 60 | "You can define a class attribute by assigning a value to a variable name outside of .__init__().\n", 61 | "\n", 62 | "\"\"\"" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 30, 68 | "metadata": {}, 69 | "outputs": [], 70 | "source": [ 71 | "class Dog:\n", 72 | " species = \"Canis familiaris\"\n", 73 | "\n", 74 | " def __init__(self, name, age):\n", 75 | " self.name = name\n", 76 | " self.age = age\n", 77 | "\n", 78 | " # Another instance method\n", 79 | " def speak(self, sound):\n", 80 | " return f\"{self.name} says {sound}\"\n", 81 | "\n", 82 | " # Special instance method - dunder methods\n", 83 | " def __str__(self):\n", 84 | " return f\"{self.name} is {self.age} years old\"" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": 31, 90 | "metadata": {}, 91 | "outputs": [], 92 | "source": [ 93 | "a = Dog(\"Buddy\", 9)\n", 94 | "b = Dog(\"Miles\", 4)" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": 32, 100 | "metadata": {}, 101 | "outputs": [ 102 | { 103 | "output_type": "stream", 104 | "name": "stdout", 105 | "text": [ 106 | "False\nFalse\n" 107 | ] 108 | } 109 | ], 110 | "source": [ 111 | "print(a == b) \n", 112 | "print(a is b) " 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": 33, 118 | "metadata": {}, 119 | "outputs": [ 120 | { 121 | "output_type": "stream", 122 | "name": "stdout", 123 | "text": [ 124 | "Buddy\n9\n" 125 | ] 126 | } 127 | ], 128 | "source": [ 129 | "print(a.name)\n", 130 | "print(a.age)" 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": 34, 136 | "metadata": {}, 137 | "outputs": [ 138 | { 139 | "output_type": "execute_result", 140 | "data": { 141 | "text/plain": [ 142 | "'Canis familiaris'" 143 | ] 144 | }, 145 | "metadata": {}, 146 | "execution_count": 34 147 | } 148 | ], 149 | "source": [ 150 | "a.species" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 35, 156 | "metadata": {}, 157 | "outputs": [ 158 | { 159 | "output_type": "execute_result", 160 | "data": { 161 | "text/plain": [ 162 | "10" 163 | ] 164 | }, 165 | "metadata": {}, 166 | "execution_count": 35 167 | } 168 | ], 169 | "source": [ 170 | "a.age = 10 # We can change values of attributes\n", 171 | "a.age" 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": 36, 177 | "metadata": {}, 178 | "outputs": [ 179 | { 180 | "output_type": "stream", 181 | "name": "stdout", 182 | "text": [ 183 | "Felis silvestris\nCanis familiaris\n" 184 | ] 185 | } 186 | ], 187 | "source": [ 188 | "a.species = 'Felis silvestris'\n", 189 | "print(a.species)\n", 190 | "print(b.species) # Not changed for another instance" 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": 37, 196 | "metadata": {}, 197 | "outputs": [ 198 | { 199 | "output_type": "execute_result", 200 | "data": { 201 | "text/plain": [ 202 | "'Buddy says Woof woof'" 203 | ] 204 | }, 205 | "metadata": {}, 206 | "execution_count": 37 207 | } 208 | ], 209 | "source": [ 210 | "sound = \"Woof woof\"\n", 211 | "a.speak(sound)" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": 38, 217 | "metadata": {}, 218 | "outputs": [ 219 | { 220 | "output_type": "execute_result", 221 | "data": { 222 | "text/plain": [ 223 | "<__main__.Dog at 0x110bc6160>" 224 | ] 225 | }, 226 | "metadata": {}, 227 | "execution_count": 38 228 | } 229 | ], 230 | "source": [ 231 | "a" 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": 39, 237 | "metadata": {}, 238 | "outputs": [ 239 | { 240 | "output_type": "stream", 241 | "name": "stdout", 242 | "text": [ 243 | "Buddy is 10 years old\n" 244 | ] 245 | } 246 | ], 247 | "source": [ 248 | "print(a) # Because we have special instance method __str__" 249 | ] 250 | }, 251 | { 252 | "cell_type": "code", 253 | "execution_count": null, 254 | "metadata": {}, 255 | "outputs": [], 256 | "source": [ 257 | "\"\"\"Inheritance\n", 258 | "- Parent class --> child class\n", 259 | "\n", 260 | "- Overriding (parent has, child just changes):\n", 261 | "You may have inherited your hair color from your mother. It’s an attribute you were born with. Let’s say you decide to color your hair purple. Assuming your mother doesn’t have purple hair, you’ve just ```overridden``` the hair color attribute that you inherited from your mom.\n", 262 | "\n", 263 | "- Extending (parent do not has):\n", 264 | "You also inherit, in a sense, your language from your parents. If your parents speak English, then you’ll also speak English. Now imagine you decide to learn a second language, like German. In this case you’ve ```extended``` your attributes because you’ve added an attribute that your parents don’t have.\n", 265 | "\"\"\"\n" 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": 59, 271 | "metadata": {}, 272 | "outputs": [], 273 | "source": [ 274 | "class JackRussellTerrier(Dog):\n", 275 | " def speak(self, sound=\"Arf\"):\n", 276 | " # return f\"{self.name} says {sound}\"\n", 277 | " return super().speak(sound)\n", 278 | "\n", 279 | "class Dachshund(Dog):\n", 280 | " def speak(self, sound=\"Yap\"):\n", 281 | " return f\"{self.name} says {sound}\"\n", 282 | "\n", 283 | "class Bulldog(Dog):\n", 284 | " def speak(self, sound=\"Woof\"):\n", 285 | " return f\"{self.name} says {sound}\"" 286 | ] 287 | }, 288 | { 289 | "cell_type": "code", 290 | "execution_count": 60, 291 | "metadata": {}, 292 | "outputs": [ 293 | { 294 | "output_type": "stream", 295 | "name": "stdout", 296 | "text": [ 297 | "Miles\n4\nMiles is 4 years old\nMiles says Arf\nMiles says Bla bla bla\n" 298 | ] 299 | } 300 | ], 301 | "source": [ 302 | "c = JackRussellTerrier(\"Miles\", 4)\n", 303 | "print(c.name)\n", 304 | "print(c.age)\n", 305 | "print(c)\n", 306 | "print(c.speak()) # Great, now we can use .speak() even without passing arg\n", 307 | "print(c.speak(\"Bla bla bla\"))" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": 61, 313 | "metadata": {}, 314 | "outputs": [ 315 | { 316 | "output_type": "stream", 317 | "name": "stdout", 318 | "text": [ 319 | "True\nTrue\nFalse\n" 320 | ] 321 | } 322 | ], 323 | "source": [ 324 | "print(isinstance(c, Dog))\n", 325 | "print(isinstance(c, JackRussellTerrier))\n", 326 | "print(isinstance(c, Bulldog))" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "execution_count": 62, 332 | "metadata": {}, 333 | "outputs": [ 334 | { 335 | "output_type": "stream", 336 | "name": "stdout", 337 | "text": [ 338 | "Bird is ready\nPenguin is ready\nPenguin\nSwim faster\nRun faster\n" 339 | ] 340 | } 341 | ], 342 | "source": [ 343 | "# One more example\n", 344 | "# parent class\n", 345 | "class Bird:\n", 346 | " \n", 347 | " def __init__(self):\n", 348 | " print(\"Bird is ready\")\n", 349 | "\n", 350 | " def whoisThis(self):\n", 351 | " print(\"Bird\")\n", 352 | "\n", 353 | " def swim(self):\n", 354 | " print(\"Swim faster\")\n", 355 | "\n", 356 | "# child class\n", 357 | "class Penguin(Bird):\n", 358 | "\n", 359 | " def __init__(self):\n", 360 | " # call super() function\n", 361 | " super().__init__()\n", 362 | " print(\"Penguin is ready\")\n", 363 | "\n", 364 | " def whoisThis(self):\n", 365 | " print(\"Penguin\")\n", 366 | "\n", 367 | " def run(self):\n", 368 | " print(\"Run faster\")\n", 369 | "\n", 370 | "peggy = Penguin()\n", 371 | "peggy.whoisThis()\n", 372 | "peggy.swim()\n", 373 | "peggy.run()" 374 | ] 375 | }, 376 | { 377 | "cell_type": "code", 378 | "execution_count": 63, 379 | "metadata": {}, 380 | "outputs": [ 381 | { 382 | "output_type": "stream", 383 | "name": "stdout", 384 | "text": [ 385 | "Selling Price: 900\nSelling Price: 900\nSelling Price: 1000\n" 386 | ] 387 | } 388 | ], 389 | "source": [ 390 | "\"\"\"\n", 391 | "Encapsulation\n", 392 | "\n", 393 | "We can restrict access to methods and variables. This prevents data from direct modification which is called encapsulation. In Python, we denote private attributes using underscore as the prefix i.e single _ or double __\n", 394 | "\n", 395 | "\"\"\"\n", 396 | "class Computer:\n", 397 | "\n", 398 | " def __init__(self):\n", 399 | " self.__maxprice = 900\n", 400 | "\n", 401 | " def sell(self):\n", 402 | " print(\"Selling Price: {}\".format(self.__maxprice))\n", 403 | "\n", 404 | " def setMaxPrice(self, price):\n", 405 | " self.__maxprice = price\n", 406 | "\n", 407 | "c = Computer()\n", 408 | "c.sell()\n", 409 | "\n", 410 | "# change the price\n", 411 | "c.__maxprice = 1000\n", 412 | "c.sell()\n", 413 | "\n", 414 | "# using setter function\n", 415 | "c.setMaxPrice(1000)\n", 416 | "c.sell()" 417 | ] 418 | }, 419 | { 420 | "cell_type": "code", 421 | "execution_count": 64, 422 | "metadata": {}, 423 | "outputs": [ 424 | { 425 | "output_type": "stream", 426 | "name": "stdout", 427 | "text": [ 428 | "Parrot can fly\nPenguin can't fly\n" 429 | ] 430 | } 431 | ], 432 | "source": [ 433 | "\"\"\"\n", 434 | "Polymorphism\n", 435 | "\n", 436 | "Polymorphism is an ability (in OOP) to use a common interface for multiple forms (data types).\n", 437 | "\n", 438 | "Suppose, we need to color a shape, there are multiple shape options (rectangle, square, circle). However we could use the same method to color any shape. This concept is called Polymorphism.\n", 439 | "\n", 440 | "\"\"\"\n", 441 | "class Parrot:\n", 442 | " def fly(self):\n", 443 | " print(\"Parrot can fly\")\n", 444 | " \n", 445 | " def swim(self):\n", 446 | " print(\"Parrot can't swim\")\n", 447 | "\n", 448 | "class Penguin:\n", 449 | " def fly(self):\n", 450 | " print(\"Penguin can't fly\")\n", 451 | " \n", 452 | " def swim(self):\n", 453 | " print(\"Penguin can swim\")\n", 454 | "\n", 455 | "# common interface\n", 456 | "def flying_test(bird):\n", 457 | " bird.fly()\n", 458 | "\n", 459 | "#instantiate objects\n", 460 | "blu = Parrot()\n", 461 | "peggy = Penguin()\n", 462 | "\n", 463 | "# passing the object\n", 464 | "flying_test(blu)\n", 465 | "flying_test(peggy)" 466 | ] 467 | }, 468 | { 469 | "cell_type": "code", 470 | "execution_count": null, 471 | "metadata": {}, 472 | "outputs": [], 473 | "source": [] 474 | } 475 | ] 476 | } -------------------------------------------------------------------------------- /Projects/Snake Game/snake_game.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rustam-Z/python-programming/e38a2305df555768a5ab0fa5383f77b73544c4bd/Projects/Snake Game/snake_game.exe -------------------------------------------------------------------------------- /Projects/Snake Game/snake_game.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: -*- 3 | import turtle as t 4 | import random as rd 5 | 6 | t.bgcolor('yellow') 7 | 8 | caterpillar = t.Turtle() 9 | caterpillar.shape('square') 10 | caterpillar.speed(0) 11 | caterpillar.penup() 12 | caterpillar.hideturtle() 13 | 14 | leaf = t.Turtle() 15 | leaf_shape = ((0, 0), (14, 2), (18, 6), (20, 20), (6, 18), (2, 14)) 16 | t.register_shape('leaf', leaf_shape) 17 | leaf.shape('leaf') 18 | leaf.color('green') 19 | leaf.penup() 20 | leaf.hideturtle() 21 | leaf.speed() 22 | 23 | game_started = False 24 | text_turtle = t.Turtle() 25 | text_turtle.write('- - - Eight Soft Academy - - - \n\n Press SPACE to start', align='center', 26 | font=('Arial', 16, 'bold')) 27 | text_turtle.hideturtle() 28 | 29 | score_turtle = t.Turtle() 30 | score_turtle.hideturtle() 31 | score_turtle.speed(0) 32 | 33 | 34 | def outside_window(): 35 | left_wall = -t.window_width() / 2 36 | right_wall = t.window_width() / 2 37 | top_wall = t.window_height() / 2 38 | bottom_wall = -t.window_height() / 2 39 | (x, y) = caterpillar.pos() 40 | outside = x < left_wall or x > right_wall or y < bottom_wall or y > top_wall 41 | return outside 42 | 43 | 44 | def place_leaf(): 45 | leaf.hideturtle() 46 | leaf.setx(rd.randint(-200, 200)) 47 | leaf.sety(rd.randint(-200, 200)) 48 | leaf.showturtle() 49 | 50 | 51 | def game_over(): 52 | global game_started 53 | caterpillar.color('yellow') 54 | leaf.color('yellow') 55 | t.penup() 56 | t.hideturtle() 57 | t.write('GAME OVER!', align='center', font=('Aerial', 30, 'normal')) 58 | 59 | 60 | def display_score(current_score): 61 | score_turtle.clear() 62 | score_turtle.penup() 63 | x = (t.window_width() / 2) - 60 64 | y = (t.window_height() / 2) - 60 65 | score_turtle.setpos(x, y) 66 | score_turtle.write(str(current_score), align='right', font=('Arial', 40, 'bold')) 67 | 68 | 69 | def start_game(): 70 | global game_started 71 | if game_started: 72 | return 73 | game_started = True 74 | 75 | score = 0 76 | text_turtle.clear() 77 | 78 | caterpillar_speed = 2 79 | caterpillar_length = 3 80 | caterpillar.shapesize(1, caterpillar_length, 1) 81 | caterpillar.showturtle() 82 | display_score(score) 83 | place_leaf() 84 | 85 | while (True): 86 | caterpillar.forward(caterpillar_speed) 87 | if (caterpillar.distance(leaf) < 20): 88 | caterpillar_speed += 0.3 89 | score += 10 90 | display_score(score) 91 | place_leaf() 92 | 93 | if outside_window(): 94 | game_over() 95 | break 96 | 97 | 98 | def move_up(): 99 | if caterpillar.heading() == 0 or caterpillar.heading() == 180: 100 | caterpillar.setheading(90) 101 | 102 | 103 | def move_down(): 104 | if caterpillar.heading() == 0 or caterpillar.heading() == 180: 105 | caterpillar.setheading(270) 106 | 107 | 108 | def move_left(): 109 | if caterpillar.heading() == 90 or caterpillar.heading() == 270: 110 | caterpillar.setheading(180) 111 | 112 | 113 | def move_right(): 114 | if caterpillar.heading() == 90 or caterpillar.heading() == 270: 115 | caterpillar.setheading(0) 116 | 117 | 118 | t.onkey(start_game, 'space') 119 | t.onkey(move_up, 'Up') 120 | t.onkey(move_right, 'Right') 121 | t.onkey(move_down, 'Down') 122 | t.onkey(move_left, 'Left') 123 | t.listen() 124 | t.mainloop() 125 | -------------------------------------------------------------------------------- /Projects/Telegram Bots/Grading.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rustam-Z/python-programming/e38a2305df555768a5ab0fa5383f77b73544c4bd/Projects/Telegram Bots/Grading.pdf -------------------------------------------------------------------------------- /Projects/Telegram Bots/README.md: -------------------------------------------------------------------------------- 1 | # Python Telegram Bots 2 | 3 | By Rustam Zokirov 4 | 5 | ## Projects list: 6 | - [Repeater](/repeater.py) 7 | - [Number guessing](/guessa.py) 8 | - [AI chat with Eliza](/elizaa.py) 9 | - [Document sender](/send_doc.py) 10 | - [Courses scores](/failpy.py) 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Projects/Telegram Bots/config.py: -------------------------------------------------------------------------------- 1 | TOKEN = '' # bot token from @BotFather 2 | # Put the TOKEN inside 3 | -------------------------------------------------------------------------------- /Projects/Telegram Bots/elizaa.py: -------------------------------------------------------------------------------- 1 | from nltk.chat.eliza import eliza_chatbot 2 | import telepot 3 | import asyncio 4 | import telepot.aio 5 | from telepot.aio.loop import MessageLoop 6 | import config 7 | 8 | 9 | async def hande(msg): 10 | content_type, chat_type, chat_id = telepot.glance(msg) 11 | command = msg['text'] 12 | 13 | print(content_type, chat_type, chat_id) 14 | print('Got command: %s' % command) 15 | 16 | if content_type == 'text': 17 | if command == "/start": 18 | await bot.sendMessage(chat_id, "Hello, do you need any help?") 19 | else: 20 | await bot.sendMessage(chat_id, eliza_chatbot.respond(command)) 21 | 22 | 23 | # put the token inside 24 | TOKEN = '' 25 | 26 | bot = telepot.aio.Bot(TOKEN) 27 | loop = asyncio.get_event_loop() 28 | 29 | loop.create_task(MessageLoop(bot, hande).run_forever()) 30 | # also we may use bot.message_loop(handle) 31 | 32 | print("Listening ...") 33 | 34 | # keep the program running 35 | loop.run_forever() 36 | -------------------------------------------------------------------------------- /Projects/Telegram Bots/guessa.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import asyncio 3 | import random 4 | import telepot 5 | import config 6 | from telepot.aio.loop import MessageLoop 7 | from telepot.aio.delegate import per_chat_id, create_open, pave_event_space 8 | 9 | 10 | class Player(telepot.aio.helper.ChatHandler): 11 | def __init__(self, *args, **kwargs): 12 | super(Player, self).__init__(*args, **kwargs) 13 | self._answer = random.randint(0, 99) 14 | 15 | def _hint(self, answer, guess): 16 | if answer > guess: 17 | return 'larger' 18 | else: 19 | return 'smaller' 20 | 21 | async def open(self, initial_msg, seed): 22 | await self.sender.sendMessage('Guess my number') 23 | return True # prevent on_message() from being called on the initial message 24 | 25 | async def on_chat_message(self, msg): 26 | content_type, chat_type, chat_id = telepot.glance(msg) 27 | 28 | if content_type != 'text': 29 | await self.sender.sendMessage('Give me a number, please.') 30 | return 31 | 32 | try: 33 | guess = int(msg['text']) 34 | except ValueError: 35 | await self.sender.sendMessage('Give me a number, please.') 36 | return 37 | 38 | # check the guess against the answer ... 39 | if guess != self._answer: 40 | # give a descriptive hint 41 | hint = self._hint(self._answer, guess) 42 | await self.sender.sendMessage(hint) 43 | else: 44 | await self.sender.sendMessage('Correct!') 45 | self.close() 46 | 47 | async def on__idle(self, event): 48 | await self.sender.sendMessage('Game expired. The answer is %d' % self._answer) 49 | self.close() 50 | 51 | 52 | TOKEN = '1295279684:AAGKfm8kGIqS6q1r2vCbUpozfDoX-TlvDHY' 53 | 54 | bot = telepot.aio.DelegatorBot(TOKEN, [ 55 | pave_event_space()( 56 | per_chat_id(), create_open, Player, timeout=10), 57 | ]) 58 | 59 | loop = asyncio.get_event_loop() 60 | loop.create_task(MessageLoop(bot).run_forever()) 61 | print('Listening ...') 62 | 63 | loop.run_forever() 64 | -------------------------------------------------------------------------------- /Projects/Telegram Bots/repeater.py: -------------------------------------------------------------------------------- 1 | import telepot 2 | import time 3 | import telepot.aio 4 | from telepot.loop import MessageLoop 5 | from config import TOKEN # Custom token 6 | 7 | 8 | def handle(msg): 9 | content_type, chat_type, chat_id = telepot.glance(msg) 10 | command = msg['text'] 11 | 12 | print(content_type, chat_type, chat_id) 13 | print('Got command: %s' % command) 14 | 15 | if content_type == 'text': 16 | bot.sendMessage(chat_id, "Ты сказал '{}'".format(command)) 17 | 18 | 19 | bot = telepot.Bot(TOKEN) 20 | 21 | MessageLoop(bot, handle).run_as_thread() 22 | # also we may use bot.message_loop(handle) 23 | 24 | print("Listening ...") 25 | 26 | # keep the program running 27 | while 1: 28 | time.sleep(10) 29 | -------------------------------------------------------------------------------- /Projects/Telegram Bots/repeatera.py: -------------------------------------------------------------------------------- 1 | import telepot 2 | import asyncio 3 | import telepot.aio 4 | from telepot.aio.loop import MessageLoop 5 | import config 6 | 7 | 8 | async def hande(msg): 9 | content_type, chat_type, chat_id = telepot.glance(msg) 10 | command = msg['text'] 11 | 12 | print(content_type, chat_type, chat_id) 13 | print('Got command: %s' % command) 14 | 15 | if content_type == 'text': 16 | await bot.sendMessage(chat_id, "You said '{}'".format(command)) 17 | 18 | 19 | TOKEN = config.TOKEN 20 | 21 | bot = telepot.aio.Bot(TOKEN) 22 | loop = asyncio.get_event_loop() 23 | 24 | loop.create_task(MessageLoop(bot, hande).run_forever()) 25 | # also we may use bot.message_loop(handle) 26 | 27 | print("Listening ...") 28 | 29 | # keep the program running 30 | loop.run_forever() 31 | -------------------------------------------------------------------------------- /Projects/Telegram Bots/send_doc.py: -------------------------------------------------------------------------------- 1 | import telepot 2 | import asyncio 3 | import telepot.aio 4 | from telepot.aio.loop import MessageLoop 5 | import config 6 | from telepot.namedtuple import ReplyKeyboardMarkup, KeyboardButton, ReplyKeyboardRemove, ForceReply 7 | from telepot.namedtuple import InlineKeyboardMarkup, InlineKeyboardButton 8 | from telepot.namedtuple import InlineQueryResultArticle, InlineQueryResultPhoto, InputTextMessageContent 9 | 10 | 11 | async def handel(msg): 12 | content_type, chat_type, chat_id = telepot.glance(msg) 13 | command = msg 14 | 15 | print(content_type, chat_type, chat_id) 16 | print('Got command: %s' % command) 17 | 18 | if command == '/start': 19 | await bot.sendMessage(chat_id, "Now please send your phone number!") 20 | markup = ReplyKeyboardMarkup(keyboard=[ 21 | [dict(text='Phone', request_contact=True), KeyboardButton(text='Location', request_location=True)], 22 | ]) 23 | await bot.sendMessage(chat_id, 'Thank you!', reply_markup=markup) 24 | 25 | if command == 'ok' or 'Ok' or 'OK': 26 | await bot.sendMessage(chat_id, "Hi there. Now I will send you the pdf below ...") 27 | await bot.sendDocument(chat_id, document=open('Grading.pdf', 'rb')) 28 | 29 | elif command == 'thank you' or 'thanks' or 'thanks bro' or 'thank you bro': 30 | await bot.sendMessage(chat_id, "Welcome :)") 31 | 32 | # await bot.sendMessage(chat_id, "You said '{}'".format(command)) 33 | 34 | 35 | TOKEN = '' 36 | 37 | bot = telepot.aio.Bot(TOKEN) 38 | loop = asyncio.get_event_loop() 39 | 40 | loop.create_task(MessageLoop(bot, handel).run_forever()) 41 | # also we may use bot.message_loop(handle) 42 | 43 | print("Listening ...") 44 | 45 | # keep the program running 46 | loop.run_forever() 47 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/README.md: -------------------------------------------------------------------------------- 1 | # Python Tkinter GUI Programs 2 | 3 | - [Calculator](examples/calculator_app.py) 4 | - [File reader audio](examples/file-3_with_audio_reader.py) 5 | - [Image viewer](examples/image_viewer_app.py) 6 | - [File explorer](examples/file-2.py) 7 | - [Exe terminator](examples/close_exe.py) 8 | - [Converter](examples/converter.py) 9 | - [CRM](examples/crm.py) 10 | - [Loading page](examples/loading_page.py) 11 | - [Calendar](examples/my_calendar.py) 12 | - [Menu driven app](examples/menu_bar_oop_frame-2.py) 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/Tkinter.txt: -------------------------------------------------------------------------------- 1 | REFERENCES: 2 | � Put the venv in your .gitignore: 3 | git init 4 | echo 'venv' > .gitignore 5 | -> tkinter tutorial: https://www.tutorialspoint.com/python/python_gui_programming.htm 6 | -> tkinter YouTube tutorial series: https://www.youtube.com/watch?v=yQSEXcf6s2I&list 7 | -> https://realpython.com/openpyxl-excel-spreadsheets-python/ 8 | -> https://www.geeksforgeeks.org/writing-excel-sheet-using-python/ 9 | QUESTIONS: 10 | � how to open an excel spreadsheet in tkinter application; 11 | � how to make a db; 12 | � how to fill the excel template with data from db; 13 | � print button in tkinter application; 14 | ===================================================== 15 | TKINTER: 16 | WIDGETS: Label, Button, Entry, ImageTk, LabelFrame, Radio 17 | 18 | PART 1: 19 | � declare the widget and put on screen(pack, grid); 20 | � LABEL 21 | from tkinter import * 22 | window = Tk() 23 | # to rename title of the window window.title("GUI") 24 | # window.iconbitmap("icon.ico") 25 | # pack is used to show the object in the window 26 | label = Label(window, text="Hello World!").pack() 27 | window.mainloop() 28 | 29 | � GRID SYSTEM 30 | my_widget.grid(row=0, column=0) 31 | 32 | � BUTTON 33 | my_button = Button(window, text="Click me!", command).pack() 34 | parameters: state=DISABLED, padx=50(size), pady=50, fg, bg; 35 | 36 | � ENTRY 37 | my_entry = Entry(window).pack() 38 | 39 | � IMAGES 40 | from PIL import Image, ImageTk 41 | my_img = ImageTk.PhotoImage(Image.open ('examples/photos/image.jpg')) 42 | my_label = Label(image=my_img) 43 | my_label.pack() 44 | 45 | � FRAMES 46 | frame = LabelFrame(root, padx=5, pady=5) # inside 47 | frame.pack(padx=100, pady=100) # outside 48 | button = Button(frame, text="Click me!").pack() 49 | 50 | � RADIO BUTTOM/DROPDOWN 51 | 52 | ====================================================== 53 | PART 2: SQL-> MySQL 54 | 1. my_db = mysql.connector.connect(host="localhost", user="root", passwd="1234") 55 | 2. create cursor: my_cursor = my_db.cursor() 56 | 3. create db: my_cursor.execute("CREATE DATABASE codemy") 57 | 3.1. check to see if db was created: 58 | my_cursor.execute("SHOW DATABASES") 59 | for db in my_cursor: 60 | print(db) 61 | 3.2. comment CREATE DATABASE 62 | 4. create a table: my_cursor.execute("CREATE TABLE IF NOT EXISTS customers (name VARCHAR(255), phone int(10))") 63 | 5. then add in my_db: database = "codemy" 64 | 6. comment CREATE TABLE 65 | 7. check if data was added to db: 66 | my_cursor.execute("select * from customers ") 67 | res = my_cursor.fetchall() 68 | for i in res: 69 | print(i) 70 | 71 | ================================================== 72 | 73 | 74 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/address_book.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rustam-Z/python-programming/e38a2305df555768a5ab0fa5383f77b73544c4bd/Projects/Tkinter Projects/address_book.db -------------------------------------------------------------------------------- /Projects/Tkinter Projects/customers.csv: -------------------------------------------------------------------------------- 1 | 1,1,1,1.00,1,1,1,1,1,1,1,1,1,1 2 | Rus,Zok,1234,125.00,2,zok,123,321,SaM,hE,uZ,985589,Visa,888asd 3 | Alim,Abd,100000,32.00,3,s@gmail.com,123,432,Tash,T,uzbd,234123,pyan,83 4 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/buttons.py: -------------------------------------------------------------------------------- 1 | # By RΨST-4M 🚀 2 | 3 | from tkinter import * 4 | 5 | root = Tk() 6 | 7 | 8 | def myClick(): 9 | my_label = Label(root, text="I clicked a Button!", ) 10 | my_label.pack() 11 | 12 | 13 | myButton = Button(root, text="Click me!", command=myClick, fg="blue", bg="yellow") 14 | myButton.pack() 15 | 16 | # Button's arguments 17 | # state=DISABLED 18 | # size: padx=50, pady=50 19 | # text color: fg="blue", 20 | # command=myFunction 21 | 22 | root.mainloop() 23 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/calculator_app.py: -------------------------------------------------------------------------------- 1 | # Tuesday, July 14, 2020 2 | # By RΨST-4M 🚀 3 | # EightSoft Company CEO 4 | 5 | from tkinter import * 6 | 7 | root = Tk() 8 | root.title("Simple Calculator") 9 | 10 | f_num = 0 # global variables 11 | math = "" 12 | 13 | e = Entry(root, width=34, borderwidth=5) 14 | e.grid(row=0, column=0, columnspan=3, padx=10, pady=10) 15 | 16 | 17 | def button_click(number): 18 | """You will be able to type normal numbers with this function.""" 19 | current = e.get() 20 | e.delete(0, END) 21 | e.insert(0, str(current) + str(number)) 22 | 23 | 24 | def button_clear(): 25 | """Just clears the Entry.""" 26 | e.delete(0, END) 27 | 28 | 29 | def button_add(): 30 | """Saves the first number in memory with global f_num.""" 31 | first_number = e.get() 32 | global f_num 33 | global math 34 | math = "addition" 35 | f_num = int(first_number) 36 | e.delete(0, END) 37 | 38 | 39 | def button_subtract(): 40 | first_number = e.get() 41 | global f_num 42 | global math 43 | math = "subtraction" 44 | f_num = int(first_number) 45 | e.delete(0, END) 46 | 47 | 48 | def button_multiply(): 49 | first_number = e.get() 50 | global f_num 51 | global math 52 | math = "multiplication" 53 | f_num = int(first_number) 54 | e.delete(0, END) 55 | 56 | 57 | def button_divide(): 58 | first_number = e.get() 59 | global f_num 60 | global math 61 | math = "division" 62 | f_num = int(first_number) 63 | e.delete(0, END) 64 | 65 | 66 | def button_equal(): 67 | """Outputs the result.""" 68 | second_number = e.get() 69 | e.delete(0, END) 70 | 71 | if math == "addition": 72 | e.insert(0, f_num + int(second_number)) 73 | elif math == "subtraction": 74 | e.insert(0, f_num - int(second_number)) 75 | elif math == "multiplication": 76 | e.insert(0, f_num * int(second_number)) 77 | elif math == "division": 78 | e.insert(0, f_num / int(second_number)) 79 | 80 | 81 | # defining the buttons 82 | button_1 = Button(root, text="1", padx=40, pady=20, command=lambda: button_click(1)) 83 | button_2 = Button(root, text="2", padx=40, pady=20, command=lambda: button_click(2)) 84 | button_3 = Button(root, text="3", padx=40, pady=20, command=lambda: button_click(3)) 85 | 86 | button_4 = Button(root, text="4", padx=40, pady=20, command=lambda: button_click(4)) 87 | button_5 = Button(root, text="5", padx=40, pady=20, command=lambda: button_click(5)) 88 | button_6 = Button(root, text="6", padx=40, pady=20, command=lambda: button_click(6)) 89 | 90 | button_7 = Button(root, text="7", padx=40, pady=20, command=lambda: button_click(7)) 91 | button_8 = Button(root, text="8", padx=40, pady=20, command=lambda: button_click(8)) 92 | button_9 = Button(root, text="9", padx=40, pady=20, command=lambda: button_click(9)) 93 | button_0 = Button(root, text="0", padx=40, pady=20, command=lambda: button_click(0)) 94 | 95 | button_add = Button(root, text="+", padx=39, pady=20, command=button_add) 96 | button_equal = Button(root, text="=", padx=87, pady=20, command=button_equal) 97 | button_clear = Button(root, text="Clear", padx=76.5, pady=20, command=button_clear) 98 | 99 | button_subtract = Button(root, text="-", padx=41, pady=20, command=button_subtract) 100 | button_multiply = Button(root, text="*", padx=40, pady=20, command=button_multiply) 101 | button_divide = Button(root, text="/", padx=41, pady=20, command=button_divide) 102 | 103 | # Putting the buttons on the screen 104 | button_1.grid(row=3, column=0) 105 | button_2.grid(row=3, column=1) 106 | button_3.grid(row=3, column=2) 107 | 108 | button_4.grid(row=2, column=0) 109 | button_5.grid(row=2, column=1) 110 | button_6.grid(row=2, column=2) 111 | 112 | button_7.grid(row=1, column=0) 113 | button_8.grid(row=1, column=1) 114 | button_9.grid(row=1, column=2) 115 | 116 | button_0.grid(row=4, column=0) 117 | button_clear.grid(row=4, column=1, columnspan=2) 118 | button_add.grid(row=5, column=0) 119 | button_equal.grid(row=5, column=1, columnspan=2) 120 | 121 | button_subtract.grid(row=6, column=0) 122 | button_multiply.grid(row=6, column=1) 123 | button_divide.grid(row=6, column=2) 124 | 125 | # runs the code in loop 126 | root.mainloop() 127 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/close_exe.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def closeFile(): 5 | try: 6 | os.system('TASKKILL /F /IM excel.exe') 7 | 8 | except Exception: 9 | print("KU") 10 | 11 | 12 | closeFile() 13 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/converter.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | 3 | window = Tk() 4 | 5 | 6 | def from_kg(): 7 | gram = float(e1_value.get()) * 1000 8 | pound = float(e1_value.get()) * 2.20462 9 | ounce = float(e1_value.get()) * 35.274 10 | t1.delete('1.0', END) 11 | t1.insert(END, gram) 12 | t2.delete('1.0', END) 13 | t2.insert(END, pound) 14 | t3.delete('1.0', END) 15 | t3.insert(END, ounce) 16 | 17 | 18 | l1 = Label(window, text="Kg", height=1, width=20) 19 | l1.grid(row=0, column=0) 20 | 21 | e1_value = StringVar() 22 | e1 = Entry(window, textvariable=e1_value) 23 | e1.grid(row=0, column=1) 24 | 25 | b1 = Button(window, text="Convert", command=from_kg, height=1, width=20) 26 | b1.grid(row=0, column=2) 27 | 28 | t1 = Text(window, height=1, width=20) 29 | t1.grid(row=1, column=0) 30 | 31 | t2 = Text(window, height=1, width=20) 32 | t2.grid(row=1, column=1) 33 | 34 | t3 = Text(window, height=1, width=20) 35 | t3.grid(row=1, column=2) 36 | 37 | window.mainloop() 38 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/crm.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from PIL import ImageTk, Image 3 | import mysql.connector 4 | import csv 5 | 6 | # Main Window 7 | root = Tk() 8 | root.title("CRM Database") 9 | root.geometry("320x480") 10 | 11 | my_db = mysql.connector.connect( 12 | host="localhost", 13 | user="root", 14 | passwd="1234", 15 | database="codemy", 16 | ) 17 | 18 | # Check to see if connection to MySQL was created 19 | # print(my_db) 20 | 21 | # ============== Create a cursor and initialize it ============== 22 | my_cursor = my_db.cursor() 23 | 24 | # Create a db --we need only for the first time --then comment it 25 | # my_cursor.execute("CREATE DATABASE codemy") 26 | 27 | # ============= Test to see if db was created ============ 28 | # for db in my_cursor: 29 | # print(db) 30 | 31 | # =========== Create A Table ============ 32 | my_cursor.execute("CREATE TABLE IF NOT EXISTS customers (" 33 | "first_name VARCHAR(255)," 34 | "last_name VARCHAR(255)," 35 | "zip_code INT(10)," 36 | "price_paid DECIMAL(10, 2)," 37 | "user_id INT AUTO_INCREMENT PRIMARY KEY " 38 | ")") 39 | 40 | 41 | # # =========== Alter Table =========== 42 | # my_cursor.execute("ALTER TABLE customers ADD (\ 43 | # email VARCHAR(255),\ 44 | # address_1 VARCHAR(255),\ 45 | # address_2 VARCHAR(255),\ 46 | # city VARCHAR(50),\ 47 | # state VARCHAR(50),\ 48 | # country VARCHAR(255),\ 49 | # phone VARCHAR(255),\ 50 | # payment_method VARCHAR(50),\ 51 | # discount_code VARCHAR(255))") 52 | 53 | # =========== Show Table =========== 54 | # my_cursor.execute("SELECT * FROM customers") 55 | # print(my_cursor.description) 56 | # OR 57 | # for t in my_cursor.description: 58 | # print(t) 59 | 60 | 61 | def clear_fields(): 62 | """Clears the text fields""" 63 | first_name_box.delete(0, END) 64 | last_name_box.delete(0, END) 65 | address1_box.delete(0, END) 66 | address2_box.delete(0, END) 67 | city_box.delete(0, END) 68 | state_box.delete(0, END) 69 | zip_code_box.delete(0, END) 70 | country_box.delete(0, END) 71 | phone_box.delete(0, END) 72 | email_box.delete(0, END) 73 | username_box.delete(0, END) 74 | payment_method_box.delete(0, END) 75 | discount_code_box.delete(0, END) 76 | price_paid_box.delete(0, END) 77 | 78 | 79 | # Submit Customer To Database 80 | def add_customer(): 81 | sql_command = "INSERT INTO customers (first_name, last_name, zip_code, price_paid, email, address_1, address_2, " \ 82 | "city, state, country, phone, payment_method, discount_code) VALUES (%s, %s, %s, %s, %s, %s, %s, " \ 83 | "%s, %s, %s, %s, %s, %s) " 84 | values = (first_name_box.get(), last_name_box.get(), zip_code_box.get(), price_paid_box.get(), email_box.get(), 85 | address1_box.get(), address2_box.get(), city_box.get(), state_box.get(), country_box.get(), 86 | phone_box.get(), payment_method_box.get(), discount_code_box.get()) 87 | my_cursor.execute(sql_command, values) 88 | 89 | # Commit the changes to the database 90 | my_db.commit() 91 | # Clear the fields 92 | clear_fields() 93 | 94 | 95 | def list_customers(): 96 | def write_to_csv(res): 97 | with open('customers.csv', 'a', newline='') as f: 98 | w = csv.writer(f, dialect='excel') 99 | for record in res: 100 | w.writerow(record) 101 | 102 | global index 103 | list_customer_query = Tk() 104 | list_customer_query.title("List of All Customers") 105 | list_customer_query.geometry('400x600') 106 | 107 | my_cursor.execute("select * from customers ") 108 | res = my_cursor.fetchall() 109 | 110 | for index, i in enumerate(res): 111 | num = 0 112 | for j in i: 113 | list_label = Label(list_customer_query, text=j) 114 | list_label.grid(row=index, column=num) 115 | num += 1 116 | 117 | csv_button = Button(list_customer_query, text="Save to Excel", command=lambda: write_to_csv(res)) 118 | csv_button.grid(row=index+1, column=0, padx=10) 119 | csv_open_button = Button(list_customer_query, text="Open Excel", command=lambda: write_to_csv(res)) 120 | csv_open_button.grid(row=index+2, column=0, padx=10) 121 | 122 | 123 | # =========== Create Main Form To Enter Customer Form =========== 124 | title_label = Label(root, text="Codemy Customer Database", font=("Helvetica", 16)) 125 | title_label.grid(row=0, column=0, columnspan=2, padx=15) 126 | first_name_label = Label(root, text="First Name").grid(row=1, column=0, sticky=W, padx=10) 127 | last_name_label = Label(root, text="Last Name").grid(row=2, column=0, sticky=W, padx=10) 128 | address1_label = Label(root, text="Address 1").grid(row=3, column=0, sticky=W, padx=10) 129 | address2_label = Label(root, text="Address 2").grid(row=4, column=0, sticky=W, padx=10) 130 | city_label = Label(root, text="City").grid(row=5, column=0, sticky=W, padx=10) 131 | state_label = Label(root, text="Sate").grid(row=6, column=0, sticky=W, padx=10) 132 | zip_code_label = Label(root, text="Zip Code").grid(row=7, column=0, sticky=W, padx=10) 133 | country_label = Label(root, text="Country").grid(row=8, column=0, sticky=W, padx=10) 134 | phone_label = Label(root, text="Phone Number").grid(row=9, column=0, sticky=W, padx=10) 135 | email_label = Label(root, text="Email").grid(row=10, column=0, sticky=W, padx=10) 136 | username_label = Label(root, text="Username").grid(row=11, column=0, sticky=W, padx=10) 137 | payment_method_label = Label(root, text="Payment Method").grid(row=12, column=0, sticky=W, padx=10) 138 | discount_code_label = Label(root, text="Discount Code").grid(row=13, column=0, sticky=W, padx=10) 139 | price_paid_label = Label(root, text="Price Paid").grid(row=14, column=0, sticky=W, padx=10) 140 | 141 | # =========== Create Entry Box =========== 142 | first_name_box = Entry(root) 143 | first_name_box.grid(row=1, column=1, pady=3) 144 | last_name_box = Entry(root) 145 | last_name_box.grid(row=2, column=1, pady=3) 146 | address1_box = Entry(root) 147 | address1_box.grid(row=3, column=1, pady=3) 148 | address2_box = Entry(root) 149 | address2_box.grid(row=4, column=1, pady=3) 150 | city_box = Entry(root) 151 | city_box.grid(row=5, column=1, pady=3) 152 | state_box = Entry(root) 153 | state_box.grid(row=6, column=1, pady=3) 154 | zip_code_box = Entry(root) 155 | zip_code_box.grid(row=7, column=1, pady=3) 156 | country_box = Entry(root) 157 | country_box.grid(row=8, column=1, pady=3) 158 | phone_box = Entry(root) 159 | phone_box.grid(row=9, column=1, pady=3) 160 | email_box = Entry(root) 161 | email_box.grid(row=10, column=1, pady=3) 162 | username_box = Entry(root) 163 | username_box.grid(row=11, column=1, pady=3) 164 | payment_method_box = Entry(root) 165 | payment_method_box.grid(row=12, column=1, pady=3) 166 | discount_code_box = Entry(root) 167 | discount_code_box.grid(row=13, column=1, pady=3) 168 | price_paid_box = Entry(root) 169 | price_paid_box.grid(row=14, column=1, pady=4) 170 | 171 | # =========== Create Buttons =========== 172 | add_customer_button = Button(root, text="Add Customer", fg="blue", padx=20, command=add_customer) 173 | add_customer_button.grid(row=15, column=0, pady=5) 174 | clear_fields_button = Button(root, text="Clear Fields", fg="red", padx=28, command=clear_fields) 175 | clear_fields_button.grid(row=15, column=1, pady=5) 176 | # List customers button 177 | list_customers_button = Button(root, text="List Customers", padx=19, command=list_customers) 178 | list_customers_button.grid(row=16, column=0, padx=10) 179 | 180 | root.mainloop() 181 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/database-1.py: -------------------------------------------------------------------------------- 1 | # Start: Tuesday, July 14, 2020, 3:02 PM 2 | # Address Book Application 3 | # Videos 19-23 4 | # EightSoft Academy 5 | 6 | from tkinter import * 7 | from PIL import ImageTk, Image 8 | import sqlite3 9 | 10 | root = Tk() 11 | root.title("Database 1") 12 | root.iconbitmap('examples/photos/icon.ico') 13 | root.geometry("325x400") 14 | # root.configure(bg="black") 15 | 16 | # Create table 17 | ''' 18 | c.execute("""CREATE TABLE addresses ( 19 | first_name text, 20 | last_name text, 21 | address text, 22 | city text, 23 | state text, 24 | zip_code int 25 | )""") 26 | ''' 27 | 28 | 29 | def delete(): 30 | """Function to delete a record""" 31 | conn = sqlite3.connect('address_book.db') 32 | c = conn.cursor() 33 | # Delete a record 34 | c.execute("DELETE from addresses WHERE oid="+delete_box.get()) 35 | 36 | delete_box.delete(0, END) 37 | # Commit changes 38 | conn.commit() 39 | # Close connection 40 | conn.close() 41 | 42 | 43 | def save_edit(): 44 | conn = sqlite3.connect('address_book.db') 45 | c = conn.cursor() 46 | 47 | c.execute("""UPDATE addresses SET 48 | first_name = :f_name, 49 | last_name = :l_name, 50 | address = :address, 51 | city = :city, 52 | state = :state, 53 | zip_code = :zip_code 54 | 55 | WHERE oid = :oid""", 56 | { 57 | 'f_name': f_name_editor.get(), 58 | 'l_name': l_name_editor.get(), 59 | 'address': address_editor.get(), 60 | 'city': city_editor.get(), 61 | 'state': state_editor.get(), 62 | 'zip_code': zip_code_editor.get(), 63 | 'oid': delete_box.get() 64 | } 65 | ) 66 | conn.commit() 67 | conn.close() 68 | 69 | editor.destroy() 70 | 71 | 72 | def edit(): 73 | """Edits the record in db""" 74 | global editor 75 | editor = Tk() 76 | editor.title("Update the record") 77 | editor.iconbitmap('examples/photos/icon.ico') 78 | editor.geometry("325x300") 79 | 80 | # Create Globals 81 | global f_name_editor 82 | global l_name_editor 83 | global address_editor 84 | global city_editor 85 | global state_editor 86 | global zip_code_editor 87 | 88 | # Create a text boxes 89 | f_name_editor = Entry(editor, width=30) 90 | f_name_editor.grid(row=0, column=1, padx=20, pady=4) 91 | l_name_editor = Entry(editor, width=30) 92 | l_name_editor.grid(row=1, column=1, padx=20, pady=4) 93 | address_editor = Entry(editor, width=30) 94 | address_editor.grid(row=2, column=1, padx=20, pady=4) 95 | city_editor = Entry(editor, width=30) 96 | city_editor.grid(row=3, column=1, padx=20, pady=4) 97 | state_editor = Entry(editor, width=30) 98 | state_editor.grid(row=4, column=1, padx=20, pady=4) 99 | zip_code_editor = Entry(editor, width=30) 100 | zip_code_editor.grid(row=5, column=1, padx=20, pady=4) 101 | 102 | # Create Text Box Labels 103 | f_name_editor_label = Label(editor, text="First Name") 104 | f_name_editor_label.grid(row=0, column=0, padx=20) 105 | l_name_editor_label = Label(editor, text="Last Name") 106 | l_name_editor_label.grid(row=1, column=0, padx=20) 107 | address_editor_label = Label(editor, text="Address") 108 | address_editor_label.grid(row=2, column=0, padx=20) 109 | city_editor_label = Label(editor, text="City") 110 | city_editor_label.grid(row=3, column=0, padx=20) 111 | state_editor_label = Label(editor, text="State") 112 | state_editor_label.grid(row=4, column=0, padx=20) 113 | zip_code_editor_label = Label(editor, text="Zip Code") 114 | zip_code_editor_label.grid(row=5, column=0, padx=20) 115 | 116 | save_btn = Button(editor, text="Save Record", command=save_edit, bg="grey") 117 | save_btn.grid(row=6, column=0, columnspan=2, pady=10, padx=10, ipadx=106) 118 | 119 | conn = sqlite3.connect('address_book.db') 120 | c = conn.cursor() 121 | 122 | record_id = delete_box.get() 123 | c.execute("SELECT * FROM addresses WHERE OID = " + record_id) 124 | records = c.fetchall() 125 | 126 | # Loop thru results 127 | for record in records: 128 | f_name_editor.insert(0, record[0]) 129 | l_name_editor.insert(0, record[1]) 130 | address_editor.insert(0, record[2]) 131 | city_editor.insert(0, record[3]) 132 | state_editor.insert(0, record[4]) 133 | zip_code_editor.insert(0, record[5]) 134 | 135 | 136 | def submit(): 137 | """Adds the record to the database""" 138 | # Create a db or connect to one 139 | conn = sqlite3.connect('address_book.db') 140 | # Create cursor 141 | c = conn.cursor() 142 | # Insert into table 143 | c.execute("INSERT INTO addresses VALUES (:f_name, :l_name, :address, :city, :state, :zip_code )", 144 | { 145 | 'f_name': f_name.get(), 146 | 'l_name': l_name.get(), 147 | 'address': address.get(), 148 | 'city': city.get(), 149 | 'state': state.get(), 150 | 'zip_code': state.get(), 151 | } 152 | ) 153 | # Commit changes 154 | conn.commit() 155 | # Close connection 156 | conn.close() 157 | 158 | f_name.delete(0, END) 159 | l_name.delete(0, END) 160 | address.delete(0, END) 161 | city.delete(0, END) 162 | state.delete(0, END) 163 | zip_code.delete(0, END) 164 | 165 | 166 | def query(): 167 | """Reads the records from db""" 168 | conn = sqlite3.connect('address_book.db') 169 | c = conn.cursor() 170 | 171 | # query the database 172 | c.execute("SELECT *, OID FROM addresses") 173 | records = c.fetchall() 174 | # print(records) # printing in terminal 175 | 176 | # Loop through results 177 | print_records = '' 178 | for record_info in records: 179 | print_records += str(record_info[0]) + "/" + str(record_info[1]) + "/" + str(record_info[2]) + "/" + str( 180 | record_info[3]) + "/" + str(record_info[4]) + "/" + str(record_info[5]) + "/" + str(record_info[6]) + "\n" 181 | 182 | query_label = Label(root, text=print_records) 183 | query_label.grid(row=12, column=0, columnspan=2, ) 184 | 185 | conn.commit() 186 | conn.close() 187 | 188 | 189 | # Create a text boxes 190 | f_name = Entry(root, width=30) 191 | f_name.grid(row=0, column=1, padx=20, pady=4) 192 | l_name = Entry(root, width=30) 193 | l_name.grid(row=1, column=1, padx=20, pady=4) 194 | address = Entry(root, width=30) 195 | address.grid(row=2, column=1, padx=20, pady=4) 196 | city = Entry(root, width=30) 197 | city.grid(row=3, column=1, padx=20, pady=4) 198 | state = Entry(root, width=30) 199 | state.grid(row=4, column=1, padx=20, pady=4) 200 | zip_code = Entry(root, width=30) 201 | zip_code.grid(row=5, column=1, padx=20, pady=4) 202 | delete_box = Entry(root, width=30) 203 | delete_box.grid(row=9, column=1) 204 | 205 | # Create Text Box Labels 206 | f_name_label = Label(root, text="First Name") 207 | f_name_label.grid(row=0, column=0, padx=20) 208 | l_name_label = Label(root, text="Last Name") 209 | l_name_label.grid(row=1, column=0, padx=20) 210 | address_label = Label(root, text="Address") 211 | address_label.grid(row=2, column=0, padx=20) 212 | city_label = Label(root, text="City") 213 | city_label.grid(row=3, column=0, padx=20) 214 | state_label = Label(root, text="State") 215 | state_label.grid(row=4, column=0, padx=20) 216 | zip_code_label = Label(root, text="Zip Code") 217 | zip_code_label.grid(row=5, column=0, padx=20) 218 | delete_box_label = Label(root, text="Select ID: ") 219 | delete_box_label.grid(row=9, column=0, padx=10) 220 | 221 | # Create Submit Button 222 | submit_btn = Button(root, text="Add record", command=submit, fg="red") 223 | submit_btn.grid(row=6, column=0, columnspan=2, padx=10, ipadx=109) 224 | 225 | # Create a Query Button 226 | query_btn = Button(root, text="Show Records", command=query, fg="red") 227 | query_btn.grid(row=7, column=0, columnspan=2, pady=7, padx=10, ipadx=100) 228 | 229 | # Create a Delete Button 230 | delete_btn = Button(root, text="Delete Record", command=delete, bg="grey") 231 | delete_btn.grid(row=10, column=0, columnspan=2, pady=8, padx=10, ipadx=101) 232 | 233 | # Create an Update button 234 | edit_btn = Button(root, text="Update Record", command=edit, bg="grey") 235 | edit_btn.grid(row=11, column=0, columnspan=2, padx=10, ipadx=98) 236 | 237 | root.mainloop() 238 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/dropdown-2.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | 3 | OptionList = [ 4 | "Aries", 5 | "Taurus", 6 | "Gemini", 7 | "Cancer" 8 | ] 9 | 10 | app = tk.Tk() 11 | 12 | app.geometry('300x300') 13 | 14 | variable = tk.StringVar(app) 15 | variable.set(OptionList[0]) 16 | 17 | opt = tk.OptionMenu(app, variable, *OptionList) 18 | opt.config(width=90, font=('Helvetica', 12)) 19 | opt.pack(side="top") 20 | 21 | 22 | labelTest = tk.Label(text="", font=('Helvetica', 12), fg='red') 23 | labelTest.pack(side="top") 24 | 25 | def callback(*args): 26 | labelTest.configure(text="The selected item is {}".format(variable.get())) 27 | 28 | variable.trace("w", callback) 29 | 30 | app.mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/dropdown.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from PIL import ImageTk, Image 3 | 4 | root = Tk() 5 | root.title("DropDown") 6 | root.geometry("400x400") 7 | 8 | # Drop Down Boxes 9 | 10 | clicked = StringVar() 11 | clicked.set("1") 12 | 13 | OPTIONS = [ 14 | "1", "2", "3", "4", "5", 15 | ] 16 | 17 | def show(): 18 | Label(root, text=clicked.get()).pack() 19 | 20 | drop = OptionMenu(root, clicked, *OPTIONS).pack() 21 | my_button = Button(root, text="Show selection", command=show).pack() 22 | 23 | root.mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/entry-height.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | 3 | root = Tk() 4 | root.geometry('400x400') 5 | 6 | 7 | def my_click(): 8 | hello = "Hello " + e.get() 9 | label = Label(root, text=hello) 10 | label.pack(pady=10) 11 | 12 | 13 | e = Entry(root, width=30).pack(pady=30, ipady=10, ipadx=50) 14 | 15 | btn = Button(root, text="Enter your name", command=my_click) 16 | btn.pack(pady=10) 17 | 18 | root.mainloop() 19 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/entry.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | 3 | root = Tk() 4 | 5 | e = Entry(root, width=50) 6 | e.pack() 7 | e.insert(0, "Enter the name: ") 8 | 9 | def myClick(): 10 | hello = "Hello " + e.get() 11 | myLabel = Label(root, text=hello) 12 | myLabel.pack() 13 | 14 | myButton=Button(root, text="Click me!", command=myClick) 15 | myButton.pack() 16 | 17 | root.mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/file-1.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from tkinter import filedialog 3 | import os 4 | 5 | root = Tk() 6 | root.geometry("600x400") 7 | 8 | 9 | def open_program(): 10 | my_program = filedialog.askopenfilename() 11 | my_label.config(text=my_program) 12 | # Open the program 13 | os.system('"%s"' % my_program) 14 | 15 | 16 | def open_notepad(): 17 | notepad = 'c:/Windows/system32/notepad.exe' 18 | os.system('"%s"' % notepad) 19 | 20 | 21 | my_button = Button(root, text="Open Program", command=open_program) 22 | my_button.pack(pady=20) 23 | 24 | my_button2 = Button(root, text="Open Notepad", command=open_notepad) 25 | my_button2.pack(pady=20) 26 | 27 | my_label = Label(root, text="") 28 | my_label.pack(pady=20) 29 | 30 | root.mainloop() 31 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/file-2.py: -------------------------------------------------------------------------------- 1 | # Read more at: https://pythonprogramming.altervista.org/tkinter-show-the-files-in-the-folder-in-a-listbox/ 2 | # EightSoft Academy 3 | # You must be in the same directory in which you have include the project 4 | 5 | import tkinter as tk 6 | import os 7 | 8 | # WINDOW CREATION 9 | win = tk.Tk() 10 | geo = win.geometry 11 | geo("400x400+400+400") 12 | win['bg'] = 'orange' 13 | 14 | # get the list of files 15 | f_list = os.listdir() 16 | 17 | l_box = tk.Listbox(win) 18 | l_box.pack() 19 | 20 | # THE ITEMS INSERTED WITH A LOOP 21 | for item in f_list: 22 | l_box.insert(tk.END, item) 23 | 24 | def show_content(event): 25 | x = l_box.curselection()[0] 26 | file = l_box.get(x) 27 | with open(file) as file: 28 | file = file.read() 29 | text.delete('1.0', tk.END) 30 | text.insert(tk.END, file) 31 | 32 | 33 | text = tk.Text(win, bg='cyan') 34 | text.pack() 35 | 36 | l_box.bind("<>", show_content) 37 | 38 | win.mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/file-3_with_audio_reader.py: -------------------------------------------------------------------------------- 1 | 2 | # the whole code with the double click 3 | # to open files in the listbox 4 | 5 | 6 | import tkinter as tk 7 | import os 8 | from win32com.client import Dispatch 9 | 10 | 11 | s = Dispatch("SAPI.SpVoice") 12 | 13 | # WINDOW CREATION 14 | win = tk.Tk() 15 | geo = win.geometry 16 | geo("400x400+400+400") 17 | win['bg'] = 'orange' 18 | 19 | # get the list of files 20 | flist = os.listdir() 21 | 22 | lbox = tk.Listbox(win) 23 | lbox.pack() 24 | 25 | # THE ITEMS INSERTED WITH A LOOP 26 | for item in flist: 27 | lbox.insert(tk.END, item) 28 | 29 | 30 | def showcontent(event, audio=0): 31 | x = lbox.curselection()[0] 32 | file = lbox.get(x) 33 | with open(file, 'r', encoding='utf-8') as file: 34 | file = file.read() 35 | text.delete('1.0', tk.END) 36 | text.insert(tk.END, file) 37 | 38 | 39 | def audio(): 40 | s.Speak(text.get('1.0', tk.INSERT)) 41 | 42 | 43 | def opensystem(event): 44 | x = lbox.curselection()[0] 45 | os.system(lbox.get(x)) 46 | 47 | 48 | button = tk.Button(win, text="audio") 49 | button['command'] = audio 50 | button.pack() 51 | 52 | text = tk.Text(win, bg='cyan') 53 | text.pack() 54 | # BINDING OF LISTBOX lbox 55 | lbox.bind("<>", showcontent) 56 | lbox.bind("", opensystem) 57 | # BUTTON 58 | 59 | win.mainloop() 60 | 1 61 | 2 62 | 3 63 | 4 64 | 5 65 | 6 66 | 7 67 | 8 68 | 9 69 | 10 70 | 11 71 | 12 72 | 13 73 | 14 74 | 15 75 | 16 76 | 17 77 | 18 78 | 19 79 | 20 80 | 21 81 | 22 82 | 23 83 | 24 84 | 25 85 | 26 86 | 27 87 | 28 88 | 29 89 | 30 90 | 31 91 | 32 92 | 33 93 | 34 94 | 35 95 | 36 96 | 37 97 | 38 98 | 39 99 | 40 100 | 41 101 | 42 102 | 43 103 | 44 104 | 45 105 | 46 106 | 47 107 | 48 108 | 49 109 | 50 110 | 51 111 | 52 112 | 53 113 | 54 114 | 55 115 | 56 116 | 57 117 | 58 118 | # the whole code with the double click 119 | # to open files in the listbox 120 | 121 | 122 | import tkinter as tk 123 | import os 124 | from win32com.client import Dispatch 125 | 126 | 127 | s = Dispatch("SAPI.SpVoice") 128 | 129 | # WINDOW CREATION 130 | win = tk.Tk() 131 | geo = win.geometry 132 | geo("400x400+400+400") 133 | win['bg'] = 'orange' 134 | 135 | # get the list of files 136 | flist = os.listdir() 137 | 138 | lbox = tk.Listbox(win) 139 | lbox.pack() 140 | 141 | # THE ITEMS INSERTED WITH A LOOP 142 | for item in flist: 143 | lbox.insert(tk.END, item) 144 | 145 | 146 | def showcontent(event, audio=0): 147 | x = lbox.curselection()[0] 148 | file = lbox.get(x) 149 | with open(file, 'r', encoding='utf-8') as file: 150 | file = file.read() 151 | text.delete('1.0', tk.END) 152 | text.insert(tk.END, file) 153 | 154 | 155 | def audio(): 156 | s.Speak(text.get('1.0', tk.INSERT)) 157 | 158 | 159 | def opensystem(event): 160 | x = lbox.curselection()[0] 161 | os.system(lbox.get(x)) 162 | 163 | 164 | button = tk.Button(win, text="audio") 165 | button['command'] = audio 166 | button.pack() 167 | 168 | text = tk.Text(win, bg='cyan') 169 | text.pack() 170 | # BINDING OF LISTBOX lbox 171 | lbox.bind("<>", showcontent) 172 | lbox.bind("", opensystem) 173 | # BUTTON 174 | 175 | win.mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/file.py: -------------------------------------------------------------------------------- 1 | # Open Files Dialog Box 2 | # By RΨST-4M 🚀 3 | # EightSoft Academy 4 | 5 | from tkinter import * 6 | from tkinter import filedialog 7 | from PIL import ImageTk, Image 8 | 9 | root = Tk() 10 | 11 | def open(): 12 | global my_image # we always need global to open an image 13 | root.filename = filedialog.askopenfilename(initialdir="examples/photos", title="Select a File", filetypes=(("png files", "*.png"), ("jpg files", "*.jpg"))) 14 | my_label = Label(root, text=root.filename).pack() # it returns the location of file as string 15 | 16 | my_image = ImageTk.PhotoImage(Image.open(root.filename)) 17 | my_image_label = Label(root, image=my_image).pack() 18 | 19 | 20 | my_btn = Button(root, text="Open file", command=open).pack() 21 | 22 | mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/frames.py: -------------------------------------------------------------------------------- 1 | # July 16, 2020 12:15 PM 2 | # Frames 3 | # By RΨST-4M 🚀 4 | # EightSoft Academy 5 | 6 | from tkinter import * 7 | 8 | root = Tk() 9 | root.title("Frames") 10 | root.iconbitmap('examples/photos/icon.ico') 11 | 12 | frame = LabelFrame(root, padx=5, pady=5) # inside # we can add -> text="My Frame", 13 | frame.pack(padx=10, pady=10) # outside 14 | 15 | button = Button(frame, text="Click me!").pack() 16 | 17 | root.mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/grid.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | 3 | window = Tk() 4 | 5 | # to rename the title of the window window.title("GUI") 6 | window.title("GUI") 7 | # pack is used to show the object in the window 8 | 9 | label = Label(window, text="Hello World!").grid(row=0, column=0) 10 | label2 = Label(window, text=" Hello World!").grid(row=1, column=1) 11 | 12 | # for running the program 13 | window.mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/howto.py: -------------------------------------------------------------------------------- 1 | # PART1: the best way to organize the application 2 | import tkinter as tk 3 | 4 | class MainApplication(tk.Frame): 5 | def __init__(self, parent, *args, **kwargs): 6 | tk.Frame.__init__(self, parent, *args, **kwargs) 7 | self.parent = parent 8 | 9 | # 10 | 11 | if __name__ == "__main__": 12 | root = tk.Tk() 13 | MainApplication(root).pack(side="top", fill="both", expand=True) 14 | root.mainloop() 15 | 16 | # PART2: Current working directory 17 | import os 18 | def rcpath(rel_path): 19 | return os.path.join(os.getcwd(), rel_path) 20 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/image_viewer_app.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from PIL import ImageTk, Image 3 | 4 | # Main Window 5 | root = Tk() 6 | root.title("Image Viewer") 7 | root.iconbitmap('photos/icon.ico') 8 | 9 | # Images location 10 | img1 = ImageTk.PhotoImage(Image.open("photos/python.png")) 11 | img2 = ImageTk.PhotoImage(Image.open("photos/python-file.png")) 12 | img3 = ImageTk.PhotoImage(Image.open("photos/python-file-1.png")) 13 | img_list = [img1, img2, img3] 14 | 15 | # Labels & Status bar in footer 16 | my_label = Label(image=img1) 17 | status = Label(root, text="Image 1 of " + str(len(img_list)), relief=SUNKEN, anchor=E, 18 | font=("times new roman", 10)) 19 | 20 | # Functions for << and >> 21 | def forward(img_num): 22 | global my_label 23 | global button_forward 24 | global button_back 25 | 26 | my_label.grid_forget() 27 | my_label = Label(image=img_list[img_num-1]) 28 | 29 | button_forward = Button(root, text=">>", command=lambda: forward(img_num+1), 30 | font=("times new roman", 15), bg="black", fg="white") 31 | 32 | button_back = Button(root, text="<<",command=lambda: back(img_num-1), 33 | font=("times new roman", 15), bg="black", fg="white") 34 | 35 | # cheaking for the last image 36 | if img_num == len(img_list): 37 | button_forward = Button(root, text=">>", state=DISABLED) 38 | 39 | # footer - status bar 40 | status = Label(root, text="Image "+str(img_num) + " of " + str(len(img_list)), relief=SUNKEN, anchor=E, 41 | font=("times new roman", 10)) 42 | status.grid(row=2, column=0, columnspan=3, sticky=W + E) 43 | 44 | my_label.grid(row=0, column=0, columnspan=3) 45 | button_back.grid(row=1, column=0) 46 | button_forward.grid(row=1, column=2) 47 | 48 | 49 | def back(img_num): 50 | global my_label 51 | global button_forward 52 | global button_back 53 | global status 54 | 55 | my_label.grid_forget() 56 | my_label = Label(image=img_list[img_num-1]) 57 | 58 | button_forward = Button(root, text=">>", command=lambda: forward(img_num+1), 59 | font=("times new roman", 15), bg="black", fg="white") 60 | button_back = Button(root, text="<<", command=lambda: back(img_num-1), 61 | font=("times new roman", 15), bg="black", fg="white") 62 | 63 | # cheaking for the last image 64 | if img_num == 1: 65 | button_back = Button(root, text="<<", state=DISABLED) 66 | 67 | # footer - status bar 68 | status = Label(root, text="Image "+str(img_num) + " of " + str(len(img_list)), relief=SUNKEN, anchor=E, 69 | font=("times new roman", 10)) 70 | status.grid(row=2, column=0, columnspan=3, sticky=W + E) 71 | 72 | my_label.grid(row=0, column=0, columnspan=3) 73 | button_back.grid(row=1, column=0) 74 | button_forward.grid(row=1, column=2) 75 | 76 | 77 | # Buttons 78 | button_quit = Button(root, text='Exit Program', 79 | font=("times new roman", 15), command=root.quit, bg="black", fg="white") 80 | button_back = Button(root, text="<<", command=back, state = DISABLED, 81 | font=("times new roman", 15), bg="black", fg="white") 82 | button_forward = Button(root, text=">>", command=lambda: forward(2), 83 | font=("times new roman", 15), bg="black", fg="white") 84 | 85 | 86 | # Showing on Window 87 | my_label.grid(row=0, column=0, columnspan=3) 88 | button_back.grid(row=1, column=0) 89 | button_quit.grid(row=1, column=1) 90 | button_forward.grid(row=1, column=2, pady=10) 91 | status.grid(row=2, column=0, columnspan=3, sticky=W+E) 92 | 93 | # sticky is a line like --------------------------- 94 | # anchor is the location 95 | 96 | root.mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/images.py: -------------------------------------------------------------------------------- 1 | # Images, icons, and exit button 2 | 3 | from tkinter import * 4 | from PIL import Image, ImageTk 5 | 6 | root = Tk() 7 | root.title('EightSoft Academy') 8 | 9 | # For changing the icon 10 | root.iconbitmap('examples/photos/icon.ico') 11 | 12 | # images 13 | my_img = ImageTk.PhotoImage(Image.open('examples/photos/image.jpg')) 14 | my_label = Label(image=my_img) 15 | my_label.pack() 16 | 17 | # Exit Button 18 | button_quit = Button(root, text="Exit program!", command=root.quit) 19 | button_quit.pack() 20 | 21 | root.mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/is_num.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | 3 | root = Tk() 4 | root.geometry("400x400") 5 | 6 | 7 | def number(): 8 | try: 9 | float(my_box.get()) 10 | answer.config(text="That is a number!") 11 | 12 | except ValueError: 13 | answer.config(text="That is NOT a number!") 14 | 15 | 16 | my_label = Label(root, text="Enter a Number") 17 | my_label.pack(pady=20) 18 | 19 | my_box = Entry(root) 20 | my_box.pack(pady=10) 21 | 22 | my_button = Button(root, text="Enter a Number", command=number) 23 | my_button.pack(pady=5) 24 | 25 | answer = Label(root, text='') 26 | answer.pack(pady=20) 27 | 28 | root.mainloop() 29 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/list_box.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | 3 | # --- functions --- 4 | 5 | def on_button(): 6 | for i, var in enumerate(o_vars): 7 | print('OptionMenu {}: {}'.format(i, var.get())) 8 | print() 9 | 10 | print('ListBox:', l.curselection()) 11 | for i in l.curselection(): 12 | print('option:', OPTIONS[i]) 13 | print() 14 | 15 | print('ChecboxBox:') 16 | for i, var in enumerate(cb_vars): 17 | if var.get(): 18 | print('option:', OPTIONS[i]) 19 | 20 | # --- main --- 21 | 22 | OPTIONS = ["Script 1","Script 2","Script 3","Script 4","Script 5"] 23 | 24 | root = tk.Tk() 25 | 26 | # --- OptionMenu --- 27 | 28 | tk.Label(root, text='OptionMenus', bg='#aaa').pack(fill='x') 29 | 30 | o_vars = [] 31 | 32 | for i in range(3): 33 | var = tk.StringVar(value='- select -') 34 | o_vars.append(var) 35 | o = tk.OptionMenu(root, var, *OPTIONS) 36 | o.pack() 37 | 38 | # --- Listbox --- 39 | 40 | tk.Label(root, text='Listbox', bg='#aaa').pack(fill='x') 41 | 42 | l = tk.Listbox(root, selectmode='multiple') 43 | l.pack() 44 | l.insert('end', *OPTIONS) 45 | 46 | # --- Checkbuttons --- 47 | 48 | tk.Label(root, text='Checkbuttons', bg='#aaa').pack(fill='x') 49 | 50 | cb_vars = [] 51 | for x in OPTIONS: 52 | var = tk.BooleanVar(value=False) 53 | cb_vars.append(var) 54 | c = tk.Checkbutton(root, text=x, variable=var) 55 | c.pack() 56 | 57 | # --- others --- 58 | 59 | b = tk.Button(root, text='OK', command=on_button) 60 | b.pack(fill='x') 61 | 62 | root.mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/loading_page.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | import time 3 | from PIL import Image, ImageTk 4 | 5 | 6 | class Splash(tk.Toplevel): 7 | def __init__(self, parent): 8 | tk.Toplevel.__init__(self, parent) 9 | self.title("Xabar") 10 | self.geometry("400x400+480+200") 11 | tk.Label(self, text="Kuting, ma'lumotlar bazasi yuklanmoqda.").pack() 12 | 13 | 14 | ## required to make window show before the program gets to the mainloop 15 | self.update() 16 | 17 | class App(tk.Tk): 18 | def __init__(self): 19 | tk.Tk.__init__(self) 20 | self.withdraw() 21 | splash = Splash(self) 22 | 23 | ## setup stuff goes here 24 | self.title("Main Window") 25 | ## simulate a delay while loading 26 | time.sleep(6) 27 | 28 | ## finished loading so destroy splash 29 | splash.destroy() 30 | 31 | ## show window again 32 | self.deiconify() 33 | 34 | if __name__ == "__main__": 35 | app = App() 36 | app.mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/menu_bar.py: -------------------------------------------------------------------------------- 1 | # Tuesday, July 19, 2020 2 | # By RΨST-4M 🚀 3 | # EightSoft Academy 4 | 5 | from tkinter import * 6 | from tkinter import messagebox 7 | 8 | root = Tk() 9 | root.title("Menu Bar") 10 | root.iconbitmap('examples/photos/icon.ico') 11 | root.geometry("400x400") 12 | 13 | # Crate a Menu 14 | my_menu = Menu(root) 15 | root.config(menu=my_menu) 16 | 17 | 18 | # Create a functions for commands 19 | def command_new(): 20 | """When you press File->New ... the following function code will work""" 21 | Label(root, text="You Clicked New ...").pack() 22 | 23 | 24 | def command_cut(): 25 | Label(root, text="Awesome, it is working!").pack() 26 | 27 | 28 | def question(): 29 | response = messagebox.askquestion("Question", "Do you liked Menu Bars?") 30 | if response == "yes": 31 | Label(root, text="Ugh!!!").pack() 32 | else: 33 | Label(root, text="Sorry ...").pack() 34 | 35 | 36 | def command_copy(): 37 | Button(root, text="Popup", command=question).pack() 38 | 39 | 40 | # Create a Menu Item "File" 41 | file_menu = Menu(my_menu, tearoff=False) 42 | my_menu.add_cascade(label="File", menu=file_menu) 43 | file_menu.add_command(label="New", command=command_new) 44 | file_menu.add_separator() 45 | file_menu.add_command(label="Exit", command=root.quit) 46 | 47 | # Create a Menu Item "Edit" 48 | edit_menu = Menu(my_menu, tearoff=False) 49 | my_menu.add_cascade(label="Ask", menu=edit_menu) 50 | edit_menu.add_command(label="Press me :)", command=command_cut) 51 | edit_menu.add_separator() 52 | edit_menu.add_command(label="Question", command=command_copy) 53 | 54 | 55 | # for running the program 56 | root.mainloop() 57 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/menu_bar_frame.py: -------------------------------------------------------------------------------- 1 | # Tuesday, July 19, 2020 2 | # By RΨST-4M 🚀 3 | # How to clear the screen after pressing the menu item? The answer is here! 4 | # Create a Frame widget for each menu item and also -> hide_all_frames() 5 | # EightSoft Academy 6 | 7 | from tkinter import * 8 | from tkinter import messagebox 9 | 10 | root = Tk() 11 | root.title("Menu Bar") 12 | root.iconbitmap('examples/photos/icon.ico') 13 | root.geometry("400x400") 14 | 15 | # Crate a Menu 16 | my_menu = Menu(root) 17 | root.config(menu=my_menu) 18 | 19 | 20 | # Create a functions for commands 21 | def command_file_new(): 22 | """When you press File->New ... the following function code will work""" 23 | hide_all_frames() 24 | file_new_frame.pack(fill="both", expand=1) 25 | Label(file_new_frame, text="it is just for checking New->File").pack() 26 | Button(file_new_frame, text="Test", command=testing).pack() 27 | 28 | 29 | def testing(): 30 | Label(file_new_frame, text="hello World").pack() 31 | 32 | 33 | def command_edit_cut(): 34 | hide_all_frames() 35 | edit_cut_frame.pack(fill="both", expand=1) 36 | Label(edit_cut_frame, text="it is just for checking Edit->Cut").pack() 37 | 38 | 39 | def command_copy(): 40 | Label(root, text="it is just for checking").pack() 41 | 42 | 43 | def hide_all_frames(): 44 | """Clears the screen after pressing the menu item""" 45 | for widget in file_new_frame.winfo_children(): 46 | widget.destroy() 47 | 48 | for widget in edit_cut_frame.winfo_children(): 49 | widget.destroy() 50 | 51 | file_new_frame.pack_forget() 52 | edit_cut_frame.pack_forget() 53 | 54 | 55 | # Create a Menu Item "File" 56 | file_menu = Menu(my_menu, tearoff=False) 57 | my_menu.add_cascade(label="File", menu=file_menu) 58 | file_menu.add_command(label="New", command=command_file_new) 59 | file_menu.add_separator() 60 | file_menu.add_command(label="Exit", command=root.quit) 61 | 62 | # Create a Menu Item "Edit" 63 | edit_menu = Menu(my_menu, tearoff=False) 64 | my_menu.add_cascade(label="Edit", menu=edit_menu) 65 | edit_menu.add_command(label="Cut", command=command_edit_cut) 66 | edit_menu.add_separator() 67 | edit_menu.add_command(label="Question", command=command_copy) 68 | 69 | # Create some frames 70 | file_new_frame = Frame(root, width=400, height=400, bg="red") 71 | edit_cut_frame = Frame(root, width=400, height=400, bg="blue") 72 | 73 | # for running the program 74 | root.mainloop() 75 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/menu_bar_oop.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | import sys 3 | from tkinter import messagebox 4 | from tkinter import ttk # Normal Tkinter.* widgets are not themed! 5 | from ttkthemes import ThemedStyle 6 | import os 7 | 8 | 9 | class MenuBar(tk.Menu): 10 | def __init__(self, parent): 11 | tk.Menu.__init__(self, parent) 12 | self.parent = parent 13 | 14 | teachers_menu = tk.Menu(self, tearoff=False) 15 | self.add_cascade(label="File", underline=0, menu=teachers_menu) 16 | teachers_menu.add_command(label="Press-1", underline=1, command=self.press1) 17 | 18 | groups_menu = tk.Menu(self, tearoff=False) 19 | self.add_cascade(label="New", underline=0, menu=groups_menu) 20 | groups_menu.add_command(label="Press-2", underline=1, command=self.press2) 21 | 22 | def press1(self): 23 | p1 = ttk.Label(self.parent, text="Press-1") 24 | p1.pack() 25 | 26 | def press2(self): 27 | p2 = ttk.Label(self.parent, text="Press-2") 28 | p2.pack() 29 | 30 | def quit(self): 31 | sys.exit(0) 32 | 33 | 34 | class App(tk.Tk): 35 | def __init__(self, parent): 36 | tk.Tk.__init__(self) 37 | self.parent = parent 38 | 39 | menubar = MenuBar(self) 40 | self.config(menu=menubar) 41 | 42 | 43 | if __name__ == "__main__": 44 | app = App(None) 45 | app.title("AutoRoad") 46 | app.geometry("400x400") 47 | style = ThemedStyle(app) 48 | style.set_theme("breeze") 49 | app.mainloop() 50 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/menu_bar_oop_frame-1.py: -------------------------------------------------------------------------------- 1 | from tkinter import * # from x import * is bad practice 2 | from tkinter import messagebox 3 | from tkinter import ttk # Normal Tkinter.* widgets are not themed! 4 | from ttkthemes import ThemedTk 5 | 6 | 7 | # http://tkinter.unpythonic.net/wiki/VerticalScrolledFrame 8 | 9 | # Scrollbar working with Sample App Class 10 | class VerticalScrolledFrame(Frame): 11 | """A pure Tkinter scrollable frame that actually works! 12 | * Use the 'interior' attribute to place widgets inside the scrollable frame 13 | * Construct and pack/place/grid normally 14 | * This frame only allows vertical scrolling 15 | 16 | """ 17 | 18 | def __init__(self, parent, *args, **kw): 19 | Frame.__init__(self, parent, *args, **kw) 20 | 21 | # create a canvas object and a vertical scrollbar for scrolling it 22 | vscrollbar = Scrollbar(self, orient=VERTICAL) 23 | vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE) 24 | canvas = Canvas(self, bd=0, highlightthickness=0, 25 | yscrollcommand=vscrollbar.set) 26 | canvas.pack(side=LEFT, fill=BOTH, expand=TRUE) 27 | vscrollbar.config(command=canvas.yview) 28 | 29 | # reset the view 30 | canvas.xview_moveto(0) 31 | canvas.yview_moveto(0) 32 | 33 | # create a frame inside the canvas which will be scrolled with it 34 | self.interior = interior = Frame(canvas) 35 | interior_id = canvas.create_window(0, 0, window=interior, 36 | anchor=NW) 37 | 38 | # track changes to the canvas and frame width and sync them, 39 | # also updating the scrollbar 40 | def _configure_interior(event): 41 | # update the scrollbars to match the size of the inner frame 42 | size = (interior.winfo_reqwidth(), interior.winfo_reqheight()) 43 | canvas.config(scrollregion="0 0 %s %s" % size) 44 | if interior.winfo_reqwidth() != canvas.winfo_width(): 45 | # update the canvas's width to fit the inner frame 46 | canvas.config(width=interior.winfo_reqwidth()) 47 | 48 | interior.bind('', _configure_interior) 49 | 50 | def _configure_canvas(event): 51 | if interior.winfo_reqwidth() != canvas.winfo_width(): 52 | # update the inner frame's width to fill the canvas 53 | canvas.itemconfigure(interior_id, width=canvas.winfo_width()) 54 | 55 | canvas.bind('', _configure_canvas) 56 | 57 | 58 | # For testing the VerticalScrolledFrame 59 | class SampleApp: 60 | def __init__(self, master): 61 | self.frame = VerticalScrolledFrame(master) 62 | self.frame.pack() 63 | self.label = ttk.Label(text="Shrink the window to activate the scrollbar.") 64 | self.label.pack() 65 | buttons = [] 66 | for i in range(100): 67 | buttons.append(ttk.Button(self.frame.interior, text="Button " + str(i))) 68 | buttons[-1].pack(pady=5) 69 | 70 | 71 | class Root: 72 | def __init__(self, master): 73 | frame = ttk.Frame(master) 74 | frame.pack() 75 | self.my_menu = Menu(master) 76 | master.config(menu=self.my_menu) 77 | 78 | # Create a Menu Item "File" 79 | self.file_menu = Menu(self.my_menu, tearoff=False) 80 | self.my_menu.add_cascade(label="File", menu=self.file_menu) 81 | self.file_menu.add_command(label="New", command=self.command_file_new) 82 | self.file_menu.add_separator() 83 | self.file_menu.add_command(label="Exit", command=master.quit) 84 | 85 | # Create a Menu Item "Edit" 86 | self.edit_menu = Menu(self.my_menu, tearoff=False) 87 | self.my_menu.add_cascade(label="Edit", menu=self.edit_menu) 88 | self.edit_menu.add_command(label="Cut", command=self.command_edit_cut) 89 | self.edit_menu.add_separator() 90 | self.edit_menu.add_command(label="Question", command=master.quit) 91 | 92 | # Create some frames 93 | self.file_new_frame = ttk.Frame(master, width=400, height=400) 94 | self.edit_cut_frame = ttk.Frame(master, width=400, height=400) 95 | 96 | def hide_all_frames(self): 97 | """Clears the screen after pressing the menu item""" 98 | for widget in self.file_new_frame.winfo_children(): 99 | widget.destroy() 100 | 101 | for widget in self.edit_cut_frame.winfo_children(): 102 | widget.destroy() 103 | 104 | self.file_new_frame.pack_forget() 105 | self.edit_cut_frame.pack_forget() 106 | 107 | # Create a functions for commands 108 | def command_file_new(self): 109 | """When you press File->New ... the following function code will work""" 110 | self.hide_all_frames() 111 | self.file_new_frame.pack(fill="both", expand=1) 112 | lab0 = ttk.Label(self.file_new_frame, text="it is just for checking New->File") 113 | btn0 = ttk.Button(self.file_new_frame, text="asdf", command=self.test) 114 | btn0.pack() 115 | lab0.pack() 116 | 117 | def test(self): 118 | ttk.Label(self.file_new_frame, text="asdf").pack() 119 | 120 | def command_edit_cut(self): 121 | self.hide_all_frames() 122 | self.edit_cut_frame.pack(fill="both", expand=1) 123 | lab1 = ttk.Label(self.edit_cut_frame, text="it is just for checking Edit->Cut") 124 | lab1.pack() 125 | 126 | 127 | def main(): 128 | root = ThemedTk(theme="breeze") 129 | root.geometry("500x500+250+100") 130 | app = Root(root) 131 | root.mainloop() 132 | 133 | 134 | if __name__ == '__main__': 135 | main() 136 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/menu_bar_oop_frame-2.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | import sys 3 | from tkinter import messagebox 4 | from tkinter import ttk # Normal Tkinter.* widgets are not themed! 5 | from ttkthemes import ThemedStyle 6 | import os 7 | 8 | 9 | class MenuBar(tk.Menu): 10 | def __init__(self, master): 11 | tk.Menu.__init__(self, master) 12 | 13 | self.frame = ttk.Frame(master) 14 | self.frame.pack() 15 | 16 | self.master = master 17 | 18 | # Create a Menu Item for Teachers 19 | teachers_menu = tk.Menu(self, tearoff=False) 20 | 21 | # Create a Menu Item for Groups 22 | groups_menu = tk.Menu(self, tearoff=False) 23 | 24 | # Create a Menu Item for Students 25 | students_menu = tk.Menu(self, tearoff=False) 26 | 27 | # Create a Menu Item for Info --EightSoft dev 28 | info_menu = tk.Menu(self, tearoff=False) 29 | 30 | # Add the cascades for menu bar 31 | self.add_cascade(label="Укитувчи", menu=teachers_menu) 32 | self.add_cascade(label="Гуруҳ", menu=groups_menu) 33 | self.add_cascade(label="Укивчилар", menu=students_menu) 34 | self.add_cascade(label="Инфо", menu=info_menu) 35 | 36 | # Teachers 37 | teachers_menu.add_command(label="Кошиш", command=self.teachers_add) 38 | teachers_menu.add_command(label="Янгилаш", command=self.teachers_edit) 39 | teachers_menu.add_command(label="Учириш", command=self.teachers_delete) 40 | 41 | # Groups 42 | groups_menu.add_command(label="Кошиш", command=self.groups_add) 43 | groups_menu.add_command(label="Янгилаш", command=self.groups_edit) 44 | groups_menu.add_command(label="Учириш", command=self.groups_delete) 45 | 46 | # Students 47 | students_menu.add_command(label="База", command=self.students_db) 48 | 49 | # Info 50 | info_menu.add_command(label="Дастур хакида малумот", command=self.info_about) 51 | info_menu.add_separator() 52 | 53 | # Create frames for each new window --MenuBar-Cascade-Commands 54 | self.teachers_add_frame = ttk.Frame(master) 55 | self.teachers_edit_frame = ttk.Frame(master) 56 | self.teachers_delete_frame = ttk.Frame(master) 57 | 58 | self.groups_add_frame = ttk.Frame(master) 59 | self.groups_edit_frame = ttk.Frame(master) 60 | self.groups_delete_frame = ttk.Frame(master) 61 | 62 | self.students_db_frame = ttk.Frame(master) 63 | 64 | self.info_about_frame = ttk.Frame(master) 65 | 66 | # Hide the frames when you switch the menu 67 | def hide_all_frames(self): 68 | """Cleans the screen after pressing the menu item""" 69 | for widget in self.teachers_add_frame.winfo_children(): 70 | widget.destroy() 71 | 72 | for widget in self.teachers_edit_frame.winfo_children(): 73 | widget.destroy() 74 | 75 | for widget in self.teachers_delete_frame.winfo_children(): 76 | widget.destroy() 77 | 78 | for widget in self.groups_add_frame.winfo_children(): 79 | widget.destroy() 80 | 81 | for widget in self.groups_edit_frame.winfo_children(): 82 | widget.destroy() 83 | 84 | for widget in self.groups_delete_frame.winfo_children(): 85 | widget.destroy() 86 | 87 | for widget in self.students_db_frame.winfo_children(): 88 | widget.destroy() 89 | 90 | for widget in self.info_about_frame.winfo_children(): 91 | widget.destroy() 92 | 93 | self.teachers_add_frame.pack_forget() 94 | self.teachers_edit_frame.pack_forget() 95 | self.teachers_delete_frame.pack_forget() 96 | self.groups_add_frame.pack_forget() 97 | self.groups_edit_frame.pack_forget() 98 | self.groups_delete_frame.pack_forget() 99 | self.students_db_frame.pack_forget() 100 | self.info_about_frame.pack_forget() 101 | 102 | # Create methods for Teachers 103 | def teachers_add(self): 104 | self.hide_all_frames() 105 | self.teachers_add_frame.pack(fill="both", expand=1) 106 | p1 = ttk.Label(self.teachers_add_frame, text="Teachers Add") 107 | p1.grid(row=0, column=0) 108 | 109 | def teachers_edit(self): 110 | self.hide_all_frames() 111 | self.teachers_edit_frame.pack(fill="both", expand=1) 112 | p2 = ttk.Label(self.teachers_edit_frame, text="Teachers Edit") 113 | p2.pack() 114 | 115 | def teachers_delete(self): 116 | self.hide_all_frames() 117 | self.teachers_delete_frame.pack(fill="both", expand=1) 118 | p3 = ttk.Label(self.teachers_delete_frame, text="Teachers Delete") 119 | p3.pack() 120 | 121 | # Create methods for Groups 122 | def groups_add(self): 123 | self.hide_all_frames() 124 | self.groups_add_frame.pack(fill="both", expand=1) 125 | p4 = ttk.Label(self.groups_add_frame, text="Groups Add") 126 | p4.pack() 127 | 128 | def groups_edit(self): 129 | self.hide_all_frames() 130 | self.groups_edit_frame.pack(fill="both", expand=1) 131 | p5 = ttk.Label(self.groups_edit_frame, text="Groups Edit") 132 | p5.pack() 133 | 134 | def groups_delete(self): 135 | self.hide_all_frames() 136 | self.groups_delete_frame.pack(fill="both", expand=1) 137 | p1 = ttk.Label(self.groups_delete_frame, text="Groups Delete") 138 | p1.pack() 139 | 140 | # Create methods for Students 141 | def students_db(self): 142 | self.hide_all_frames() 143 | self.students_db_frame.pack(fill="both", expand=1) 144 | p1 = ttk.Label(self.students_db_frame, text="Students Database") 145 | p1.pack() 146 | 147 | def info_about(self): 148 | self.hide_all_frames() 149 | self.info_about_frame.pack(fill="both", expand=1) 150 | p1 = ttk.Label(self.info_about_frame, text="About") 151 | p1.pack() 152 | 153 | # teachers_menu = tk.Menu(self, tearoff=False) 154 | # self.add_cascade(label="File", underline=0, menu=teachers_menu) 155 | # teachers_menu.add_command(label="Press-1", underline=1, command=self.press1) 156 | # 157 | # groups_menu = tk.Menu(self, tearoff=False) 158 | # self.add_cascade(label="New", underline=0, menu=groups_menu) 159 | # groups_menu.add_command(label="Press-2", underline=1, command=self.press2) 160 | # 161 | # def press1(self): 162 | # p1 = ttk.Label(self.parent, text="Press-1") 163 | # p1.pack() 164 | # 165 | # def press2(self): 166 | # p2 = ttk.Label(self.parent, text="Press-2") 167 | # p2.pack() 168 | # 169 | # def quit(self): 170 | # sys.exit(0) 171 | 172 | 173 | class App(tk.Tk): 174 | def __init__(self, master): 175 | tk.Tk.__init__(self) 176 | self.master = master 177 | 178 | menubar = MenuBar(self) 179 | self.config(menu=menubar) 180 | 181 | 182 | if __name__ == "__main__": 183 | app = App(None) 184 | app.title("AutoRoad") 185 | app.geometry("400x400") 186 | style = ThemedStyle(app) 187 | style.set_theme("breeze") 188 | app.mainloop() 189 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/message_boxes.py: -------------------------------------------------------------------------------- 1 | # July 16, 2020 11:38 PM 2 | # Message Boxes 3 | # By RΨST-4M 🚀 4 | # EightSoft Academy 5 | 6 | from tkinter import * 7 | from tkinter import messagebox 8 | 9 | root = Tk() 10 | root.title("MessageBox") 11 | root.iconbitmap('examples/photos/icon.ico') 12 | 13 | def popup(): 14 | response = messagebox.askquestion("This is my pupup!", "hello world") 15 | Label(root, text=response).pack() 16 | # showinfo, showwarning, showerror, askquestion, askokcancel, askyesno 17 | if response=="yes": 18 | Label(root, text="You pressed Yes!").pack() 19 | else: 20 | Label(root, text="You pressed No!").pack() 21 | 22 | 23 | Button(root, text="Popup", command=popup).pack() 24 | 25 | root.mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/my_calendar.py: -------------------------------------------------------------------------------- 1 | # Images, icons, and exit button 2 | 3 | from tkinter import * 4 | from tkcalendar import * 5 | 6 | root = Tk() 7 | root.title('EightSoft Academy') 8 | root.geometry("600x400") 9 | 10 | cal = Calendar(root, selectmode="day", year=2020, month=5, day=22) 11 | cal.pack() 12 | 13 | 14 | def grab_date(): 15 | my_label.config(text=cal.get_date()) 16 | 17 | 18 | my_btn = Button(root, text="Get Date", command=grab_date).pack() 19 | 20 | my_label = Label(root, text="") 21 | my_label.pack() 22 | 23 | root.mainloop() 24 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/new_window.py: -------------------------------------------------------------------------------- 1 | # July 17, 2020 8:50 AM 2 | # New Window popups 3 | # By RΨST-4M 🚀 4 | # EightSoft Academy 5 | 6 | from tkinter import * 7 | from PIL import Image, ImageTk 8 | from tkinter import messagebox 9 | 10 | root = Tk() 11 | root.title("New Window") 12 | root.iconbitmap('examples/photos/icon.ico') 13 | 14 | def open(): 15 | global my_image 16 | def popup(): 17 | response = messagebox.askquestion("Print", "Do you want to print?") 18 | if response=="yes": 19 | Label(root, text="It is printing!").pack() 20 | else: 21 | Label(root, text="You pressed No!").pack() 22 | 23 | # Top Level Window 24 | top = Toplevel() 25 | top.title("Python Image") 26 | 27 | my_image = ImageTk.PhotoImage(Image.open("examples/photos/python-file-1.png")) 28 | my_label = Label(top, image=my_image).pack() 29 | Button(top, text="Print out", command=popup).pack() 30 | 31 | 32 | btn = Button(root, text="Open the excel file of ... ...", command=open).pack() 33 | 34 | 35 | mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/photos/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rustam-Z/python-programming/e38a2305df555768a5ab0fa5383f77b73544c4bd/Projects/Tkinter Projects/examples/photos/icon.ico -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/photos/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rustam-Z/python-programming/e38a2305df555768a5ab0fa5383f77b73544c4bd/Projects/Tkinter Projects/examples/photos/image.jpg -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/photos/imge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rustam-Z/python-programming/e38a2305df555768a5ab0fa5383f77b73544c4bd/Projects/Tkinter Projects/examples/photos/imge.png -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/photos/python-file-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rustam-Z/python-programming/e38a2305df555768a5ab0fa5383f77b73544c4bd/Projects/Tkinter Projects/examples/photos/python-file-1.png -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/photos/python-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rustam-Z/python-programming/e38a2305df555768a5ab0fa5383f77b73544c4bd/Projects/Tkinter Projects/examples/photos/python-file.png -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/photos/python.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rustam-Z/python-programming/e38a2305df555768a5ab0fa5383f77b73544c4bd/Projects/Tkinter Projects/examples/photos/python.png -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/progress_bar.py: -------------------------------------------------------------------------------- 1 | # importing tkinter module 2 | from tkinter import * 3 | from tkinter.ttk import * 4 | 5 | # creating tkinter window 6 | root = Tk() 7 | 8 | # Progress bar widget 9 | progress = Progressbar(root, orient = HORIZONTAL, 10 | length = 100, mode = 'indeterminate') 11 | 12 | # Function responsible for the updation 13 | # of the progress bar value 14 | def bar(): 15 | import time 16 | progress['value'] = 20 17 | root.update_idletasks() 18 | time.sleep(0.5) 19 | 20 | progress['value'] = 40 21 | root.update_idletasks() 22 | time.sleep(0.5) 23 | 24 | progress['value'] = 50 25 | root.update_idletasks() 26 | time.sleep(0.5) 27 | 28 | progress['value'] = 60 29 | root.update_idletasks() 30 | time.sleep(0.5) 31 | 32 | progress['value'] = 80 33 | root.update_idletasks() 34 | time.sleep(0.5) 35 | 36 | progress['value'] = 100 37 | root.update_idletasks() 38 | time.sleep(0.5) 39 | 40 | progress['value'] = 80 41 | root.update_idletasks() 42 | time.sleep(0.5) 43 | 44 | progress['value'] = 60 45 | root.update_idletasks() 46 | time.sleep(0.5) 47 | 48 | progress['value'] = 50 49 | root.update_idletasks() 50 | time.sleep(0.5) 51 | 52 | progress['value'] = 40 53 | root.update_idletasks() 54 | time.sleep(0.5) 55 | 56 | progress['value'] = 20 57 | root.update_idletasks() 58 | time.sleep(0.5) 59 | progress['value'] = 0 60 | 61 | 62 | progress.pack(pady = 10) 63 | 64 | # This button will initialize 65 | # the progress bar 66 | Button(root, text = 'Start', command = bar).pack(pady = 10) 67 | 68 | # infinite loop 69 | mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/radio.py: -------------------------------------------------------------------------------- 1 | # July 16, 2020 12:41 PM 2 | # Radio Button 3 | # By RΨST-4M 🚀 4 | # EightSoft Academy 5 | 6 | from tkinter import * 7 | 8 | root = Tk() 9 | root.title("Frames") 10 | root.iconbitmap('examples/photos/icon.ico') 11 | 12 | r = IntVar() 13 | r.set(1) # default 14 | 15 | def clicked(value): 16 | myLabel = Label(root, text=value).pack() 17 | 18 | Radiobutton(root, text="Option 1", variable=r, value=1, command=lambda: clicked(r.get())).pack() 19 | Radiobutton(root, text="Option 2", variable=r, value=2, command=lambda: clicked(r.get())).pack() 20 | 21 | label = Label(root, text=r.get()).pack(anchor=W) 22 | myButton = Button(root, text="Click me!", command=lambda: clicked(r.get())).pack() 23 | 24 | root.mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/scrollbar.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from tkinter import messagebox 3 | from tkinter import ttk # Normal Tkinter.* widgets are not themed! 4 | from ttkthemes import ThemedTk 5 | 6 | 7 | root = ThemedTk(theme="breeze") 8 | root.title("Menu Bar") 9 | root.iconbitmap('examples/photos/icon.ico') 10 | root.geometry("400x400") 11 | 12 | scrollbar = ttk.Scrollbar(root) 13 | scrollbar.pack(side=RIGHT, fill=Y) 14 | 15 | my_list = Listbox(root, yscrollcommand=scrollbar.set) 16 | for line in range(100): 17 | my_list.insert(END, "This is line number " + str(line)) 18 | 19 | my_list.pack(side=LEFT, fill=BOTH) 20 | scrollbar.config(command=my_list.yview) 21 | 22 | mainloop() 23 | -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/sliders.py: -------------------------------------------------------------------------------- 1 | # Sliders 2 | # By RΨST-4M 🚀 3 | # EightSoft Academy 4 | 5 | from tkinter import * 6 | 7 | root = Tk() 8 | root.title("Sliders") 9 | root.iconbitmap('examples/photos/icon.ico') 10 | root.geometry("400x400") 11 | 12 | vertical = Scale(root, from_=0, to=200) 13 | vertical.pack() 14 | 15 | horizontal = Scale(root, from_=0, to=200, orient=HORIZONTAL) 16 | horizontal.pack() 17 | 18 | root.mainloop() -------------------------------------------------------------------------------- /Projects/Tkinter Projects/examples/ttktheme.py: -------------------------------------------------------------------------------- 1 | # pip install ttktheme 2 | # Tuesday, July 19, 2020 3 | # By RΨST-4M 🚀 4 | # EightSoft Academy 5 | 6 | from tkinter import * 7 | from tkinter import messagebox 8 | from tkinter import ttk # Normal Tkinter.* widgets are not themed! 9 | from ttkthemes import ThemedTk 10 | 11 | root = ThemedTk(theme="breeze") 12 | root.title("Menu Bar") 13 | root.iconbitmap('examples/photos/icon.ico') 14 | root.geometry("400x400") 15 | 16 | # Crate a Menu 17 | my_menu = Menu(root) 18 | root.config(menu=my_menu) 19 | 20 | 21 | # Create a functions for commands 22 | def command_new(): 23 | """When you press File->New ... the following function code will work""" 24 | ttk.Label(root, text="You Clicked New ...").pack() 25 | 26 | 27 | def command_cut(): 28 | ttk.Label(root, text="Awesome, it is working!").pack() 29 | 30 | 31 | def question(): 32 | response = messagebox.askquestion("Question", "Do you liked Menu Bars?") 33 | if response == "yes": 34 | ttk.Label(root, text="Ugh!!!").pack() 35 | else: 36 | ttk.Label(root, text="Sorry ...").pack() 37 | 38 | 39 | def command_copy(): 40 | ttk.Button(root, text="Popup", command=question).pack() 41 | 42 | 43 | # Create a Menu Item "File" 44 | file_menu = Menu(my_menu, tearoff=False) 45 | my_menu.add_cascade(label="File", menu=file_menu) 46 | file_menu.add_command(label="New", command=command_new) 47 | file_menu.add_separator() 48 | file_menu.add_command(label="Exit", command=root.quit) 49 | 50 | # Create a Menu Item "Edit" 51 | edit_menu = Menu(my_menu, tearoff=False) 52 | my_menu.add_cascade(label="Ask", menu=edit_menu) 53 | edit_menu.add_command(label="Press me :)", command=command_cut) 54 | edit_menu.add_separator() 55 | edit_menu.add_command(label="Question", command=command_copy) 56 | 57 | 58 | # for running the program 59 | root.mainloop() 60 | -------------------------------------------------------------------------------- /Projects/Web Scraping/coreyms_com.py: -------------------------------------------------------------------------------- 1 | from bs4 import BeautifulSoup 2 | import requests 3 | import csv 4 | 5 | source = requests.get('http://coreyms.com').text 6 | 7 | soup = BeautifulSoup(source, 'lxml') 8 | 9 | csv_file = open('cms_scrape.csv', 'w') 10 | 11 | csv_writer = csv.writer(csv_file) 12 | csv_writer.writerow(['headline', 'summary', 'video_link']) 13 | 14 | for article in soup.find_all('article'): 15 | headline = article.h2.a.text 16 | print(headline) 17 | 18 | summary = article.find('div', class_='entry-content').p.text 19 | print(summary) 20 | 21 | try: 22 | vid_src = article.find('iframe', class_='youtube-player')['src'] 23 | 24 | vid_id = vid_src.split('/')[4] 25 | vid_id = vid_id.split('?')[0] 26 | 27 | yt_link = f'https://youtube.com/watch?v={vid_id}' 28 | except Exception as e: 29 | yt_link = None 30 | 31 | print(yt_link) 32 | 33 | print() 34 | 35 | csv_writer.writerow([headline, summary, yt_link]) 36 | 37 | csv_file.close() 38 | -------------------------------------------------------------------------------- /Projects/Website Blocker/hosts: -------------------------------------------------------------------------------- 1 | # Copyright (c) 1993-2009 Microsoft Corp. 2 | # 3 | # This is a sample HOSTS file used by Microsoft TCP/IP for Windows. 4 | # 5 | # This file contains the mappings of IP addresses to host names. Each 6 | # entry should be kept on an individual line. The IP address should 7 | # be placed in the first column followed by the corresponding host name. 8 | # The IP address and the host name should be separated by at least one 9 | # space. 10 | # 11 | # Additionally, comments (such as these) may be inserted on individual 12 | # lines or following the machine name denoted by a '#' symbol. 13 | # 14 | # For example: 15 | # 16 | # 102.54.94.97 rhino.acme.com # source server 17 | # 38.25.63.10 x.acme.com # x client host 18 | 19 | # localhost name resolution is handled within DNS itself. 20 | # 127.0.0.1 localhost 21 | # ::1 localhost -------------------------------------------------------------------------------- /Projects/Website Blocker/website-blocker.py: -------------------------------------------------------------------------------- 1 | import time 2 | from datetime import datetime as dt 3 | 4 | hosts_temp = r"D:\Dropbox\pp\block_websites\Demo\hosts" 5 | hosts_path = "/etc/hosts" 6 | redirect = "127.0.0.1" 7 | website_list = ["www.facebook.com", "facebook.com", "dub119.mail.live.com", "www.dub119.mail.live.com"] 8 | 9 | while True: 10 | if dt(dt.now().year, dt.now().month, dt.now().day, 8) < dt.now() < dt(dt.now().year, dt.now().month, dt.now().day, 16): 11 | print("Working hours...") 12 | with open(hosts_path, 'r+') as file: 13 | content = file.read() 14 | for website in website_list: 15 | if website in content: 16 | pass 17 | else: 18 | file.write(redirect + " " + website + "\n") 19 | else: 20 | with open(hosts_path, 'r+') as file: 21 | content = file.readlines() 22 | file.seek(0) 23 | for line in content: 24 | if not any(website in line for website in website_list): 25 | file.write(line) 26 | file.truncate() 27 | print("Fun hours...") 28 | time.sleep(5) 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Software Engineering with Python 2 | 3 | ``` 4 | Learn and code every day! Take notes. 5 | Learn to ask GOOD questions. 6 | Learn to prioritize tasks. Focus on 1 thing! 7 | Build something, anything. Build projects that bring some benefit to you or the people around you. 8 | Take small steps, but every day, consistency is very important. 9 | ``` 10 | 11 | ## Contents: 12 | - [Important Skills](#important-skills) 13 | - [Computer Science Basics](#computer-science-basics) 14 | - [Start Learning Python](#start-learning-python) 15 | - [Discover some Python libraries](#discover-some-python-libraries) 16 | - [Databases: SQL, NoSQL](#databases-sql-nosql) 17 | - [Web Development](#web-development) 18 | - [**Advanced Python](#advanced-python) 19 | 20 | ## Important Skills 21 | 1. Algorithms and data structures 22 | 2. Programming mindset - analytical, problem-solving mindset 23 | 3. Know your programming language 24 | 25 | ## Computer Science Basics 26 | - [Harvard CS50](https://youtube.com/playlist?list=PLhQjrBD2T383f9scHRNYJkior2VvYjpSL) - Scratch, C, Arrays, Algorithms, Memory, Data structures, Python, SQL, HTML, CSS, JavaScript, Flask 27 | - `Optional` [Crash Course Computer Science](https://www.youtube.com/playlist?list=PL8dPuuaLjXtNlUrzyH5r6jN9ulIgZBpdo) 28 | 29 | ## Start Learning Python 30 | Learn the basics, watch a couple of tutorials, read articles, and then build projects using Python. Learn by building. Start from building console applications, then learn how to build desktop apps, then web apps. 31 | 32 | - [11 Beginner Tips for Learning Python Programming](https://realpython.com/python-beginner-tips/) 33 | - [freeCodeCamp.org - Python beginning](https://youtu.be/rfscVS0vtbw) 34 | - [freeCodeCamp.org - Python intermediate](https://youtu.be/HGOBQPFzWKo) 35 | - [30-Days-Of-Python](https://github.com/Asabeneh/30-Days-Of-Python) 36 | - [Программирование на Python](https://www.youtube.com/playlist?list=PLlb7e2G7aSpQhNphPSpcO4daaRPeVstku) 37 | - [Corey Schafer](https://www.youtube.com/playlist?list=PL-osiE80TeTt2d9bfVyTiXJA-UTHn6WwU), focus **MORE** on this! 38 | - Readings: 39 | - [Easy practical Python](https://dabeaz-course.github.io/practical-python/Notes/Contents.html) 40 | - [w3schools.com](https://www.w3schools.com/python/) 41 | - [programiz.com](https://www.programiz.com/python-programming) 42 | - *[pythontutorial.net](https://www.pythontutorial.net/) - _Python Basics_ and _Python Advanced_ sections 43 | - **[python-course.eu](https://python-course.eu/python-tutorial/) - only _Python Tutorial_ section 44 | - **[realpython.com](https://realpython.com/python-basics/) 45 | - OOP in Python: 46 | - [by Caleb Curry](https://youtu.be/MikphENIrOo) 47 | - [by Corey Schafer](https://www.youtube.com/playlist?list=PL-osiE80TeTsqhIuOqKhwlXsIBIdSeYtc) 48 | - [python-course.eu](https://python-course.eu/oop/) 49 | - [pythontutorial.net](https://www.pythontutorial.net/python-oop/) 50 | - Books: 51 | - [Python Basics: A Practical Introduction to Python 3](https://t.me/progbook/5781) 52 | - *[Python Tricks: A Buffet of Awesome Python Features](https://t.me/progbook/5882) 53 | 54 | ## Problem solving & Practical tasks 55 | - https://github.com/Rustam-Z/cpp-programming 56 | - https://github.com/darkprinx/break-the-ice-with-python 57 | 58 | ## Discover some Python libraries 59 | - [Learn TKinter](https://www.youtube.com/playlist?list=PLCC34OHNcOtoC6GglhF3ncJ5rLwQrLGnV) 60 | - Learn web scraping using [beautiful-soup](https://beautiful-soup-4.readthedocs.io/en/latest/) or *Selenium 61 | - File handling: txt, `json`, `csv`, `yaml` 62 | - Working with paths with `pathlib` and OS with `os` 63 | - Sending HTTP requests and receiving HTTP responses with `requests` 64 | - Building CLI with `argparse` 65 | - Working with data `collections`, `itertools` 66 | 67 | ## Databases: SQL, NoSQL 68 | - SQL 69 | - [sqlbolt.com](https://sqlbolt.com/) 70 | - [w3schools.com](https://www.w3schools.com/sql/) 71 | - [sqltutorial.org](https://www.sqltutorial.org/) 72 | - `sqlite`, `sqlalchemy` 73 | - [Introduction to working with databases in Python](https://www.youtube.com/watch?v=TY6RDEG9bhw) 74 | - Relationships: One-to-One, One-to-Many, Many-to-Many 75 | - _Data normalization_ 76 | 77 | ## Web Development 78 | - Understand how the Internet works, OSI & TCP/IP models, DNS, HTTP, REST API. 79 | - HTML, CSS, JavaScript 80 | - [Web design in 4 minutes](https://jgthms.com/web-design-in-4-minutes/) 81 | - [CS50: Web Programming Course](https://www.youtube.com/playlist?list=PLhQjrBD2T380xvFSUmToMMzERZ3qB5Ueu) 82 | - Learn Django or Flask 83 | - [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Learn), [Django](https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django) 84 | - [Django girls](https://tutorial.djangogirls.org/en/) 85 | - "Flask Web Development" Miguel Grinberg 86 | - "Building REST APIs with Flask" Kunal Relan 87 | - See how others build projects using Django, then build your own app. 88 | - [Corey Schafer](https://www.youtube.com/playlist?list=PL-osiE80TeTtoQCKZ03TU5fNfx2UY6U4p) 89 | - [Dennis Ivy](https://www.youtube.com/playlist?list=PL-51WBLyFTg2vW-_6XBoUpE7vpmoR3ztO) 90 | - [Building REST API](https://wsvincent.com/django-rest-framework-tutorial/) 91 | - Books: 92 | - "Django for beginners" by Vincent W. 93 | - "Django for APIs" by Vincent W. 94 | - "Django 3 by Examples" 95 | 96 | ## Advanced Python 97 | Check https://github.com/Rustam-Z/senior-python-developer. 98 | 99 | On a high level: 100 | - Clean code: 101 | - [PEP 8 - Style Guide for Python Code](https://peps.python.org/pep-0008/) 102 | - [clean-code-python](https://github.com/zedr/clean-code-python) 103 | - [testdriven.io](https://testdriven.io/blog/clean-code-python) 104 | - "Clean code in Python" book 105 | - [LinkedIn Learning: Clean coding practices](https://www.linkedin.com/learning/agile-software-development-clean-coding-practices) 106 | - `typing` 107 | - `dataclasses` 108 | - Clean design: 109 | - Design principles: KISS, DRY, SOLID 110 | - Design patterns 111 | - Concurrency, parallelism, asynchronicity programming: 112 | - [Concurrency and parallelism](https://www.pythontutorial.net/python-concurrency/) 113 | - [realpython.com](https://realpython.com/learning-paths/python-concurrency-parallel-programming) 114 | - [LinkedIn Learning: Part 1](https://www.linkedin.com/learning/python-parallel-and-concurrent-programming-part-1) 115 | - [LinkedIn Learning: Part 2](https://www.linkedin.com/learning/python-parallel-and-concurrent-programming-part-2) 116 | - Testing: 117 | - `unittest`, `pytest` 118 | - "Python testing with PyTest" book 119 | - Advanced topics: 120 | - [python-course.eu](https://python-course.eu/advanced-python/) 121 | - [book.pythontips.com/](https://book.pythontips.com/en/latest/) 122 | - [Python topics for Senior developers](https://github.com/matacoder/senior) 123 | - [Python best practices - realpython.com](https://realpython.com/tutorials/best-practices/) 124 | - [Medium blog](https://medium.com/techtofreedom/python/home) 125 | - [thedigitalcatonline.com](https://thedigitalcatonline.com/) 126 | - *[Python 3 Patterns, Recipes and Idioms](https://python-3-patterns-idioms-test.readthedocs.io/en/latest/) 127 | - Books: 128 | - "Fluent Python" 129 | - "Python Cookbook" 130 | - "Learning Python" 131 | - "Effective Python" 132 | - "Advanced Guide to Python 3" 133 | - "Mastering Object-Oriented Python" 134 | - "Expert Python Programming" 2021 135 | - "High-performance Python" 136 | - "Practices of the Python Pro", "The Python workshop", "Python Workout" 137 | -------------------------------------------------------------------------------- /design_patterns/README.md: -------------------------------------------------------------------------------- 1 | # Design Patterns with Python 2 | Design patterns are the best formalized practices a programmer can use to solve common problems when designing an application or system. 3 | 4 | ### Types of design patterns 5 | - Creational - designed for object creation to increase flexibility and reuse of existing code. Polymorphism is used. 6 | - Structural - establishes relationship between classes making larger structures. Inheritance is used. 7 | - Whenever you think designing architecture for your system, structural design patterns help you to plan for the future, arrange classes in neat hierarchies. 8 | - Behavioral - effective communications and interactions between objects/classes. Methods are used. 9 | 10 | ### Using common design patterns, you can: 11 | - Speed up the development process; 12 | - Reduce the number of lines of code; 13 | - Make sure your code is well-designed; 14 | - Anticipate future problems arising from small issues. 15 | 16 | ## Notes 17 | 1. Creational 18 | - [Singleton](c_singleton/singleton.py), restricts a class from having more than one instance and ensures a global access point to this instance. 19 | - [Borg](c_singleton/borg.py), allows all instances of one class share common data. 20 | - [Factory](c_factory/factory.py), the method that helps to create other objects. 21 | - [Factory abstract](c_factory/abstact_factory.py), like factory but object that provides a way to encapsulate a group of individual factories. 22 | - [Builder + Director](c_builder/builder.py), separating class from building complex object. 23 | - [Prototype](c_prototype/prototype.py), registers object and clones objects (if instantiation is costly). 24 | - [Pool](c_pool/pool.py), like flyweight but for mutable objects. 25 | 3. Structural 26 | - [Facade](s_facade/facade.py), hides the complexity of implementations. New API on top of other APIs. 27 | - [Decorator](s_decorator/decorator.py), attaches new behaviors to the objects without modifying their structure. 28 | - [Adapter](s_adapter/adapter.py), makes incompatible objects adaptable to each other. Ex: `speak=english.hello(), speak=korean.anyong()` 29 | - [Bridge](s_bridge/bridge.py), separates the implementation from abstraction. Ex: DrawingAPIOne, DrawingAPITwo 30 | - [Composite](s_composite/composite.py), describes a group of objects the same way as a single instance, using Tree data structure. 31 | - [Proxy](s_proxy/proxy.py), like decorator, adds functionality to a class without changing its interface. 32 | - [Flyweight](s_flyweight/flyweight.py), cache, reuses existing instances of objects with similar/identical state. 33 | 4. Behavioural 34 | - [Iterator](b_iterator/iterator.py), helps to iterate through the elements of collection. 35 | - [Observer](b_observer/observer.py), lets subscribed entities know about changes in an observable. Ex: Elon & Twitter. 36 | - [Publish & Subscribe](b_publish_subscribe/publish_subscribe.py), a source syndicates events/data to 0+ registered listeners. 37 | - [Strategy](b_strategy/strategy.py), enables our application to select algorithms (method) at runtime. 38 | - [Visitor](b_visitor/visitor.py), adds new features to an existing hierarchy without changing its structure. Ex: electricity, hvac. 39 | - [Mediator](b_mediator/mediator.py), objects in a system communicate through a Mediator instead of directly with each other. 40 | - [Chain of responsibility](b_chain_of_responsibility/chain_of_responsibility.py), allows a request to pass down a chain of receivers until it is handled. 41 | - [Template](b_template/template.py), defines the skeleton of a base algorithm, deferring definition of exact steps to subclasses. 42 | - Momento, generate an opaque token that can be used to go back to a previous state. 43 | - State, logic is organized into a discrete number of potential states and the next state that can be transitioned to 44 | 45 | ## Resources 46 | - https://www.linkedin.com/learning/python-design-patterns/welcome?u=2113185 47 | - https://github.com/faif/python-patterns 48 | - https://jellyfish.tech/implementation-of-common-design-patterns-in-python/ 49 | - https://youtube.com/playlist?list=PLO6785UZapFX5bO4ZZSO7Unn2uOTNFqfQ 50 | - https://www.toptal.com/python/python-design-patterns 51 | - https://python-patterns.guide -------------------------------------------------------------------------------- /design_patterns/b_chain_of_responsibility/chain_of_responsibility.py: -------------------------------------------------------------------------------- 1 | """ 2 | Allows a request to pass down a chain of receivers until it is handled. 3 | 4 | Composite related to chain of responsibility. 5 | """ 6 | 7 | 8 | class Handler: 9 | """Abstract Handler""" 10 | 11 | def __init__(self, successor): 12 | self._successor = successor # Define who is the next handler 13 | 14 | def handle(self, request): 15 | handled = self._handle(request) # If handled, stop here 16 | 17 | # Otherwise, keep going 18 | if not handled: 19 | self._successor.handle(request) 20 | 21 | def _handle(self, request): 22 | raise NotImplementedError('Must provide implementation in subclass!') 23 | 24 | 25 | class ConcreteHandler1(Handler): # Inherits from the abstract handler 26 | """Concrete handler 1""" 27 | 28 | def _handle(self, request): 29 | if 0 < request <= 10: # Provide a condition for handling 30 | print("Request {} handled in handler 1".format(request)) 31 | return True # Indicates that the request has been handled 32 | 33 | 34 | class DefaultHandler(Handler): # Inherits from the abstract handler 35 | """Default handler""" 36 | 37 | def _handle(self, request): 38 | """If there is no handler available""" 39 | # No condition checking since this is a default handler 40 | print("End of chain, no handler for {}".format(request)) 41 | return True # Indicates that the request has been handled 42 | 43 | 44 | class Client: # Using handlers 45 | def __init__(self): 46 | self.handler = ConcreteHandler1(DefaultHandler(None)) # Create handlers and use them in a sequence you want 47 | # Note that the default handler has no successor 48 | 49 | def delegate(self, requests_): # Send your requests one at a time for handlers to handle 50 | for request in requests_: 51 | self.handler.handle(request) 52 | 53 | 54 | if __name__ == "__main__": 55 | # Create a client 56 | c = Client() 57 | 58 | # Create requests 59 | requests = [2, 5, 30] 60 | 61 | # Send the requests 62 | c.delegate(requests) 63 | -------------------------------------------------------------------------------- /design_patterns/b_chain_of_responsibility/chaining_method.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | 4 | class Person: 5 | def __init__(self, name: str, action: Action) -> None: 6 | self.name = name 7 | self.action = action 8 | 9 | def do_action(self) -> Action: 10 | print(self.name, self.action.name, end=" ") 11 | return self.action 12 | 13 | 14 | class Action: 15 | def __init__(self, name: str) -> None: 16 | self.name = name 17 | 18 | def amount(self, val: str) -> Action: 19 | print(val, end=" ") 20 | return self 21 | 22 | def stop(self) -> None: 23 | print("then stop") 24 | 25 | 26 | def main(): 27 | move = Action('move') 28 | person = Person('Jack', move) 29 | person.do_action().amount('5m').stop() # Jack move 5m then stop 30 | 31 | 32 | if __name__ == "__main__": 33 | main() 34 | -------------------------------------------------------------------------------- /design_patterns/b_iterator/generator.py: -------------------------------------------------------------------------------- 1 | """ 2 | It allows a client to have sequential access to the elements of an aggregate object (without exposing its underlying structure). 3 | 4 | Composite related to iterator. 5 | """ 6 | 7 | 8 | def count_to(count): 9 | """Our iterator implementation""" 10 | 11 | # Our list 12 | numbers_in_german = ["eins", "zwei", "drei", "vier", "funf"] 13 | 14 | # Our built-in iterator 15 | # Creates a tuple such as (1, "eins") 16 | iterator = zip(range(count), numbers_in_german) 17 | 18 | # Iterate through our iterable list 19 | # Extract the German numbers 20 | # Put them in a generator called number 21 | for position, number in iterator: 22 | # Returns a 'generator' containing numbers in German 23 | yield number 24 | 25 | # Let's test the generator returned by our iterator 26 | 27 | 28 | for num in count_to(7): 29 | print(num) 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /design_patterns/b_iterator/generator2.py: -------------------------------------------------------------------------------- 1 | """ 2 | http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/ 3 | Implementation of the iterator pattern with a generator 4 | *TL;DR 5 | Traverses a container and accesses the container's elements. 6 | """ 7 | from typing import Any, Generator 8 | 9 | 10 | def count_to(count: int): 11 | """Counts by word numbers, up to a maximum of five""" 12 | numbers = ["one", "two", "three", "four", "five"] 13 | yield from numbers[:count] 14 | 15 | 16 | # Test the generator 17 | def count_to_two() -> Generator[str, Any, None]: 18 | return count_to(2) 19 | 20 | 21 | def count_to_five() -> Generator[str, Any, None]: 22 | return count_to(5) 23 | 24 | 25 | def main(): 26 | """ 27 | # Counting to two... 28 | >>> for number in count_to_two(): 29 | ... print(number) 30 | one 31 | two 32 | # Counting to five... 33 | >>> for number in count_to_five(): 34 | ... print(number) 35 | one 36 | two 37 | three 38 | four 39 | five 40 | """ 41 | 42 | 43 | if __name__ == "__main__": 44 | import doctest 45 | 46 | doctest.testmod() 47 | -------------------------------------------------------------------------------- /design_patterns/b_iterator/iterator.py: -------------------------------------------------------------------------------- 1 | """ 2 | Iterator allows traversing the elements of collections without exposing the internal details. 3 | 4 | + Clean client code (Single Responsibility Principle). 5 | + Introducing iterators in collections is possible without changing the client’s code (Open/Closed Principle). 6 | + Each iteration object has its own iteration state, so you can delay & continue iteration. 7 | - Use of iterators with simple collections can overload the application. 8 | """ 9 | 10 | from __future__ import annotations 11 | from collections.abc import Iterable, Iterator 12 | from typing import Any 13 | 14 | 15 | class AlphabeticalOrderIterator(Iterator): 16 | _position: int = None 17 | _reverse: bool = False 18 | 19 | def __init__(self, collection: WordsCollection, 20 | reverse: bool = False): 21 | self._collection = collection 22 | self._reverse = reverse 23 | self._position = -1 if reverse else 0 24 | 25 | def __next__(self): 26 | try: 27 | value = self._collection[self._position] 28 | self._position += -1 if self._reverse else 1 29 | except IndexError: 30 | raise StopIteration 31 | return value 32 | 33 | 34 | class WordsCollection(Iterable): 35 | def __init__(self, collection=None): 36 | if collection is None: 37 | collection = [] 38 | self._collection = collection 39 | 40 | def __iter__(self) -> AlphabeticalOrderIterator: 41 | return AlphabeticalOrderIterator(self._collection) 42 | 43 | def get_reverse_iterator(self) -> AlphabeticalOrderIterator: 44 | return AlphabeticalOrderIterator(self._collection, True) 45 | 46 | def add_item(self, item: Any): 47 | self._collection.append(item) 48 | 49 | 50 | if __name__ == "__main__": 51 | collection_ = WordsCollection() 52 | collection_.add_item("First") 53 | collection_.add_item("Second") 54 | collection_.add_item("Third") 55 | 56 | print("Straight traversal:") 57 | print("\n".join(collection_)) 58 | 59 | print("Reverse traversal:") 60 | print("\n".join(collection_.get_reverse_iterator())) 61 | -------------------------------------------------------------------------------- /design_patterns/b_iterator/iterator2.py: -------------------------------------------------------------------------------- 1 | """ 2 | Implementation of the iterator pattern using the iterator protocol from Python 3 | *TL;DR 4 | Traverses a container and accesses the container's elements. 5 | """ 6 | from __future__ import annotations 7 | 8 | 9 | class NumberWords: 10 | """Counts by word numbers, up to a maximum of five""" 11 | 12 | _WORD_MAP = ( 13 | "one", 14 | "two", 15 | "three", 16 | "four", 17 | "five", 18 | ) 19 | 20 | def __init__(self, start: int, stop: int) -> None: 21 | self.start = start 22 | self.stop = stop 23 | 24 | def __iter__(self) -> NumberWords: # this makes the class an Iterable 25 | return self 26 | 27 | def __next__(self) -> str: # this makes the class an Iterator 28 | if self.start > self.stop or self.start > len(self._WORD_MAP): 29 | raise StopIteration 30 | current = self.start 31 | self.start += 1 32 | return self._WORD_MAP[current - 1] 33 | 34 | 35 | # Test the iterator 36 | 37 | 38 | def main(): 39 | """ 40 | # Counting to two... 41 | >>> for number in NumberWords(start=1, stop=2): 42 | ... print(number) 43 | one 44 | two 45 | # Counting to five... 46 | >>> for number in NumberWords(start=1, stop=5): 47 | ... print(number) 48 | one 49 | two 50 | three 51 | four 52 | five 53 | """ 54 | 55 | 56 | if __name__ == "__main__": 57 | import doctest 58 | 59 | doctest.testmod() 60 | -------------------------------------------------------------------------------- /design_patterns/b_mediator/mediator.py: -------------------------------------------------------------------------------- 1 | """ 2 | Objects in a system communicate through a Mediator instead of directly with each other. 3 | This reduces the dependencies between communicating objects, thereby reducing coupling. 4 | 5 | Encapsulates how a set of objects interact. 6 | """ 7 | 8 | from __future__ import annotations 9 | 10 | 11 | class ChatRoom: 12 | """Mediator class""" 13 | 14 | def display_message(self, user: User, message: str) -> None: 15 | print(f"[{user} says]: {message}") 16 | 17 | 18 | class User: 19 | """A class whose instances want to interact with each other""" 20 | 21 | def __init__(self, name: str) -> None: 22 | self.name = name 23 | self.chat_room = ChatRoom() 24 | 25 | def say(self, message: str) -> None: 26 | self.chat_room.display_message(self, message) 27 | 28 | def __str__(self) -> str: 29 | return self.name 30 | 31 | 32 | def main(): 33 | molly = User('Molly') 34 | mark = User('Mark') 35 | ethan = User('Ethan') 36 | 37 | molly.say("Hi Team! Meeting at 3 PM today.") # [Molly says]: Hi Team! Meeting at 3 PM today. 38 | mark.say("Roger that!") # [Mark says]: Roger that! 39 | ethan.say("Alright.") # [Ethan says]: Alright. 40 | 41 | 42 | if __name__ == "__main__": 43 | main() 44 | -------------------------------------------------------------------------------- /design_patterns/b_observer/observer.py: -------------------------------------------------------------------------------- 1 | """ 2 | Observer Pattern - one subject monitored by many observers. 3 | One-to-many relationship between objects such as if one object is modified, its dependent objects are to be notified automatically. 4 | 5 | Example: Elon-Musk profile in Twitter is Subject, his 65M followers are observers. 6 | 7 | Problem: 8 | - Subject to be monitored 9 | - Observers to be notified 10 | 11 | Scenario: 12 | - Core temperature - reactors at a power plant. 13 | 14 | Solution: 15 | - Subject - abstract classes 16 | Attach 17 | Detach 18 | Notify 19 | - Concrete subjects(Subject) 20 | 21 | + You haven’t to change the publisher’s code to add subscribers’ classes. 22 | - Subscribers get notifications in random order. 23 | 24 | Singleton related to Observer 25 | """ 26 | 27 | 28 | class Subject(object): # Represents what is being 'observed' 29 | 30 | def __init__(self): 31 | self._observers = [] # This where references to all the observers are being kept 32 | # Note that this is a one-to-many relationship: there will be one subject to be observed by multiple _observers 33 | 34 | def attach(self, observer): 35 | if observer not in self._observers: # If the observer is not already in the observers list 36 | self._observers.append(observer) # append the observer to the list 37 | 38 | def detach(self, observer): # Simply remove the observer 39 | try: 40 | self._observers.remove(observer) 41 | except ValueError: 42 | pass 43 | 44 | def notify(self, modifier=None): 45 | for observer in self._observers: # For all the observers in the list 46 | if modifier != observer: # Don't notify the observer who is actually updating the temperature 47 | observer.update(self) # Alert the observers! 48 | 49 | 50 | class Core(Subject): # Inherits from the Subject class 51 | 52 | def __init__(self, name=""): 53 | Subject.__init__(self) 54 | self._name = name # Set the name of the core 55 | self._temp = 0 # Initialize the temperature of the core 56 | 57 | @property # Getter that gets the core temperature 58 | def temp(self): 59 | return self._temp 60 | 61 | @temp.setter # Setter that sets the core temperature 62 | def temp(self, temp): 63 | self._temp = temp 64 | self.notify() # Notify the observers whenever somebody changes the core temperature 65 | 66 | 67 | class TempViewer: 68 | def update(self, subject): # Alert method that is invoked when the notify() method in a concrete subject is invoked 69 | print("Temperature Viewer: {} has Temperature {}".format(subject._name, subject._temp)) 70 | 71 | 72 | if __name__ == "__main__": 73 | # Let's create our subjects 74 | c1 = Core("Core 1") 75 | 76 | # Let's create our observers 77 | v1 = TempViewer() 78 | v2 = TempViewer() 79 | 80 | # Let's attach our observers to the first core 81 | c1.attach(v1) 82 | c1.attach(v2) 83 | 84 | # Let's change the temperature of our first core 85 | c1.temp = 80 86 | c1.temp = 90 87 | -------------------------------------------------------------------------------- /design_patterns/b_publish_subscribe/publish_subscribe.py: -------------------------------------------------------------------------------- 1 | """ 2 | Reference: 3 | http://www.slideshare.net/ishraqabd/publish-subscribe-model-overview-13368808 4 | Author: https://github.com/HanWenfang 5 | """ 6 | 7 | 8 | class Provider: 9 | def __init__(self): 10 | self.msg_queue = [] 11 | self.subscribers = {} 12 | 13 | def notify(self, msg): 14 | self.msg_queue.append(msg) 15 | 16 | def subscribe(self, msg, subscriber): 17 | self.subscribers.setdefault(msg, []).append(subscriber) 18 | 19 | def unsubscribe(self, msg, subscriber): 20 | self.subscribers[msg].remove(subscriber) 21 | 22 | def update(self): 23 | for msg in self.msg_queue: 24 | for sub in self.subscribers.get(msg, []): 25 | sub.run(msg) 26 | self.msg_queue = [] 27 | 28 | 29 | class Publisher: 30 | def __init__(self, msg_center): 31 | self.provider = msg_center 32 | 33 | def publish(self, msg): 34 | self.provider.notify(msg) 35 | 36 | 37 | class Subscriber: 38 | def __init__(self, name, msg_center): 39 | self.name = name 40 | self.provider = msg_center 41 | 42 | def subscribe(self, msg): 43 | self.provider.subscribe(msg, self) 44 | 45 | def unsubscribe(self, msg): 46 | self.provider.unsubscribe(msg, self) 47 | 48 | def run(self, msg): 49 | print(f"{self.name} got {msg}") 50 | 51 | 52 | def main(): 53 | """ 54 | >>> message_center = Provider() 55 | >>> fftv = Publisher(message_center) 56 | >>> jim = Subscriber("jim", message_center) 57 | >>> jim.subscribe("cartoon") 58 | >>> jack = Subscriber("jack", message_center) 59 | >>> jack.subscribe("music") 60 | >>> gee = Subscriber("gee", message_center) 61 | >>> gee.subscribe("movie") 62 | >>> vani = Subscriber("vani", message_center) 63 | >>> vani.subscribe("movie") 64 | >>> vani.unsubscribe("movie") 65 | # Note that no one subscribed to `ads` 66 | # and that vani changed their mind 67 | >>> fftv.publish("cartoon") 68 | >>> fftv.publish("music") 69 | >>> fftv.publish("ads") 70 | >>> fftv.publish("movie") 71 | >>> fftv.publish("cartoon") 72 | >>> fftv.publish("cartoon") 73 | >>> fftv.publish("movie") 74 | >>> fftv.publish("blank") 75 | >>> message_center.update() 76 | jim got cartoon 77 | jack got music 78 | gee got movie 79 | jim got cartoon 80 | jim got cartoon 81 | gee got movie 82 | """ 83 | 84 | 85 | if __name__ == "__main__": 86 | import doctest 87 | 88 | doctest.testmod() 89 | -------------------------------------------------------------------------------- /design_patterns/b_strategy/strategy.py: -------------------------------------------------------------------------------- 1 | """ 2 | Strategy pattern - we have a default method, we can change its behaviour with another function at run time. 3 | 4 | It is easy to implement with Python with its build-in "types" module. 5 | """ 6 | 7 | 8 | import types 9 | 10 | 11 | class Strategy: 12 | """The Strategy Pattern class""" 13 | def __init__(self, function=None): 14 | self.name = "Default Strategy" 15 | 16 | # If a reference to a function is provided, replace the execute() method with the given function 17 | if function: 18 | self.execute = types.MethodType(function, self) 19 | 20 | def execute(self): # This gets replaced by another version if another strategy is provided. 21 | """The default method that prints the name of the strategy being used""" 22 | print("{} is used!".format(self.name)) 23 | 24 | 25 | def strategy_one(self): 26 | print("{} is used to execute method 1".format(self.name)) 27 | 28 | 29 | def strategy_two(self): 30 | print("{} is used to execute method 2".format(self.name)) 31 | 32 | 33 | def main(): 34 | # Let's create our default strategy 35 | s0 = Strategy() 36 | s0.execute() 37 | 38 | s1 = Strategy(strategy_one) 39 | s1.name = "Strategy One" 40 | s1.execute() 41 | 42 | s2 = Strategy(strategy_two) 43 | s2.name = "Strategy Two" 44 | s2.execute() 45 | 46 | 47 | if __name__ == "__main__": 48 | main() 49 | 50 | -------------------------------------------------------------------------------- /design_patterns/b_strategy/strategy2.py: -------------------------------------------------------------------------------- 1 | """ 2 | Enables selecting an algorithm at runtime. 3 | 4 | What is this pattern about? 5 | Define a family of algorithms, encapsulate each one, and make them interchangeable. 6 | Strategy lets the algorithm vary independently of clients that use it. 7 | """ 8 | 9 | 10 | from __future__ import annotations 11 | 12 | from typing import Callable 13 | 14 | 15 | class DiscountStrategyValidator: # Descriptor class for check perform 16 | @staticmethod 17 | def validate(obj: Order, value: Callable) -> bool: 18 | try: 19 | if obj.price - value(obj) < 0: 20 | raise ValueError( 21 | f"Discount cannot be applied due to negative price resulting. {value.__name__}" 22 | ) 23 | except ValueError as ex: 24 | print(str(ex)) 25 | return False 26 | else: 27 | return True 28 | 29 | def __set_name__(self, owner, name: str) -> None: 30 | self.private_name = f"_{name}" 31 | 32 | def __set__(self, obj: Order, value: Callable = None) -> None: 33 | if value and self.validate(obj, value): 34 | setattr(obj, self.private_name, value) 35 | else: 36 | setattr(obj, self.private_name, None) 37 | 38 | def __get__(self, obj: object, objtype: type = None): 39 | return getattr(obj, self.private_name) 40 | 41 | 42 | class Order: 43 | discount_strategy = DiscountStrategyValidator() 44 | 45 | def __init__(self, price: float, discount_strategy: Callable = None) -> None: 46 | self.price: float = price 47 | self.discount_strategy = discount_strategy 48 | 49 | def apply_discount(self) -> float: 50 | if self.discount_strategy: 51 | discount = self.discount_strategy(self) 52 | else: 53 | discount = 0 54 | 55 | return self.price - discount 56 | 57 | def __repr__(self) -> str: 58 | return f"" 59 | 60 | 61 | def ten_percent_discount(order: Order) -> float: 62 | return order.price * 0.10 63 | 64 | 65 | def on_sale_discount(order: Order) -> float: 66 | return order.price * 0.25 + 20 67 | 68 | 69 | def main(): 70 | """ 71 | >>> order = Order(100, discount_strategy=ten_percent_discount) 72 | >>> print(order) 73 | 74 | >>> print(order.apply_discount()) 75 | 90.0 76 | >>> order = Order(100, discount_strategy=on_sale_discount) 77 | >>> print(order) 78 | 79 | >>> print(order.apply_discount()) 80 | 55.0 81 | >>> order = Order(10, discount_strategy=on_sale_discount) 82 | Discount cannot be applied due to negative price resulting. on_sale_discount 83 | >>> print(order) 84 | 85 | """ 86 | 87 | 88 | if __name__ == "__main__": 89 | import doctest 90 | 91 | doctest.testmod() 92 | -------------------------------------------------------------------------------- /design_patterns/b_template/template.py: -------------------------------------------------------------------------------- 1 | """ 2 | An example of the Template pattern in Python 3 | 4 | Defines the skeleton of a base algorithm, deferring definition of exact 5 | steps to subclasses. 6 | 7 | Examples in Python ecosystem: 8 | Django class based views: https://docs.djangoproject.com/en/2.1/topics/class-based-views/ 9 | """ 10 | 11 | 12 | def get_text() -> str: 13 | return "plain-text" 14 | 15 | 16 | def get_pdf() -> str: 17 | return "pdf" 18 | 19 | 20 | def get_csv() -> str: 21 | return "csv" 22 | 23 | 24 | def convert_to_text(data: str) -> str: 25 | print("[CONVERT]") 26 | return f"{data} as text" 27 | 28 | 29 | def saver() -> None: 30 | print("[SAVE]") 31 | 32 | 33 | def template_function(getter, converter=False, to_save=False) -> None: 34 | data = getter() 35 | print(f"Got `{data}`") 36 | 37 | if len(data) <= 3 and converter: 38 | data = converter(data) 39 | else: 40 | print("Skip conversion") 41 | 42 | if to_save: 43 | saver() 44 | 45 | print(f"`{data}` was processed") 46 | 47 | 48 | def main(): 49 | template_function(get_text, to_save=True) 50 | """ 51 | Got `plain-text` 52 | Skip conversion 53 | [SAVE] 54 | `plain-text` was processed 55 | """ 56 | 57 | template_function(get_pdf, converter=convert_to_text) 58 | """ 59 | Got `pdf` 60 | [CONVERT] 61 | `pdf as text` was processed 62 | """ 63 | 64 | template_function(get_csv, to_save=True) 65 | """ 66 | Got `csv` 67 | Skip conversion 68 | [SAVE] 69 | `csv` was processed 70 | """ 71 | 72 | 73 | if __name__ == "__main__": 74 | main() 75 | -------------------------------------------------------------------------------- /design_patterns/b_visitor/visitor.py: -------------------------------------------------------------------------------- 1 | """ 2 | Adding new features to an existing hierarchy without changing its structure. 3 | """ 4 | 5 | 6 | class House(object): # The class being visited 7 | def accept(self, visitor): 8 | """Interface to accept a visitor""" 9 | visitor.visit(self) # Triggers the visiting operation! 10 | 11 | def work_on_hvac(self, hvac_specialist): 12 | print(self, "worked on by", 13 | hvac_specialist) # Note that we now have a reference to the HVAC specialist object in the house object! 14 | 15 | def work_on_electricity(self, electrician): 16 | print(self, "worked on by", 17 | electrician) # Note that we now have a reference to the electrician object in the house object! 18 | 19 | def __str__(self): 20 | """Simply return the class name when the House object is printed""" 21 | return self.__class__.__name__ 22 | 23 | 24 | class Visitor(object): 25 | """Abstract visitor""" 26 | 27 | def __str__(self): 28 | """Simply return the class name when the Visitor object is printed""" 29 | return self.__class__.__name__ 30 | 31 | 32 | class HvacSpecialist(Visitor): # Inherits from the parent class, Visitor 33 | """Concrete visitor: HVAC specialist""" 34 | 35 | def visit(self, house): 36 | house.work_on_hvac(self) # Note that the visitor now has a reference to the house object 37 | 38 | 39 | class Electrician(Visitor): # Inherits from the parent class, Visitor 40 | """Concrete visitor: electrician""" 41 | 42 | def visit(self, house): 43 | house.work_on_electricity(self) # Note that the visitor now has a reference to the house object 44 | 45 | 46 | # Create an HVAC specialist 47 | hv = HvacSpecialist() 48 | # Create an electrician 49 | e = Electrician() 50 | 51 | # Create a house 52 | home = House() 53 | 54 | # Let the house accept the HVAC specialist and work on the house by invoking the visit() method 55 | home.accept(hv) 56 | 57 | # Let the house accept the electrician and work on the house by invoking the visit() method 58 | home.accept(e) 59 | -------------------------------------------------------------------------------- /design_patterns/c_builder/builder.py: -------------------------------------------------------------------------------- 1 | """ 2 | Separating class from building complex object. 3 | Separating actual algorithm of creation of objects from actual object being created. 4 | 5 | Builder constructs/initializes object. 6 | Director knows how construct, concrete algorithm. 7 | 8 | Director 9 | .construct() -> open_file, parse_config, build_product, close_file 10 | Builder 11 | .open_file() 12 | .parse_config() 13 | .build_product() 14 | .close_file() 15 | 16 | ConcreteBuilder * concreteBuilder = new ConcreteBuilder(); 17 | Director * director = new Director(ConcreteBuilder); 18 | director->construct("myAssets.zip"); 19 | Product * product = concreteBuilder.getProduct(); 20 | 21 | Isn't is wonderful! Wow! 22 | 23 | https://github.com/faif/python-patterns/blob/master/patterns/creational/builder.py 24 | https://youtu.be/VCxNt2K7aVY?t=527 25 | """ 26 | from typing import Type 27 | 28 | 29 | class Car: 30 | """Product""" 31 | 32 | def __init__(self): 33 | self.model = None 34 | self.tires = None 35 | self.engine = None 36 | 37 | def __str__(self): 38 | return '{} | {} | {}'.format(self.model, self.tires, self.engine) 39 | 40 | 41 | class Director: 42 | """Director""" 43 | 44 | def __init__(self, builder): 45 | self._builder = builder 46 | 47 | def construct(self): 48 | self._builder.create_new_car() 49 | self._builder.add_model() 50 | self._builder.add_tires() 51 | self._builder.add_engine() 52 | 53 | 54 | class Builder: 55 | """Abstract Builder""" 56 | 57 | def __init__(self): 58 | self.car = None 59 | 60 | def create_new_car(self): 61 | self.car = Car() 62 | 63 | 64 | class SkyLarkBuilder(Builder): 65 | """Concrete Builder --> provides parts and tools to work on the parts""" 66 | 67 | def add_model(self): 68 | self.car.model = "Skylark" 69 | 70 | def add_tires(self): 71 | self.car.tires = "Regular tires" 72 | 73 | def add_engine(self): 74 | self.car.engine = "Turbo engine" 75 | 76 | def get_car(self) -> Type[Car]: 77 | """Get object method should be inside Concrete Builder method. 78 | Otherwise, we will lose all butty of Builder design pattern.""" 79 | return self.car 80 | 81 | 82 | if __name__ == "__main__": 83 | concrete_builder = SkyLarkBuilder() 84 | director = Director(concrete_builder) 85 | director.construct() 86 | car = concrete_builder.get_car() 87 | print(car) # Skylark | Regular tires | Turbo engine 88 | -------------------------------------------------------------------------------- /design_patterns/c_builder/with_builder_geeks_for_geeks.py: -------------------------------------------------------------------------------- 1 | # Abstract course 2 | class Course: 3 | def __init__(self): 4 | self.Fee() 5 | self.available_batches() 6 | 7 | def Fee(self): 8 | raise NotImplementedError 9 | 10 | def available_batches(self): 11 | raise NotImplementedError 12 | 13 | def __repr__(self): 14 | return f'1 Fee : {self.fee} | Batches Available : {self.batches}' 15 | 16 | 17 | # concrete course 18 | class DSA(Course): 19 | """Class for Data Structures and Algorithms""" 20 | 21 | def Fee(self): 22 | self.fee = 8000 23 | 24 | def available_batches(self): 25 | self.batches = 5 26 | 27 | def __str__(self): 28 | return "DSA" 29 | 30 | 31 | # concrete course 32 | class SDE(Course): 33 | """Class for Software Development Engineer""" 34 | 35 | def Fee(self): 36 | self.fee = 10000 37 | 38 | def available_batches(self): 39 | self.batches = 4 40 | 41 | def __str__(self): 42 | return "SDE" 43 | 44 | 45 | # concrete course 46 | class STL(Course): 47 | """Class for Standard Template Library""" 48 | 49 | def Fee(self): 50 | self.fee = 5000 51 | 52 | def available_batches(self): 53 | self.batches = 7 54 | 55 | def __str__(self): 56 | return "STL" 57 | 58 | 59 | # Complex Course 60 | class ComplexCourse: 61 | def __repr__(self): 62 | return 'Fee : {0.fee} | available_batches: {0.batches}'.format(self) 63 | 64 | 65 | # Complex course 66 | class Complexcourse(ComplexCourse): 67 | 68 | def Fee(self): 69 | self.fee = 7000 70 | 71 | def available_batches(self): 72 | self.batches = 6 73 | 74 | 75 | # construct course 76 | def construct_course(cls): 77 | course = cls() 78 | course.Fee() 79 | course.available_batches() 80 | 81 | return course # return the course object 82 | 83 | 84 | # main method 85 | if __name__ == "__main__": 86 | dsa = DSA() # object for DSA course 87 | sde = SDE() # object for SDE course 88 | stl = STL() # object for STL course 89 | 90 | complex_course = construct_course(Complexcourse) 91 | print(complex_course) 92 | -------------------------------------------------------------------------------- /design_patterns/c_builder/without_builder_geeks_for_geeks.py: -------------------------------------------------------------------------------- 1 | # concrete course 2 | class DSA(): 3 | """Class for Data Structures and Algorithms""" 4 | 5 | def Fee(self): 6 | self.fee = 8000 7 | return self.fee 8 | 9 | def available_batches(self): 10 | self.batches = 5 11 | 12 | def __str__(self): 13 | return "DSA" 14 | 15 | 16 | # concrete course 17 | class SDE(): 18 | """Class for Software development Engineer""" 19 | 20 | def Fee(self): 21 | self.fee = 10000 22 | return self.fee 23 | 24 | def available_batches(self): 25 | self.batches = 4 26 | 27 | def __str__(self): 28 | return "SDE" 29 | 30 | 31 | # concrete course 32 | class STL(): 33 | """class for Standard Template Library of C++""" 34 | 35 | def Fee(self): 36 | self.fee = 5000 37 | return self.fee 38 | 39 | def available_batches(self): 40 | self.batches = 7 41 | 42 | def __str__(self): 43 | return "STL" 44 | 45 | 46 | # main method 47 | if __name__ == "__main__": 48 | sde = SDE() # object for SDE 49 | dsa = DSA() # object for DSA 50 | stl = STL() # object for STL 51 | 52 | print(f'Name of Course: {sde} and its Fee: {sde.Fee()}') 53 | print(f'Name of Course: {stl} and its Fee: {stl.Fee()}') 54 | print(f'Name of Course: {dsa} and its Fee: {dsa.Fee()}') 55 | -------------------------------------------------------------------------------- /design_patterns/c_factory/abstact_factory.py: -------------------------------------------------------------------------------- 1 | """ 2 | Provides a way to encapsulate a group of individual factories. 3 | Creates object without specifying their actual class. 4 | 5 | In Python, the interface we use is simply a callable, which is "builtin" interface 6 | in Python, and in normal circumstances we can simply use the class itself as 7 | that callable, because classes are first class objects in Python. 8 | """ 9 | 10 | from typing import Type 11 | 12 | 13 | class Pet: 14 | def __init__(self, name: str) -> None: 15 | self.name = name 16 | 17 | def speak(self) -> None: 18 | raise NotImplementedError 19 | 20 | def __str__(self) -> str: 21 | raise NotImplementedError 22 | 23 | 24 | class Dog(Pet): 25 | def speak(self) -> None: 26 | print("woof") 27 | 28 | def __str__(self) -> str: 29 | return f"Dog<{self.name}>" 30 | 31 | 32 | class Cat(Pet): 33 | def speak(self) -> None: 34 | print("meow") 35 | 36 | def __str__(self) -> str: 37 | return f"Cat<{self.name}>" 38 | 39 | 40 | class PetStore: 41 | """Abstract Factory""" 42 | def __init__(self, pet_factory: Type[Pet]) -> None: 43 | """pet_factory is our Abstract Factory""" 44 | self._pet_factory = pet_factory 45 | 46 | def buy_pet(self, name: str) -> Pet: 47 | """Creates and shows a pet using the abstract factory""" 48 | pet = self._pet_factory(name) 49 | print(f"Here is your lovely {pet}") 50 | return pet 51 | 52 | 53 | if __name__ == "__main__": 54 | cat_store = PetStore(Cat) 55 | 56 | pet = cat_store.buy_pet("Lucy") # Here is your lovely Cat 57 | pet.speak() # meow 58 | -------------------------------------------------------------------------------- /design_patterns/c_factory/factory.py: -------------------------------------------------------------------------------- 1 | """ 2 | Factory Pattern is useful when you are not sure which types of objects you need in your system 3 | """ 4 | 5 | 6 | class Dog: 7 | def __init__(self, name): 8 | self._name = name 9 | 10 | def speak(self): 11 | return "Woof!" 12 | 13 | 14 | class Cat: 15 | def __init__(self, name): 16 | self._name = name 17 | 18 | def speak(self): 19 | return "Meow!" 20 | 21 | 22 | def get_pet(pet="dog"): 23 | """The factory method""" 24 | pets = dict(dog=Dog("Hope"), cat=Cat("Peace")) 25 | return pets[pet] 26 | 27 | 28 | if __name__ == "__main__": 29 | d = get_pet("dog") 30 | print(d.speak()) 31 | 32 | c = get_pet("cat") 33 | print(c.speak()) 34 | -------------------------------------------------------------------------------- /design_patterns/c_pool/pool.py: -------------------------------------------------------------------------------- 1 | """ 2 | Stores a set of initialized objects kept ready to use. 3 | 4 | 5 | This pattern is used when creating an object is costly (and they are 6 | created frequently) but only a few are used at a time. With a Pool we 7 | can manage those instances we have as of now by caching them. Now it 8 | is possible to skip the costly creation of an object if one is 9 | available in the pool. 10 | A pool allows to 'check out' an inactive object and then to return it. 11 | If none are available the pool creates one to provide without wait. 12 | 13 | http://stackoverflow.com/questions/1514120/python-implementation-of-the-object-pool-design-pattern 14 | https://sourcemaking.com/design_patterns/object_pool 15 | """ 16 | 17 | 18 | class ObjectPool: 19 | def __init__(self, queue, auto_get=False): 20 | self._queue = queue 21 | self.item = self._queue.get() if auto_get else None 22 | 23 | def __enter__(self): 24 | if self.item is None: 25 | self.item = self._queue.get() 26 | return self.item 27 | 28 | def __exit__(self, Type, value, traceback): 29 | if self.item is not None: 30 | self._queue.put(self.item) 31 | self.item = None 32 | 33 | def __del__(self): 34 | if self.item is not None: 35 | self._queue.put(self.item) 36 | self.item = None 37 | 38 | 39 | def main(): 40 | """ 41 | >>> import queue 42 | >>> def test_object(queue): 43 | ... pool = ObjectPool(queue, True) 44 | ... print('Inside func: {}'.format(pool.item)) 45 | >>> sample_queue = queue.Queue() 46 | >>> sample_queue.put('yam') 47 | >>> with ObjectPool(sample_queue) as obj: 48 | ... print('Inside with: {}'.format(obj)) 49 | Inside with: yam 50 | >>> print('Outside with: {}'.format(sample_queue.get())) 51 | Outside with: yam 52 | >>> sample_queue.put('sam') 53 | >>> test_object(sample_queue) 54 | Inside func: sam 55 | >>> print('Outside func: {}'.format(sample_queue.get())) 56 | Outside func: sam 57 | if not sample_queue.empty(): 58 | print(sample_queue.get()) 59 | """ 60 | 61 | 62 | if __name__ == "__main__": 63 | import doctest 64 | 65 | doctest.testmod() -------------------------------------------------------------------------------- /design_patterns/c_prototype/deep_copy_vs_shallow_copy.py: -------------------------------------------------------------------------------- 1 | import copy 2 | 3 | 4 | def print_xy(xs, ys): 5 | print(">>> xs", xs) 6 | print(">>> ys", ys) 7 | 8 | 9 | xs = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 10 | 11 | ys = copy.deepcopy(xs) # Make a shallow copy 12 | 13 | print_xy(xs, ys) 14 | 15 | ys.append(['new sublist']) 16 | 17 | print_xy(xs, ys) 18 | 19 | ys[1][0] = 'X' 20 | 21 | print_xy(xs, ys) 22 | 23 | -------------------------------------------------------------------------------- /design_patterns/c_prototype/prototype.py: -------------------------------------------------------------------------------- 1 | """ 2 | Making copying instead of building. 3 | 4 | Creating many identical objects individually - is expensive. 5 | Cloning is easy and fast. 6 | 7 | Solution by Prototype pattern: 8 | - Create a prototypical instance first 9 | - Clone when you need a replica 10 | 11 | Abstract Factory related to Prototype. 12 | """ 13 | 14 | import copy 15 | 16 | 17 | class Prototype: 18 | def __init__(self): 19 | self._objects = {} 20 | 21 | def register_object(self, name, obj): 22 | """Register an object""" 23 | self._objects[name] = obj 24 | 25 | def unregister_object(self, name): 26 | """Unregister an object""" 27 | del self._objects[name] 28 | 29 | def clone(self, name, **attr): 30 | """Clone a registered object and update its attributes""" 31 | obj = copy.deepcopy(self._objects.get(name)) 32 | obj.__dict__.update(attr) 33 | return obj 34 | 35 | 36 | class Car: 37 | def __init__(self): 38 | self.name = "Skylark" 39 | self.color = "Red" 40 | self.options = "Ex" 41 | 42 | def __str__(self): 43 | return '{} | {} | {}'.format(self.name, self.color, self.options) 44 | 45 | 46 | if __name__ == "__main__": 47 | c = Car() 48 | 49 | prototype = Prototype() 50 | prototype.register_object('skylark', c) 51 | 52 | c1 = prototype.clone('skylark') 53 | 54 | print(c1) # Skylark | Red | Ex 55 | print(id(c), id(c1)) # Different ids 56 | -------------------------------------------------------------------------------- /design_patterns/c_singleton/borg.py: -------------------------------------------------------------------------------- 1 | """ 2 | Singleton is used when you want to allow only one object to be instantiated from a class. 3 | 4 | Borg pattern making the class attributes global. 5 | There are multiple instances that share the same state. 6 | Sharing state instead of sharing instance. 7 | """ 8 | 9 | 10 | class Borg: 11 | _shared_data = {} # Class attribute dictionary 12 | 13 | def __init__(self): 14 | self.__dict__ = self._shared_data # Make it an attribute dictionary 15 | 16 | 17 | class Singleton(Borg): 18 | """This class now shares all its attributes among its various instances. 19 | This essentially makes the singleton objects an object-oriented global variable. 20 | """ 21 | def __init__(self, **kwargs): 22 | super().__init__() # Borg.__init__(self) 23 | self._shared_data.update(kwargs) # Update the attribute dictionary by inserting a new key-value pair 24 | 25 | def __str__(self): 26 | return str(self._shared_data) # Returns the attribute dictionary for printing 27 | 28 | 29 | if __name__ == "__main__": 30 | # Let's create a singleton object and add our first acronym 31 | x = Singleton(HTTP="Hyper Text Transfer Protocol") 32 | 33 | print(x) 34 | 35 | # Let's create another singleton object and if it refers to the same attribute dictionary by adding another acronym. 36 | y = Singleton(SNMP="Simple Network Management Protocol") 37 | 38 | print(y) 39 | -------------------------------------------------------------------------------- /design_patterns/c_singleton/borg_one_variable.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | 3 | 4 | class Borg: 5 | _shared_state: Dict[str, str] = {} 6 | 7 | def __init__(self): 8 | self.__dict__ = self._shared_state 9 | 10 | 11 | class YourBorg(Borg): 12 | def __init__(self, state=None): 13 | super().__init__() 14 | if state: 15 | self.state = state 16 | else: 17 | # initiate the first instance with default state 18 | if not hasattr(self, "state"): 19 | self.state = "Init" 20 | 21 | def __str__(self): 22 | return self.state 23 | 24 | 25 | def main(): 26 | """ 27 | >>> rm1 = YourBorg() 28 | >>> rm2 = YourBorg() 29 | >>> rm1.state = 'Idle' 30 | >>> rm2.state = 'Running' 31 | >>> print('rm1: {0}'.format(rm1)) 32 | rm1: Running 33 | >>> print('rm2: {0}'.format(rm2)) 34 | rm2: Running 35 | # When the `state` attribute is modified from instance `rm2`, 36 | # the value of `state` in instance `rm1` also changes 37 | >>> rm2.state = 'Zombie' 38 | >>> print('rm1: {0}'.format(rm1)) 39 | rm1: Zombie 40 | >>> print('rm2: {0}'.format(rm2)) 41 | rm2: Zombie 42 | # Even though `rm1` and `rm2` share attributes, the instances are not the same 43 | >>> rm1 is rm2 44 | False 45 | # New instances also get the same shared state 46 | >>> rm3 = YourBorg() 47 | >>> print('rm1: {0}'.format(rm1)) 48 | rm1: Zombie 49 | >>> print('rm2: {0}'.format(rm2)) 50 | rm2: Zombie 51 | >>> print('rm3: {0}'.format(rm3)) 52 | rm3: Zombie 53 | # A new instance can explicitly change the state during creation 54 | >>> rm4 = YourBorg('Running') 55 | >>> print('rm4: {0}'.format(rm4)) 56 | rm4: Running 57 | # Existing instances reflect that change as well 58 | >>> print('rm3: {0}'.format(rm3)) 59 | rm3: Running 60 | """ 61 | 62 | 63 | if __name__ == "__main__": 64 | import doctest 65 | 66 | doctest.testmod() 67 | -------------------------------------------------------------------------------- /design_patterns/c_singleton/singleton.py: -------------------------------------------------------------------------------- 1 | """ 2 | Singleton restricts a class from having more than one instance and ensures a global access point to this instance. 3 | 4 | Use case. Singleton helps 5 | - Manage a shared resource: i.e. a single database, file manager, or printer spooler shared by multiple parts of the application. 6 | - Store a global state (help filepath, user language, application path, etc.). 7 | - Create a simple logger. 8 | 9 | + Class has a single instance 10 | - Violates the SRP (Single Responsibility Principle). 11 | - It’s hard to unit test the code as the majority of test frameworks use inheritance when creating mock objects. 12 | """ 13 | 14 | 15 | class Singleton: 16 | def __new__(cls): 17 | if not hasattr(cls, 'instance'): 18 | cls.instance = super(Singleton, cls).__new__(cls) 19 | return cls.instance 20 | 21 | 22 | if __name__ == "__main__": 23 | s = Singleton() 24 | print("Object created:", s) 25 | 26 | s1 = Singleton() 27 | print("Object created:", s1) 28 | -------------------------------------------------------------------------------- /design_patterns/c_singleton/singleton_with_exception.py: -------------------------------------------------------------------------------- 1 | class Singleton: 2 | __instance = None 3 | 4 | @staticmethod 5 | def get_instance(): 6 | """ Static access method. """ 7 | if Singleton.__instance is None: 8 | Singleton() 9 | return Singleton.__instance 10 | 11 | def __init__(self): 12 | """ Virtually private constructor. """ 13 | if Singleton.__instance is not None: 14 | raise Exception("This class is a singleton!") 15 | else: 16 | Singleton.__instance = self 17 | 18 | 19 | s = Singleton() 20 | print(s) 21 | 22 | s = Singleton.get_instance() 23 | print(s) 24 | 25 | s = Singleton.get_instance() 26 | print(s) 27 | 28 | # The code below will raise Exception. 29 | # s2 = Singleton() 30 | # print(s2) 31 | -------------------------------------------------------------------------------- /design_patterns/delegation_pattern/delegator_pattern.py: -------------------------------------------------------------------------------- 1 | """ 2 | Allows object composition to achieve the same code reuse as inheritance. 3 | """ 4 | 5 | from __future__ import annotations 6 | 7 | from typing import Any, Callable 8 | 9 | 10 | class Delegator: 11 | """ 12 | >>> delegator = Delegator(Delegate()) 13 | >>> delegator.p1 14 | 123 15 | >>> delegator.p2 16 | Traceback (most recent call last): 17 | ... 18 | AttributeError: 'Delegate' object has no attribute 'p2' 19 | >>> delegator.do_something("nothing") 20 | 'Doing nothing' 21 | >>> delegator.do_anything() 22 | Traceback (most recent call last): 23 | ... 24 | AttributeError: 'Delegate' object has no attribute 'do_anything' 25 | """ 26 | 27 | def __init__(self, delegate: Delegate): 28 | self.delegate = delegate 29 | 30 | def __getattr__(self, name: str) -> Any | Callable: 31 | attr = getattr(self.delegate, name) 32 | 33 | if not callable(attr): 34 | return attr 35 | 36 | def wrapper(*args, **kwargs): 37 | return attr(*args, **kwargs) 38 | 39 | return wrapper 40 | 41 | 42 | class Delegate: 43 | def __init__(self): 44 | self.p1 = 123 45 | 46 | def do_something(self, something: str) -> str: 47 | return f"Doing {something}" 48 | -------------------------------------------------------------------------------- /design_patterns/s_adapter/adapter.py: -------------------------------------------------------------------------------- 1 | """ 2 | Adapter pattern - making the incompatible objects adaptable to each other. 3 | Converts the interface of a class into another one that a client is expecting. 4 | 5 | For example, Adapter could help convert XML data format to JSON for further analysis. 6 | 7 | + Allows separating the interface from business logic. 8 | + Adding new adapters doesn’t break the client’s code 9 | - Increases the code complexity 10 | 11 | Bridge and decorator related to Adapter pattern. 12 | """ 13 | 14 | 15 | class Target: 16 | def request(self): 17 | return "Target: The default target's behavior." 18 | 19 | 20 | class Adaptee: 21 | def specific_request(self): 22 | return ".eetpadA eht fo roivaheb laicepS" 23 | 24 | 25 | class Adapter(Target, Adaptee): 26 | def request(self): 27 | return f"Adapter: (TRANSLATED) {self.specific_request()[::-1]}" 28 | 29 | 30 | def client_code(target: "Target"): 31 | print(target.request()) 32 | 33 | 34 | def main(): 35 | print("Client: I can work just fine with the Target objects:") 36 | 37 | target = Target() 38 | client_code(target) 39 | 40 | adaptee = Adaptee() 41 | 42 | print("Client: The Adaptee class has a weird interface. " 43 | "See, I don't understand it:") 44 | print(f"Adaptee: {adaptee.specific_request()}") 45 | 46 | print("Client: But I can work with it via the Adapter:") 47 | 48 | adapter = Adapter() 49 | client_code(adapter) 50 | 51 | 52 | if __name__ == "__main__": 53 | main() 54 | -------------------------------------------------------------------------------- /design_patterns/s_adapter/adapter2.py: -------------------------------------------------------------------------------- 1 | """ 2 | Here the problem is that Korean has speak_korean() but British has speak_english(). 3 | """ 4 | 5 | class Korean: 6 | """Korean speaker""" 7 | 8 | def __init__(self): 9 | self.name = "Korean" 10 | 11 | def speak_korean(self): 12 | return "An-neyong?" 13 | 14 | 15 | class British: 16 | """English speaker""" 17 | 18 | def __init__(self): 19 | self.name = "British" 20 | 21 | # Note the different method name here! 22 | def speak_english(self): 23 | return "Hello!" 24 | 25 | 26 | class Adapter: 27 | """This changes the generic method name to individualized method names""" 28 | 29 | def __init__(self, adapter_object, **adapted_method): 30 | """Change the name of the method""" 31 | self._object = adapter_object 32 | 33 | # Add a new dictionary item that establishes the mapping between the generic method name: speak() and the 34 | # concrete method For example, speak() will be translated to speak_korean() if the mapping says so 35 | self.__dict__.update(adapted_method) 36 | 37 | def __getattr__(self, attr): 38 | """Simply return the rest of attributes!""" 39 | return getattr(self._object, attr) 40 | 41 | def original_dict(self): 42 | """Print original object dict""" 43 | return self._object.__dict__ 44 | 45 | 46 | def main(): 47 | objects = [] # List to store speaker objects 48 | 49 | korean = Korean() 50 | british = British() 51 | 52 | objects.append(Adapter(korean, speak=korean.speak_korean)) # Later speak() will be used to access the speak_korean 53 | objects.append(Adapter(british, speak=british.speak_english)) 54 | 55 | # print(Adapter(korean, speak=korean.speak_korean).original_dict()) 56 | 57 | for obj in objects: 58 | print(f"{obj.name} says {obj.speak()}") 59 | 60 | 61 | if __name__ == "__main__": 62 | main() 63 | -------------------------------------------------------------------------------- /design_patterns/s_bridge/bridge.py: -------------------------------------------------------------------------------- 1 | """ 2 | Bridge pattern helps untangle (распутывать) an unnecessary complicated class hierarchy. 3 | When implementation of specific classes, are mixed with implementation of independent classes. 4 | 5 | Problem: 6 | - Unrelated parallel abstraction 7 | - Implementation specific abstraction, implementation independent abstraction 8 | 9 | Scenario: 10 | - Implementation-independent circle abstraction, (properties of circle, and how scale it) 11 | - Implementation-dependent circle abstraction, (how to draw a circle) 12 | 13 | Solution: 14 | - Separate the abstraction into two different class hierarchies 15 | 16 | Abstract factory and adapter are related to bridge pattern. 17 | """ 18 | 19 | 20 | class DrawingAPIOne(object): 21 | """Implementation-specific abstraction: concrete class one""" 22 | 23 | def draw_circle(self, x, y, radius): 24 | print("API 1 drawing a circle at ({}, {} with radius {}!)".format(x, y, radius)) 25 | 26 | 27 | class DrawingAPITwo(object): 28 | """Implementation-specific abstraction: concrete class two""" 29 | 30 | def draw_circle(self, x, y, radius): 31 | print("API 2 drawing a circle at ({}, {} with radius {}!)".format(x, y, radius)) 32 | 33 | 34 | class Circle(object): 35 | """Implementation-independent abstraction: for example, there could be a rectangle class!""" 36 | 37 | def __init__(self, x, y, radius, drawing_api): 38 | """Initialize the necessary attributes""" 39 | self._x = x 40 | self._y = y 41 | self._radius = radius 42 | self._drawing_api = drawing_api 43 | 44 | def draw(self): 45 | """Implementation-specific abstraction taken care of by another class: DrawingAPI""" 46 | self._drawing_api.draw_circle(self._x, self._y, self._radius) 47 | 48 | def scale(self, percent): 49 | """Implementation-independent""" 50 | self._radius *= percent 51 | 52 | 53 | # Build the first Circle object using API One 54 | circle1 = Circle(1, 2, 3, DrawingAPIOne()) 55 | # Draw a circle 56 | circle1.draw() 57 | 58 | # Build the second Circle object using API Two 59 | circle2 = Circle(2, 3, 4, DrawingAPITwo()) 60 | # Draw a circle 61 | circle2.draw() 62 | -------------------------------------------------------------------------------- /design_patterns/s_composite/composite.py: -------------------------------------------------------------------------------- 1 | """ 2 | TREE Data Structure. 3 | Describes a group of objects that is treated the same way as a single instance of the same type of the objects. 4 | 5 | Problem: 6 | - We have a Menu 7 | - We have a Submenu for menu items 8 | 9 | Solution: 10 | - Component (Abstract class) 11 | - Child (Concrete class), inherits from Component 12 | - Composite (Concrete class), inherits from Component 13 | - child objects (to, from) 14 | """ 15 | 16 | from abc import ABC, abstractmethod 17 | 18 | 19 | class Component(ABC): 20 | def __init__(self, *args, **kwargs): 21 | ... 22 | 23 | @abstractmethod 24 | def component_function(self): 25 | ... 26 | 27 | 28 | class Child(Component): 29 | def __init__(self, *args, **kwargs): 30 | super().__init__(*args, **kwargs) 31 | self.name = args[0] 32 | 33 | def component_function(self): 34 | print("{}".format(self.name)) 35 | 36 | 37 | class Composite(Component): 38 | """Concrete class and maintains the tree recursive structure""" 39 | def __init__(self, *args, **kwargs): 40 | # Component.__init__(self, *args, **kwargs) 41 | super().__init__(*args, **kwargs) 42 | 43 | # This is where we store the name of the composite object 44 | self.name = args[0] # First argument is the "name" 45 | 46 | # This is where we keep our child items 47 | self.children = [] 48 | 49 | def append_child(self, child): 50 | self.children.append(child) 51 | 52 | def remove_child(self, child): 53 | self.children.remove(child) 54 | 55 | def component_function(self): 56 | # Print the name of the composite object 57 | print("{}".format(self.name)) 58 | # print(self.children) # Just for debugging purposes 59 | 60 | # Iterate through the child objects and invoke their component function printing their names 61 | for i in self.children: 62 | i.component_function() 63 | 64 | 65 | def main(): 66 | # Submenu 1 with its sub-submenus 67 | sub1 = Composite("submenu1") 68 | sub11 = Child("sub_submenu 11") 69 | sub12 = Child("sub_submenu 12") 70 | sub1.append_child(sub11) 71 | sub1.append_child(sub12) 72 | 73 | # Submenu 2 74 | sub2 = Child("submenu2") 75 | 76 | # Top menu 77 | top = Composite("top_menu") 78 | top.append_child(sub1) 79 | top.append_child(sub2) 80 | top.component_function() 81 | # top_menu 82 | # submenu1 83 | # sub_submenu 84 | # 11 85 | # sub_submenu 86 | # 12 87 | # submenu2 88 | 89 | 90 | if __name__ == "__main__": 91 | main() 92 | -------------------------------------------------------------------------------- /design_patterns/s_decorator/decorator.py: -------------------------------------------------------------------------------- 1 | """ 2 | Decorator attaches new behaviors to the objects without modifying their structure. 3 | 4 | + Changes the object behavior without creating a subclass. 5 | + You can combine several behaviors by wrapping an object into multiple decorators. 6 | 7 | Problem: 8 | - Add new feature to an existing object 9 | - Dynamic changes 10 | - Without subclasses 11 | 12 | Solution: 13 | - Built-in decorator 14 | """ 15 | 16 | from functools import wraps 17 | 18 | 19 | def make_blink(function): 20 | """Defines the decorator""" 21 | 22 | # This makes the decorator transparent in terms of its name and docstring 23 | @wraps(function) 24 | # Define the inner function 25 | def decorator(*args, **kwargs): 26 | # Grab the return value of the function being decorated 27 | ret = function(*args, **kwargs) 28 | 29 | # Add new functionality to the function being decorated 30 | return "" + ret + "" 31 | 32 | return decorator 33 | 34 | 35 | # Apply the decorator here! 36 | @make_blink 37 | def hello_world(): 38 | """Original function! """ 39 | return "Hello, World!" 40 | 41 | 42 | # Check the result of decorating 43 | print(hello_world()) 44 | 45 | # Check if the function name is still the same name of the function being decorated 46 | print(hello_world.__name__) 47 | 48 | # Check if the docstring is still the same as that of the function being decorated 49 | print(hello_world.__doc__) 50 | -------------------------------------------------------------------------------- /design_patterns/s_decorator/decorator_as_class.py: -------------------------------------------------------------------------------- 1 | class my_decorator: 2 | def __init__(self, func): 3 | print("inside my_decorator.__init__()") 4 | self.function = func 5 | 6 | def __call__(self, *args, **kwargs): 7 | result = self.function(*args, **kwargs) # Prove that function definition has completed 8 | print("inside my_decorator.__call__() that returns", result) 9 | 10 | 11 | @my_decorator 12 | def my_function(name, message='Hello'): 13 | print("{}, {}".format(message, name)) 14 | return 49 15 | 16 | 17 | if __name__ == "__main__": 18 | my_function("Rustam") 19 | -------------------------------------------------------------------------------- /design_patterns/s_decorator/decorator_with_args.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | 3 | 4 | def repeat(num_times): 5 | def decorator_repeat(func): 6 | @wraps(func) 7 | def wrapper_repeat(*args, **kwargs): 8 | for _ in range(num_times): 9 | value = func(*args, **kwargs) 10 | return value 11 | return wrapper_repeat 12 | return decorator_repeat 13 | 14 | 15 | @repeat(num_times=4) 16 | def greet(name): 17 | print(f"Hello {name}") 18 | 19 | 20 | greet("World") 21 | -------------------------------------------------------------------------------- /design_patterns/s_facade/facade.py: -------------------------------------------------------------------------------- 1 | """ 2 | Facade provides a simplified yet limited interface to decrease the complexity of an application. 3 | Complex subsystems with multiple moving parts could be “masked” by Facade. 4 | 5 | Use case. Create the Facade class in case you work with complex libraries & APIs and you need only the part of their functionality. 6 | 7 | + System complexity is separated from the code 8 | - Using the Facade pattern, you can create a god object. 9 | 10 | https://jellyfish.tech/blog/implementation-of-common-design-patterns-in-python/ 11 | """ 12 | 13 | 14 | class Addition: 15 | def __init__(self, field1: int, field2: int): 16 | self.field1 = field1 17 | self.field2 = field2 18 | 19 | def get_result(self): 20 | return self.field1 + self.field2 21 | 22 | 23 | class Multiplication: 24 | def __init__(self, field1: int, field2: int): 25 | self.field1 = field1 26 | self.field2 = field2 27 | 28 | def get_result(self): 29 | return self.field1 * self.field2 30 | 31 | 32 | class Subtraction: 33 | def __init__(self, field1: int, field2: int): 34 | self.field1 = field1 35 | self.field2 = field2 36 | 37 | def get_result(self): 38 | return self.field1 - self.field2 39 | 40 | 41 | class Facade: 42 | @staticmethod 43 | def make_addition(*args) -> Addition: 44 | return Addition(*args) 45 | 46 | @staticmethod 47 | def make_multiplication(*args) -> Multiplication: 48 | return Multiplication(*args) 49 | 50 | @staticmethod 51 | def make_subtraction(*args) -> Subtraction: 52 | return Subtraction(*args) 53 | 54 | 55 | if __name__ == "__main__": 56 | addition_obj = Facade.make_addition(5, 5) 57 | multiplication_obj = Facade.make_multiplication(5, 2) 58 | subtraction_obj = Facade.make_subtraction(15, 5) 59 | 60 | print(addition_obj.get_result()) 61 | print(multiplication_obj.get_result()) 62 | print(subtraction_obj.get_result()) 63 | -------------------------------------------------------------------------------- /design_patterns/s_flyweight/flyweight.py: -------------------------------------------------------------------------------- 1 | """ 2 | Reuses existing instances of objects with similar/identical state 3 | Minimises memory usage by sharing data with other similar objects. 4 | 5 | http://codesnipers.com/?q=python-flyweights 6 | https://python-patterns.guide/gang-of-four/flyweight/ 7 | """ 8 | 9 | import weakref 10 | 11 | 12 | class Card: 13 | """The Flyweight""" 14 | 15 | # Could be a simple dict. 16 | # With WeakValueDictionary garbage collection can reclaim the object 17 | # when there are no other references to it. 18 | _pool: weakref.WeakValueDictionary = weakref.WeakValueDictionary() 19 | 20 | def __new__(cls, value, suit): 21 | # If the object exists in the pool - just return it 22 | obj = cls._pool.get(value + suit) 23 | # otherwise - create new one (and add it to the pool) 24 | if obj is None: 25 | obj = object.__new__(Card) 26 | cls._pool[value + suit] = obj 27 | # This row does the part we usually see in `__init__` 28 | obj.value, obj.suit = value, suit 29 | return obj 30 | 31 | # If you uncomment `__init__` and comment-out `__new__` - 32 | # Card becomes normal (non-flyweight). 33 | # def __init__(self, value, suit): 34 | # self.value, self.suit = value, suit 35 | 36 | def __repr__(self): 37 | return f"" 38 | 39 | 40 | def main(): 41 | """ 42 | >>> c1 = Card('9', 'h') 43 | >>> c2 = Card('9', 'h') 44 | >>> c1, c2 45 | (, ) 46 | >>> c1 == c2 47 | True 48 | >>> c1 is c2 49 | True 50 | >>> c1.new_attr = 'temp' 51 | >>> c3 = Card('9', 'h') 52 | >>> hasattr(c3, 'new_attr') 53 | True 54 | >>> Card._pool.clear() 55 | >>> c4 = Card('9', 'h') 56 | >>> hasattr(c4, 'new_attr') 57 | False 58 | """ 59 | 60 | 61 | if __name__ == "__main__": 62 | import doctest 63 | 64 | doctest.testmod() 65 | -------------------------------------------------------------------------------- /design_patterns/s_proxy/proxy.py: -------------------------------------------------------------------------------- 1 | """ 2 | Proxy is used in places where you want to add functionality to a class without changing its interface. 3 | 4 | Proxy controls access to an object, while decorator adds responsibilities. 5 | Decorator informs and empowers its client. 6 | Proxy restricts and dis-empowers its client. 7 | """ 8 | import time 9 | 10 | 11 | class Producer: 12 | """Define the 'resource-intensive' object to instantiate!""" 13 | 14 | def produce(self): 15 | print("Producer is working hard!") 16 | 17 | def meet(self): 18 | print("Producer has time to meet you now!") 19 | 20 | 21 | class Proxy: 22 | """"Define the 'relatively less resource-intensive' proxy to instantiate as a middleman""" 23 | 24 | def __init__(self): 25 | self.occupied = 'No' 26 | self.producer = None 27 | 28 | def produce(self): 29 | """Check if Producer is available""" 30 | print("Artist checking if Producer is available ...") 31 | 32 | if self.occupied == 'No': 33 | # If the producer is available, create a producer object! 34 | self.producer = Producer() 35 | time.sleep(2) 36 | 37 | # Make the producer meet the guest! 38 | self.producer.meet() 39 | 40 | else: 41 | # Otherwise, don't instantiate a producer 42 | time.sleep(2) 43 | print("Producer is busy!") 44 | 45 | 46 | # Instantiate a Proxy 47 | p = Proxy() 48 | 49 | # Make the proxy: Artist produce until Producer is available 50 | p.produce() 51 | 52 | # Change the state to 'occupied' 53 | p.occupied = 'Yes' 54 | 55 | # Make the Producer produce 56 | p.produce() 57 | -------------------------------------------------------------------------------- /solid/1_single_responsibility_principle.py: -------------------------------------------------------------------------------- 1 | """ 2 | Single Responsibility Principle 3 | - A class should have only one reason to change. 4 | 5 | Let's say we have a class that has 3 responsibilities: 6 | - Creates a new entity (e.g. a class) 7 | - Stores data into database 8 | - Includes business logic 9 | It is not a good idea to have all three responsibilities in one class. In the future we can change our database or business logic. 10 | And we don't want to touch a class that is responsible for creating an entity. 11 | 12 | So, we should split the class into 3 classes: 13 | - A class that creates an entity 14 | - A class that stores data into database 15 | - A class that includes business logic 16 | """ 17 | from dataclasses import dataclass 18 | from typing import List 19 | 20 | 21 | class DjangoOrm: 22 | """This is the c_singleton class used to create a connection with DB.""" 23 | def __init__(self, db_path: str): 24 | self.db_path = db_path 25 | 26 | def connect(self): 27 | return Connection() 28 | 29 | 30 | @dataclass 31 | class Animal: 32 | """ 33 | Entity class. 34 | """ 35 | name: str 36 | age: int 37 | category: str 38 | 39 | @property 40 | def category(self): 41 | return self._category 42 | 43 | @category.setter 44 | def category(self, value: str) -> None: 45 | if value not in ['mammal', 'bird', 'reptile']: 46 | raise ValueError('Invalid category') 47 | self._category = value 48 | 49 | 50 | class AnimalRepository: 51 | """ 52 | DAO - Data Access Object. 53 | Responsible for storing data into database. 54 | It is good to make it interface, and inherit PROD and TEST classes from it. 55 | """ 56 | 57 | def __init__(self, database: DjangoOrm): 58 | self.database = database 59 | 60 | def save(self, animal: Animal) -> bool: 61 | """If save is successful, save() returns True, else False.""" 62 | ... 63 | 64 | def get(self, name: str) -> Animal: 65 | ... 66 | 67 | def delete(self, name: str) -> bool: 68 | """If delete is successful, save() returns True, else False.""" 69 | ... 70 | 71 | def update(self, animal: Animal) -> bool: 72 | """If update is successful, save() returns True, else False.""" 73 | ... 74 | 75 | 76 | class AnimalBusinessLogic: 77 | """ 78 | DTO - Data Transfer Object. 79 | BusinessLogic - responsible for business logic. 80 | """ 81 | 82 | def __init__(self, animal_repository: AnimalRepository): 83 | self.animal_repository = animal_repository 84 | 85 | def get_animals_by_age(self) -> List[Animal]: 86 | ... 87 | 88 | def get_average_age_by_category(self, category: str) -> List[Animal]: 89 | ... 90 | 91 | 92 | if __name__ == "__main__": 93 | orm = DjangoOrm("the_path_to_db").connect() # It should be c_singleton because many repositories will use the same database. 94 | animal_repository = AnimalRepository(orm) 95 | animal_business_logic = AnimalBusinessLogic(animal_repository) 96 | animal = Animal(name="Bobik", age=5, category='mammal') # Create an animal. 97 | animal_repository.save(animal) # Save it into database. 98 | animals_list = animal_business_logic.get_animals_by_age() # Get all animals by age. 99 | -------------------------------------------------------------------------------- /solid/2_open_closed_principle.py: -------------------------------------------------------------------------------- 1 | """ 2 | Open Closed Principle 3 | - Software entities (classes, modules, functions) should be open for extension, but closed for modification. 4 | - Don't check for object type, don't use if/else, but use Polymorphism instead. 5 | 6 | https://www.youtube.com/watch?v=aWAmScEixoE 7 | https://www.pythontutorial.net/python-oop/python-open-closed-principle/ 8 | https://github.com/heykarimoff/solid.python/blob/master/2.ocp.py 9 | 10 | If you want to add new features in the future, you should implement the abstract class. 11 | In our example, Animal class is abstract, it is open for extensions such as Snake, Lion and Mice. 12 | """ 13 | 14 | from abc import ABC, abstractmethod 15 | 16 | 17 | class Animal(ABC): 18 | def __init__(self, name: str): 19 | self.name = name 20 | 21 | def get_name(self) -> str: 22 | ... 23 | 24 | @abstractmethod 25 | def make_sound(self) -> str: 26 | pass 27 | 28 | 29 | class Lion(Animal): 30 | def make_sound(self) -> str: 31 | return 'roar' 32 | 33 | 34 | class Mouse(Animal): 35 | def make_sound(self) -> str: 36 | return 'squeak' 37 | 38 | 39 | class Snake(Animal): 40 | def make_sound(self) -> str: 41 | return 'hiss' 42 | 43 | 44 | def get_animal(name: str) -> Animal: 45 | """The c_factory method""" 46 | animals = dict(dog=Lion("Asad"), cat=Mouse("Nizo"), snake=Snake("Rust")) 47 | return animals[name] 48 | 49 | 50 | # It is the function where show how to use OCP 51 | def animal_sound(animal: Animal): 52 | return animal.make_sound() 53 | 54 | 55 | def main(): 56 | animal = get_animal("snake") 57 | print(animal_sound(animal)) 58 | 59 | 60 | if __name__ == "__main__": 61 | main() 62 | 63 | -------------------------------------------------------------------------------- /solid/3_liskov_substitution_principle.py: -------------------------------------------------------------------------------- 1 | """ 2 | Liskov Substitution Principle. 3 | - A subclass must be substitutable for its super-class. The aim of this 4 | principle is to ascertain that a subclass can assume the place of its 5 | super-class without errors. If the code finds itself checking the type of class 6 | then, it must have violated this principle. 7 | 8 | https://www.pythontutorial.net/python-oop/python-liskov-substitution-principle/ 9 | """ 10 | 11 | 12 | from abc import ABC, abstractmethod 13 | 14 | 15 | class Contact: 16 | def __init__(self, name, email, phone): 17 | self.name = name 18 | self.email = email 19 | self.phone = phone 20 | 21 | 22 | class Notification(ABC): 23 | @abstractmethod 24 | def notify(self, message): 25 | pass 26 | 27 | 28 | class Email(Notification): 29 | def __init__(self, email): 30 | self.email = email 31 | 32 | def notify(self, message): 33 | print(f'Send "{message}" to {self.email}') 34 | 35 | 36 | class SMS(Notification): 37 | def __init__(self, phone): 38 | self.phone = phone 39 | 40 | def notify(self, message): 41 | print(f'Send "{message}" to {self.phone}') 42 | 43 | 44 | class NotificationManager: 45 | def __init__(self, notification): 46 | self.notification = notification 47 | 48 | def send(self, message): 49 | self.notification.notify(message) 50 | 51 | 52 | def main_good_example(): 53 | contact = Contact('John Doe', 'john@test.com', '(408)-888-9999') 54 | 55 | sms_notification = SMS(contact.phone) 56 | email_notification = Email(contact.email) 57 | 58 | notification_manager = NotificationManager(sms_notification) 59 | notification_manager.send('Hello John') 60 | 61 | notification_manager.notification = email_notification 62 | notification_manager.send('Hi John') 63 | 64 | 65 | if __name__ == '__main__': 66 | main_good_example() 67 | -------------------------------------------------------------------------------- /solid/4_interface_segregation_principle.py: -------------------------------------------------------------------------------- 1 | """ 2 | Interface Segregation Principle 3 | 4 | - A client should depend on the smallest set of interface features: the fewest methods and attributes. 5 | - Make fine-grained interfaces that are client-specific. Clients should not be forced to implement interfaces they do not use. 6 | - In OOP, an interface is a set of methods an object MUST have. 7 | """ 8 | from abc import ABC, abstractmethod 9 | 10 | 11 | class Movable(ABC): 12 | @abstractmethod 13 | def go(self): 14 | pass 15 | 16 | 17 | class Flyable(Movable): 18 | @abstractmethod 19 | def fly(self): 20 | pass 21 | 22 | 23 | class Car(Movable): 24 | def go(self): 25 | print("Going") 26 | 27 | 28 | class Aircraft(Flyable): 29 | def go(self): 30 | print("Taxiing") 31 | 32 | def fly(self): 33 | print("Flying") 34 | 35 | 36 | def main(): 37 | car = Car() 38 | car.go() 39 | 40 | aircraft = Aircraft() 41 | aircraft.go() 42 | aircraft.fly() 43 | 44 | 45 | if __name__ == "__main__": 46 | main() 47 | -------------------------------------------------------------------------------- /solid/5_dependency_inversion_principle.py: -------------------------------------------------------------------------------- 1 | """ 2 | Dependency Inversion Principle 3 | - High-level modules should not depend on low-level modules. Both should depend on abstractions. 4 | - Abstractions should not depend on details. Details should depend on abstractions. 5 | 6 | Use the dependency inversion principle to make your code more robust by making the high-level module dependent on the abstraction, not the concrete implementation. 7 | 8 | Dependency Injection is an implementation technique for populating instance variables of a class. 9 | Dependency Inversion is a general design guideline which recommends that classes should only have direct relationships with high-level abstractions. 10 | """ 11 | 12 | 13 | from abc import ABC 14 | 15 | 16 | class CurrencyConverter(ABC): 17 | def convert(self, from_currency, to_currency, amount) -> float: 18 | pass 19 | 20 | 21 | class FXConverter(CurrencyConverter): 22 | def convert(self, from_currency, to_currency, amount) -> float: 23 | print('Converting currency using FX API') 24 | print(f'{amount} {from_currency} = {amount * 1.2} {to_currency}') 25 | return amount * 2 26 | 27 | 28 | class AlphaConverter(CurrencyConverter): 29 | def convert(self, from_currency, to_currency, amount) -> float: 30 | print('Converting currency using Alpha API') 31 | print(f'{amount} {from_currency} = {amount * 1.2} {to_currency}') 32 | return amount * 1.15 33 | 34 | 35 | class App: 36 | def __init__(self, converter: CurrencyConverter): 37 | self.converter = converter 38 | 39 | def start(self): 40 | self.converter.convert('EUR', 'USD', 100) 41 | 42 | 43 | def main(): 44 | # FXConverter 45 | converter = FXConverter() 46 | app = App(converter) 47 | app.start() 48 | 49 | # AlphaConverter 50 | converter = AlphaConverter() 51 | app = App(converter) 52 | app.start() 53 | 54 | 55 | if __name__ == '__main__': 56 | main() 57 | -------------------------------------------------------------------------------- /solid/BAD_liskov_substitution_principle.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | 4 | class Notification(ABC): 5 | @abstractmethod 6 | def notify(self, message, email): 7 | pass 8 | 9 | 10 | class Email(Notification): 11 | def notify(self, message, email): 12 | print(f'Send {message} to {email}') 13 | 14 | 15 | class SMS(Notification): 16 | def notify(self, message, phone): 17 | print(f'Send {message} to {phone}') 18 | 19 | 20 | class Contact: 21 | def __init__(self, name, email, phone): 22 | self.name = name 23 | self.email = email 24 | self.phone = phone 25 | 26 | 27 | class NotificationManager: 28 | def __init__(self, notification, contact): 29 | self.contact = contact 30 | self.notification = notification 31 | 32 | def send(self, message): 33 | if isinstance(self.notification, Email): 34 | self.notification.notify(message, contact.email) 35 | elif isinstance(self.notification, SMS): 36 | self.notification.notify(message, contact.phone) 37 | else: 38 | raise Exception('The notification is not supported') 39 | 40 | 41 | if __name__ == '__main__': 42 | contact = Contact('John Doe', 'john@test.com', '(408)-888-9999') 43 | notification = SMS() 44 | notification_manager = NotificationManager(notification, contact) 45 | notification_manager.send('Hello John') 46 | -------------------------------------------------------------------------------- /solid/BAD_open_closed_principle.py: -------------------------------------------------------------------------------- 1 | class Animal: 2 | def __init__(self, name: str): 3 | self.name = name 4 | 5 | def get_name(self) -> str: 6 | pass 7 | 8 | 9 | animals = [ 10 | Animal('lion'), 11 | Animal('mouse') 12 | ] 13 | 14 | 15 | def animal_sound(animals: list): 16 | for animal in animals: 17 | if animal.name == 'lion': 18 | print('roar') 19 | 20 | elif animal.name == 'mouse': 21 | print('squeak') 22 | 23 | 24 | animal_sound(animals) 25 | 26 | 27 | """ 28 | If we don't follow OCP then we could have one function with many if elses for all type of animals. 29 | And if we add the new animal we must edit that function. 30 | 31 | Like following: 32 | """ 33 | 34 | 35 | animals = [ 36 | Animal('lion'), 37 | Animal('mouse'), 38 | Animal('snake') 39 | ] 40 | 41 | 42 | def animal_sound(animals: list): 43 | for animal in animals: 44 | if animal.name == 'lion': 45 | print('roar') 46 | elif animal.name == 'mouse': 47 | print('squeak') 48 | elif animal.name == 'snake': 49 | print('hiss') 50 | 51 | animal_sound(animals) 52 | -------------------------------------------------------------------------------- /solid/README.md: -------------------------------------------------------------------------------- 1 | # Python S.O.L.I.D Principles - Create more classes 2 | 3 | ### Why follow SOLID? 4 | - Use SOLID principles to address design deficiencies 5 | - Some problems without SOLID 6 | - Mixed responsibility 7 | - Missing responsibility 8 | - Limited reuse potential 9 | - Not substitutable 10 | 11 | ### S.O.L.I.D - Order doesn't matter 12 | 1. Interface segregation 13 | 1. Helps design good classes 14 | 2. Helps write unit test cases 15 | 3. Asks you to create a different interface for different responsibilities, in other words, don't group unrelated behavior in one interface, You break ISP if You have already an interface with many responsibilities, and the implementor doesn't need all this stuff. 16 | 4. [https://stackoverflow.com/questions/54480725/the-difference-between-liskov-substitution-principle-and-interface-segregation-p](https://stackoverflow.com/questions/54480725/the-difference-between-liskov-substitution-principle-and-interface-segregation-p) 17 | 2. Liskov substitution - how subclasses extend superclasses 18 | 1. This principle asks you to make sure that all child classes have the same behavior as the parent class. Object of superclass S can be replaced with objects of any subclass of S. 19 | 2. Helps design good polymorphism 20 | 3. Ex: Square-Rectangle Problem 21 | 3. Open/closed - tuning the design 22 | 1. Open to extension means adding subclasses a needed 23 | 2. Closed to modification avoids "tweaking" the code to handle new situations 24 | 3. A**llow its behavior to be extended without modifying its source code. Factory → we need to update the objects list only, method names are the same.** 25 | 4. Dependency inversion - based on packaging the code. Decrease the dependency on another concrete class. 26 | 1. A direct dependency on a concrete class needs to be "inverted" 27 | 2. Depend on abstraction classes 28 | 3. Avoid concrete class name dependencies 29 | 5. Single responsibility - summary of other 4 principles 30 | 1. One responsibility per class. 31 | 2. "A class should have one reason to change" 32 | 3. Note!! "Single" at what level of abstraction? How are the responsibilities counter? 33 | 34 | ### Other OO Principle 35 | - Don't repeat yourself (DRY) 36 | - General responsibility assignment software principles (GRASP) 37 | - Test-driven development (TDD) 38 | 39 | ## Resources 40 | - https://github.com/heykarimoff/solid.python/ 41 | - https://www.linkedin.com/learning/learning-s-o-l-i-d-programming-principles 42 | - https://www.pythontutorial.net/python-oop/python-single-responsibility-principle/ 43 | --------------------------------------------------------------------------------