From 7fa2bf9f0fcaa52df24ac8d2fc45897aa6b870ec Mon Sep 17 00:00:00 2001 From: tteodorescu0 Date: Wed, 26 Jun 2024 11:04:06 -0400 Subject: [PATCH 1/6] Update 09.Dict.md Fixed typos --- 09.Dict.md | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/09.Dict.md b/09.Dict.md index 84af37e..a33423e 100644 --- a/09.Dict.md +++ b/09.Dict.md @@ -32,6 +32,8 @@ my_dict = { # Option 2: Pass keyword parameters my_dict = dict(name='John', age=30, occupation='developer') + +print(my_dict) ``` #### Output @@ -97,7 +99,7 @@ John The `min()` and `max()` functions can be used with dictionaries to find the minimum or maximum key or value. -***Note***: By default, these functions operate on the dictionary keys, but you can specify to operate on the values by using the `key` parameter. +***Note***: By default, these functions operate on the dictionary keys, but you can specify to operate on the values by using the `values()` method. #### Example @@ -307,7 +309,7 @@ True ***NOTE***: Although `dict_a` and `dict_b` were defined in different orders, they are considered equal. -***NOTE***: Order does not matterm since Python 3.7, dictionaries maintain the insertion order of items. However, the order does not influence the outcome of equality comparisons. +***NOTE***: Order does not matter since Python 3.7, dictionaries maintain the insertion order of items. However, the order does not influence the outcome of equality comparisons. ### 4.2 Inequality (`!=`) @@ -348,6 +350,7 @@ family = { } print(family['john']['job']) +print(family.get('jane').get('age')) ``` #### Output @@ -385,6 +388,11 @@ This can be done using the `.setdefault()` method or checking for the existence #### Example ```python +family = { + 'john': {'age': 30, 'job': 'developer'}, + 'jane': {'age': 28, 'job': 'designer'} +} + # Adding a new key-value pair for John family['john']['hobby'] = 'painting' @@ -434,9 +442,17 @@ To remove items either from default or a nested dictionary, use the `del` statem #### Example ```python +family = { + 'john': {'age': 30, 'job': 'developer', 'hobby': 'painting'}, + 'jane': {'age': 28, 'job': 'designer'}, + 'alice': {'age': 24, 'job': 'engineer'} +} + # Deleting a key-value pair del family['john']['hobby'] +print(family) + # Removing an entire nested dictionary removed_person = family.pop('alice', None) print(f"Removed: {removed_person}") @@ -445,7 +461,7 @@ print(f"Removed: {removed_person}") #### Output ``` -{'john': {'age': 30, 'job': 'developer'}, 'jane': {'age': 28, 'job': 'designer'}} +{'john': {'age': 30, 'job': 'developer'}, 'jane': {'age': 28, 'job': 'designer'}, 'alice': {'age': 24, 'job': 'engineer'}} Removed: {'age': 28, 'job': 'designer'} ``` From 6c6d8c6bf4bdddcd7ba3dff06a56e299d7a7fc9a Mon Sep 17 00:00:00 2001 From: tteodorescu0 Date: Wed, 26 Jun 2024 12:20:01 -0400 Subject: [PATCH 2/6] Update 10.Functions.md Fixed typos --- 10.Functions.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/10.Functions.md b/10.Functions.md index ea426e5..676c906 100644 --- a/10.Functions.md +++ b/10.Functions.md @@ -71,7 +71,7 @@ Let's write the same code, but **with functions** this time. In Python functions are defined by `def` keyword _followed by the name_ of the function , then curly brackets `()` and semicolon `:`. -***NOTE***: Take a look at **_indentation_**, in case it's wrong the `Pyhton` interpreter will not be able to compile the +***NOTE***: Take a look at **_indentation_**, in case it's wrong the `Python` interpreter will not be able to compile the code. #### Example @@ -93,7 +93,7 @@ print_cake_recipe() #### Explanation -We created a function `print_cake_recipe()` and then called it 4 times, lets see what +We created a function `print_cake_recipe()` and then called it 4 times, let's see what happens when we run it. #### Output @@ -152,15 +152,15 @@ addition(1, 3) #### Explanation -Define function `addition` and in curly brackets we declared the parameters: `a` and `b`. +We defined function `addition` and inside parentheses we declared the parameters: `a` and `b`. -Then we called the function and passed arguments `1` and `3`, as `a` and `b` accordingly +Then we called the function and passed arguments `1` and `3`, as `a` and `b` accordingly. ### 2.2 Parameters vs Arguments As irrelevant as it might seem, there is a difference between these two key terms. The function ***parameters*** are the names listed in the function's definition and the function ***arguments*** are the real values passed to the function. -You just need to understand that once you pass value `11` to the parameter `a` into the function, it becomes and argument. +You just need to understand that once you pass value `11` to the parameter `a` into the function, it becomes an argument. ## 3. Positional vs Key Arguments @@ -218,7 +218,7 @@ Here, even though the order of arguments is ***different*** from the order of parameters in the function definition, Python knows which argument corresponds to which parameter, thanks to the keyword parameters. -Personally I prefer the following approach, following it, your codebase becomes much cleaner. +Personally I prefer the following (????) approach, following it, your codebase becomes much cleaner. ## 4. Scopes @@ -267,7 +267,7 @@ NameError: name 'summ' is not defined. #### Explanation In this case we declare variable `suma` and since we created it **inside** the function -it has **local** scope, therefore we wouldn't be able to call it from outside: +it has **local** scope, therefore we wouldn't be able to call it from outside. ### 4.2 Global scope @@ -434,7 +434,7 @@ Good morning, Bob! In the `greet` function above, `name` is a **mandatory** parameter, while `message` is **optional** with a *default value* of `"Hello"`. If no `message` is provided when the function is called, it uses the *default value*. -***Important***: You can only assign default values to parameters ***After*** you have declared your positional arguments, more on this in ***args/kwargs*** section +***Important***: You can only assign default values to parameters ***after*** you have declared your positional arguments, more on this in ***args/kwargs*** section ## 7. `Args` and `Kwargs` @@ -466,8 +466,8 @@ positional arguments into a tuple called `numbers`. ### 7.1.1 Unpacking parameters -As we learned previously in data types, you can use `*` to unpack the elements of an iterable, it is relevant as if you -will try to pass an iterable to a function without unpacking it, it will be treated as a whole object. +As we learned previously in data types, you can use `*` to unpack the elements of an iterable. Be aware that if you +pass an iterable to a function without unpacking it, you will pass the iterable as a whole unpacked object (rather than passing the individual elements in the iterable). ***NOTE***: Same applies for `**kwargs` @@ -772,7 +772,7 @@ x = 10 def print_number(): x = 5 - print("Inside function:", x) + print("Inside function:", x, end=", ") print_number() print("Outside function:", x) From 796d1180b46cef1e163881b18a3868f275afe1c5 Mon Sep 17 00:00:00 2001 From: tteodorescu0 Date: Wed, 26 Jun 2024 13:45:59 -0400 Subject: [PATCH 3/6] Update 11.Exceptions.md --- 11.Exceptions.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/11.Exceptions.md b/11.Exceptions.md index 4f513bb..2194104 100644 --- a/11.Exceptions.md +++ b/11.Exceptions.md @@ -17,11 +17,11 @@ Error handling is an important component of programming that provides opportunity for code to adequately respond to unexpected situations. In Python, errors are managed through the use of exceptions, which are special objects that represent error conditions. -When Python interpreter stumbles upon a situation, it cannot cope with, it raises an exception. If the exception isn't handled, the program will terminate abruptly, which can lead to a poor user experience or even loss of data. +When Python interpreter stumbles upon a situation it cannot cope with, it raises an exception. If the exception isn't handled, the program will terminate abruptly, which can lead to a poor user experience or even loss of data. ## 2 The `try` & `except` Block -In python, error handling is managed with the use of `try` and `except` keywords. +In Python, error handling is managed with the use of `try` and `except` keywords. ### 2.1 How do `try` and `except` work? @@ -163,7 +163,7 @@ In this example, the code inside the `try` block successfully completes without The `else` block is useful when you want to separate the code that might raise an exception from the code that should only be executed if no exceptions occur. This separation can improve the readability of your code and make it easier to understand the flow of execution. -Though, I must admit that the following approach is not really popular among Python society. Have no idea why, to be honest... +Though, I must admit that the following approach (??? huh what approach) is not really popular among Python society. Have no idea why, to be honest... ### 3.2 Note @@ -215,7 +215,7 @@ Where `ExceptionType` is the class of the exception you want to raise (e.g., `Va ### 5.3 Use Cases -1.**Input Validation**: If a function requires inputs to meet certain conditions, you can raise an exception if the provided inputs are invalid. +1. **Input Validation**: If a function requires inputs to meet certain conditions, you can raise an exception if the provided inputs are invalid. ```python def set_age(age): @@ -227,7 +227,7 @@ Where `ExceptionType` is the class of the exception you want to raise (e.g., `Va print(e) ``` -2.**Enforcing Constraints**: When certain states or conditions must not occur within a program, raising exceptions can enforce these constraints explicitly. +2. **Enforcing Constraints**: When certain states or conditions must not occur within a program, raising exceptions can enforce these constraints explicitly. ```python inventory = {'apple': 10, 'banana': 5} @@ -240,7 +240,7 @@ Where `ExceptionType` is the class of the exception you want to raise (e.g., `Va inventory[item] -= quantity ``` -3.**Signaling Unimplemented Features**: If a part of your code is not yet implemented, you can raise a `NotImplementedError` as a placeholder. +3. **Signaling Unimplemented Features**: If a part of your code is not yet implemented, you can raise a `NotImplementedError` as a placeholder. ```python def future_feature(): raise NotImplementedError("This feature is coming soon!") @@ -254,7 +254,7 @@ There are no limits for your imagination in terms of handling errors, again this ### 5.5 Best Practices -- **Be Specific**: Prefer raising and catching specific exceptions rather than the general `Exception` class. This makes error handling more predictable, robust and optimised. +- **Be Specific**: Prefer raising and catching specific exceptions rather than the general `Exception` class. This makes error handling more predictable, robust, and optimised. - **Provide Useful Messages**: When raising exceptions, include a clear, descriptive message to make it easier to understand the cause of the error. From 33f674704b3ebb22934e6fea0c93ec23aeecf444 Mon Sep 17 00:00:00 2001 From: tteodorescu0 Date: Wed, 26 Jun 2024 15:55:50 -0400 Subject: [PATCH 4/6] Update 12.Imports.md --- 12.Imports.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/12.Imports.md b/12.Imports.md index 033b743..2c54bb1 100644 --- a/12.Imports.md +++ b/12.Imports.md @@ -24,13 +24,13 @@ The module name is the same as the file name with the `.py` extension added at t ### 1.1 Why do we need modules? -Generally, if we were to write everything into one file, we wouldn't be able to maintain our application, making it hard for other developers to use. +Generally, if we were to write everything into one file, we wouldn't be able to maintain our application, making it hard for other developers to use it. Using modules helps us to do the following: -- **Organizing Code**: By dividing a program into modules you can separate parts and concerns making it easier to manage and understand the program. +- **Organizing Code**: By dividing a program into modules, you can separate parts and concerns making it easier to manage and understand the program. -- **Reusable Components**: Functions, classes and variables defined in a module can be easily reused across sections of a program or different programs. +- **Reusable Components**: Functions, classes, and variables defined in a module can be easily reused across sections of a program or in different programs. - **Managing Namespaces**: Modules help prevent conflicts between names by providing a separate namespace, for each module. @@ -43,6 +43,8 @@ In `Python`, a simple `.py` file can be considered and used as a module to store 2. **Add Code to the File**: Write the necessary functions, classes, and variables in the file. Here’s an example of what `mymodule.py` might look like: ```python +# mymodule.py + def say_hello(name): print(f"Hello, {name}!") @@ -185,7 +187,7 @@ Thanks to `as` you can use `time` from both `x` and `y` modules, without any con ## 4. `if __name__ == "__main__"` -When writing Python scripts, you'll often see a code block guarded by at the bottom: +When writing Python scripts, you'll often see a code block at the bottom guarded by: ``` if __name__ == "__main__" @@ -241,7 +243,7 @@ Instead of raw theory, let's take a look at the real application and try to come #### Example -Consider a package named `finance` designed to handle various financial calculations and data processing +Consider a package named `finance` designed to handle various financial calculations and data processing. ***Strucure*** @@ -262,7 +264,7 @@ finance/ # Specify the public API for convenience __all__ = ['calculator', 'taxes', 'investments'] -# You may also initialize some package-wide constants or setup code, though its not a common practice nowdays +# You may also initialize some package-wide constants or setup code, though it's not a common practice nowdays DEFAULT_TAX_BRACKET = '25%' ``` @@ -298,7 +300,7 @@ Sub-packages enable even more granular organization within a package, grouping t For instance, `finance/investments` is a sub-package grouping financial investment-related modules like `stocks.py` and `bonds.py`. -When the project becomes extremely big, think about how you could re-structure to make it more maintainable, reusable and readable. +When the project becomes extremely big, think about how you could re-structure to make it more maintainable, reusable, and readable. ### 5.3 Importing from Packages @@ -407,11 +409,11 @@ source venv/bin/activate pip install requests ``` -Let's create an application and split everything into diffrent modules as it was already discussed above. +Let's create an application and split everything into different modules as it was already discussed above. ### 7.2 Weather Fetcher App -**Objective:**: Develop an application to display real-time weather information based on user input. +**Objective:** Develop an application to display real-time weather information based on user input. ***NOTE***: The application will interact with the `OpenWeatherMap` `API` to obtain data for the specified city and present it to the user in a clear and concise format. From 5b3c6a47a9b09b2709744427896f64eddcd22153 Mon Sep 17 00:00:00 2001 From: tteodorescu0 Date: Wed, 26 Jun 2024 16:35:46 -0400 Subject: [PATCH 5/6] Update 13.Files.md --- 13.Files.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/13.Files.md b/13.Files.md index 3cd8a45..414d069 100644 --- a/13.Files.md +++ b/13.Files.md @@ -53,7 +53,7 @@ The available modes are: | ---- | --------------------------------------------------------------------------------------------------------------------------------- | | r | To read a file, open it. (default) | | w | To write, open a file. if the file doesn't already exist, creates a new one; otherwise, truncates the existing one. | -| a | Access a file without truncating it so that you can append data to the end of it. if the file does not already exist, creates it. | +| a | Access a file without truncating it so that you can append data to the end of it. If the file does not already exist, creates it. | | t | Switch to text mode. (default) | | x | For exclusive creation, open a file. The operation fails if the file already exists. | | b | In binary mode, open. | @@ -93,7 +93,7 @@ def display_menu(): print("3. Exit") ``` -In python there is method `readlines()`, it can be used to read contents of a file as well as `read`, but instead of returning one string, it returns a list of small ones(lines of text in the document). +In Python there is method `readlines()`, it can be used to read contents of a file as well as `read`, but instead of returning one string, it returns a list of small ones(lines of text in the document). #### Example @@ -161,7 +161,7 @@ line 3 ### 2.5 Renaming and Deleting a File -To rename a file in Python, since there is no built-in way to do that in python, we need 'os' library, particularly +To rename a file in Python, since there is no built-in way to do that in Python, we need 'os' library, particularly the `os.rename()` method. ```python @@ -286,7 +286,7 @@ Base/06.Lists.md --> This is a relative path The path to a file relative to the active working directory is known as a complete path. You may use the os module to obtain the current working directory. -If you clone this project, the it will be the following +If you clone this project, the full path could be the path in the following example. #### Example @@ -319,7 +319,7 @@ The syntax for using `with open` is as follows: ```python with open("file_name", "mode") as file: -# code to work with file goes here + # code to work with file goes here ``` When you use `with open`, `Python` automatically closes the file after the block of code included in the `with` statement completes running—even if an exception does. @@ -526,7 +526,7 @@ with open("file.yaml", "r") as file: ### Pickle -Pickle is a specificly designed for Python file type, which allows us to store or save Python objects in memory. It is particulary useful in machine learning as it allows to store and transfer heavy ai models in regular memory instead of operative. +Pickle is a specificly designed for Python file type, which allows us to store or save Python objects in memory. It is particulary useful in machine learning as it allows to store and transfer heavy AI models in regular memory instead of operative. #### Example @@ -632,4 +632,4 @@ D) `ValueError` - Only rename files (not directories). - Print the old and new names of the files as they are renamed. -For additional functionality and tasks, try to use new modules and libs from the previous lesson, be creative, as it's high time you start developing your own applications! \ No newline at end of file +For additional functionality and tasks, try to use new modules and libs from the previous lesson, be creative, as it's high time you start developing your own applications! From f522e6263fcb242bc3f47874a41406cb66f718da Mon Sep 17 00:00:00 2001 From: tteodorescu0 Date: Thu, 27 Jun 2024 15:38:53 -0400 Subject: [PATCH 6/6] Update 14.Functional-programming.md --- 14.Functional-programming.md | 44 +++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/14.Functional-programming.md b/14.Functional-programming.md index c307ac7..1f4025f 100644 --- a/14.Functional-programming.md +++ b/14.Functional-programming.md @@ -291,7 +291,7 @@ In Python, unlike in low level programming languages, such as `C` there are no p ### 3.1 Syntax -In order to create function's pointer all you have to do is assign your function to another variable without paranticies `()` at the end. You will store a reference (A.K.A pointer) inside this variable. +In order to create function's pointer all you have to do is assign your function to another variable without parentheses `()` at the end. You will store a reference (A.K.A pointer) inside this variable. #### Example @@ -342,7 +342,7 @@ func_handler = { def main(): num1 = int(input("1st number:")) num2 = int(input("2nd number:")) - choice = input("choose arithhmetical operation:") + choice = input("choose arithmetical operation:") print("output:", func_handler[choice](a=num1, b=num2)) main() @@ -354,11 +354,11 @@ main() ``` 1st number:4 2nd number:3 -choose arithhmetical operation:add +choose arithmetical operation:add output:7 1st number:4 2nd number:3 -choose arithhmetical operation:substract +choose arithmetical operation:substract output:1 ``` @@ -371,7 +371,7 @@ elif choice == "substract":     print(substract(num1, num2)) ``` -Of course, however it is much more convinient to use handlers in this case, because with many inputs your if statement would grow exponentially. And you'll end up having endless if statements. +Of course, however it is much more convenient to use handlers in this case, because with many inputs your `if` statement would grow exponentially. And you'll end up having endless `if` statements. Handlers is one of the most favourite patterns I have ever used. Think about where it can be applied within your applications. @@ -567,9 +567,28 @@ say_hello(name="Sasha") say_hello(name="Dima") ``` +#### Output + +``` +Hello, Sasha! +KeyError: 'Oops, you are not a superuser' +``` + Note, that you can decorate a function indirectly, not using `@` as a syntax sugar. ```python +def superuser(func): + allowed_users = ["Yehor", "Sasha"] + def wrapper(*args, **kwargs): + if kwargs["name"] not in allowed_users: + raise KeyError("Oops, you are not a superuser") + result = func(*args, **kwargs) + return result + return wrapper + +def say_hello(name, greeting="Hello"): + print(f"{greeting}, {name}!") + decorator = superuser(say_hello) decorator(name="Yehor", greeting="Morning") ``` @@ -577,8 +596,7 @@ decorator(name="Yehor", greeting="Morning") #### Output ``` -Hello, Sasha! -KeyError: 'Oops, you are not a superuser' +Morning, Yehor! ``` I LOVE DECORATORS! Hopefully you too now! @@ -605,7 +623,7 @@ print(l2(2, 3, 4)) # Output: 9 The simplicity of lambda functions is demonstrated here, showing how they directly return the result of a single expression. -Generally, lambdas ideal for encapsulating small bits of functionality that you do not need to reuse elsewhere. As well, the best usage will be passing them into `map()` or `filter()` functions. +Generally, lambdas are ideal for encapsulating small bits of functionality that you do not need to reuse elsewhere. As such, the best usage will be passing them into `map()` or `filter()` functions. #### Example @@ -630,7 +648,7 @@ Create --> Execute --> Say Goodbye! ### 7.2 Lambda vs Def -I am not a big fan of lambdas, though, should admit that I have nothing against them! I guess, the best in this situation would be refering to this table while making a decision what should your code do. +I am not a big fan of lambdas, though, I should admit that I have nothing against them! I guess, the best in this situation would be refering to this table while making a decision what should your code do. | Feature | `lambda` | `def` | |------------------------|--------------------------|-----------------------| @@ -775,11 +793,11 @@ You have to understand that such operations are extremely resource consuming and ## 11. Function Memoization -Memorization is a technique for storing the outcomes of earlier function calls to expedite subsequent computations. +Memoization is a technique for storing the outcomes of earlier function calls to expedite subsequent computations. Repeated function calls with the same inputs allow us to save the prior values rather than doing pointless calculations again. -Calculations are significantly accelerated as a consequence. One example of how you might want to implement momoization in your code is decorators. +Calculations are significantly accelerated as a consequence. One example of how you might want to implement memoization in your code is decorators. #### Example @@ -845,7 +863,7 @@ non memoized function took 0:00:00.000558 more time As you can see in the output above, there is a huge time difference between two times thanks to memoization. -***Note***: Do not get confused by the fact that we called same function twice - the first time we called the function its result hasn't been recorded yet, therefore it is the same as calling unmemoized function. +***Note***: Do not get confused by the fact that we called same function twice - the first time we called the function its result hasn't been recorded yet, therefore it is the same as calling unmemoized function. (??? This statement does not seem correct. Calling the memoized function for the first time is not the same as calling the unmemoized function. For example, the unmemoized function might time out and not return any value, while the memoized function will work correctly.) ## 12. Quiz @@ -867,7 +885,7 @@ D) A function that performs higher mathematical calculations. > What does the `map()` function do? A) Maps a function to a specific module. -B) Applies a given function to each item of an iterable and returns a list of results. +B) Applies a given function to each item of an iterable and returns an iterable of results. C) Creates a visual map of function calls. D) Translates a function from one programming language to another.