Skip to content

Commit 5f5373e

Browse files
committed
Study/practice updates: practiced over 600+ nuanced questions across three different Udemy mock-test courses for PCAP
1 parent 76fc7a0 commit 5f5373e

16 files changed

+1779
-337
lines changed

Diff for: Functions/Introspection/isinstance(object, type).py

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
isinstance(5, int) # True
1010
isinstance(5.0, float) # True
1111
isinstance("Hello", str) # True
12+
print(isinstance(5, (int,float) )) # True If a tuple is used, 'OR' is applied, not 'AND'.
1213

1314

1415
class myObj:

Diff for: Functions/definitions & documentation.py

-36
This file was deleted.

Diff for: Functions/definitions, documentation & rules.py

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
"""ASTERISK '*' USED ALONE"""
2+
3+
def func(a, *, b, c): # * specifies that all arguments following it must be provided as keyword arguments.
4+
pass
5+
6+
# Correct call
7+
func(1, b=2, c=3)
8+
9+
10+
11+
"""ASTERISK '*' BEFORE A PARAMATER """
12+
13+
def func(arg, *args): # Allows the function to accept any number of positional arguments (the first is still captured by 'arg').
14+
pass
15+
16+
# Correct call
17+
func(1, 2, 3, 4, 5) # Python transforms '*args' into a tuple for use within the function:
18+
19+
# Printed 'args':
20+
(2, 3, 4, 5)
21+
22+
# [EXTRA] Unpack on calling fun:
23+
tuple = 1, 2, 3, 4, 5
24+
func(1, *tuple) # Useful if you already have a tuple, otherwise printout would be: ((2, 3, 4, 5),)
25+
26+
27+
28+
"""DOUBLE ASTERISK '**' BEFORE A PARAMATER """
29+
30+
def example_function(**kwargs): # An arbitary number of arguments received by a '**' prefixed parameter are automatically packed into a dictionary.
31+
for key, value in kwargs.items():
32+
print(f"{key}: {value}")
33+
34+
example_function(arg1="Hello", arg2=42)
35+
36+
# This is often referred to as "keyword argument unpacking".
37+
38+
39+
40+
41+
42+
43+
44+
45+
46+
# F U N C T I O N R U L E S
47+
48+
49+
""" Functions Without Arguments
50+
(Function checks itself first, then checks the global scope.) """
51+
52+
53+
d = 'a'
54+
55+
def fun():
56+
d += 'b' # raises error: outside immutables are read-only
57+
print(d)
58+
59+
60+
fun()
61+
print(d)
62+
63+
64+
65+
66+
d = ['a', 'b']
67+
68+
def fun():
69+
d.insert(-1, 'c') # this works; outside mutables CAN be modified
70+
print(d)
71+
72+
73+
fun()
74+
print(d) # prints: ['a', 'c', 'b']
75+
76+
77+
78+
79+
80+
"""Functions With Arguments"""
81+
82+
83+
d = 'a'
84+
85+
def fun(d):
86+
d += 'b'
87+
print(d)
88+
89+
90+
fun(d)
91+
print(d) # prints:
92+
# ab
93+
# a
94+
95+
96+
97+
""" When a variable is passed in a function call, it's not just a new copy of the value or only the value itself being passed, but a
98+
reference to the original variable that is added to the function's local namespace.
99+
100+
Mutables:
101+
The original (outer) variable is modified.
102+
103+
Immutables:
104+
The original (outer) variable is COPIED for seperate local use within the function's local scope.
105+
"""
106+

Diff for: Functions/open().md

+29-4
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,39 @@ Read Mode (`r`): Opens the file for reading from the beginning. Raises errno.ENO
44

55
Write Mode (`w`): Opens and truncates the file to zero length or creates a new one, starting at the beginning.
66

7-
Append Mode (`a`): Opens the file for appending at the end or creates a new one, starting at the beginning.
7+
Append Mode (`a`): Opens the file for appending at the end or creates a new one.
88

9-
Exclusive Creation (`x`): Creates a new file for writing, raises errno.EEXIST if it exists.
9+
Exclusive Creation (`x`): Creates a new file FOR WRITING, raises errno.EEXIST if it exists.
1010

1111
Read and Write (`r+`): Opens the file for both reading and writing from the beginning. Raises errno.ENOENT if the file doesn't exist.
1212

1313
Write and Read (`w+`): Opens the file for both reading and writing, truncating or creating it as needed, starting at the beginning.
1414

15-
Append and Read (`a+`): Opens the file for both reading and appending at the end. Only 'reads' honour seek() changes, i.e., 'appends' only at the end.
15+
Append and Read (`a+`): Opens or creates the file for both reading and appending at the end. Writes always move the file position (back) to the end.
1616

17-
Crucial difference between w+ and r+, is with r+ the file must already exist.
17+
+
18+
beside write, '+'' means read;
19+
beside read, '+'' means write (aka update)
20+
21+
# Crucial difference between w+ and r+, is with r+ the file must already exist.
22+
23+
24+
25+
26+
APPEND & READ (`a+`)
27+
28+
# file.txt exists and was created using the next three lines:
29+
# f = open('file.txt', 'w+')
30+
# f.write('line 1\nline 2\nline 3\nline 4')
31+
# f.close()
32+
33+
f = open('file.txt', 'a+')
34+
f.seek(0)
35+
s1 = f.read() + ' ...first read' # reads succesfully
36+
f.write('new line') # ignores seek() and (successfully) appends the string at the end
37+
s2 = f.read() + ' ...second read' # nothing is read, because the 'a' mode "forced" write() to moved the head to the end before writing
38+
f.close()
39+
print(s1)
40+
print(s2)
41+
42+
# Always remember to re-position the head using seek() after a write operation in 'append & read' (a+) mode.

Diff for: Functions/os.functions.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from os import uname # <--- For Unix. For windows, use `from platform import uname`
1+
from os import uname # For windows, use `from platform import uname`
22

33
print(uname())
44

Diff for: Functions/sorted.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
sorted(iterable, /, *, key=None, reverse=False)
12
# sorted() function R E T U R N S a new sorted list. Is NOT a method of a class, so does NOT sort the list in-place.
23

34
# list.sort() D O E S N O T return anything. It DOES sort in-place.

Diff for: Misc/bitwise_operations.txt

+5-3
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ Returns 1 only if both bits are 1. Even n & 1, becomes 0;
77
Bitwise XOR (^)
88
Returns 1 if exactly one of the bits is 1, but not both. (Exclusive OR) Even n ^ 1, just add 1; Odd n ^ 1, minus 1. FLIPS LEAST SIGNIFICANT BIT!
99

10-
Bitwise NOT (~) NEGATES IT MINUS AN EXTRA 1!
10+
Bitwise NOT (~) NEGATE N's SIGN, THEN, N -1
1111
n = -n - 1 5 becomes -6
1212
-n = n - 1 -5 becomes 4
1313

14-
Bitwise n << 1 n = n * 2 A left shift (<<) by n bits is equivalent to multiplication by pow(2, n).
14+
BITWISE N << 1 BITWISE N << K
15+
-------------- --------------
16+
Bitwise n << 1 x = n * 2 A left shift (<<) by k bits is equivalent to: n * pow(2, k).
1517

16-
Bitwise n >> 1 n = n / 2 A right shift (>>) by n bits is equivalent to floor division by pow(2, n).
18+
Bitwise n >> 1 x = n // 2 A right shift (>>) by k bits is equivalent to: n // pow(2, k).
1719

1820

1921

Diff for: Misc/exceptions.txt

+42-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ NameError is raised when you try to access a local or global name (like a variab
77

88
A TypeError is raised for operations on mismatched data types where the operation doesn't make sense for the data type, (like adding TypeError BaseException ← Exception ← TypeError
99
a string to an integer) or when inheritance structures in classes lead to an unclear hierarchy, preventing a consistent method
10-
resolution order (MRO).
10+
resolution order (MRO). TypeErrors also arise if the number of arguments supplied doesn't match a function's parameter signature.
11+
12+
ModuleNotFoundError is raised if attempting to import a module that cannot be found. For example, because the sys.path list has ModuleNotFoundError BaseException ← Exception ← ImportError ← ModuleNotFoundError
13+
not been appended, or attempting to use the 'import' keyword on its own without 'from' to import something inside a module.
14+
1115

1216
A ValueError is when the data type is correct, but the content within that data type isn't formatted or isn't appropriate for the ValueError BaseException ← Exception ← ValueError
1317
operation being attempted. For example, with `i = int("Hello!")` the type is correct because int() can convert other data types
@@ -184,4 +188,40 @@ BaseException
184188
| +---ErrorDuringImport
185189
+---GeneratorExit
186190
+---SystemExit
187-
+---KeyboardInterrupt
191+
+---KeyboardInterrupt
192+
193+
194+
195+
196+
197+
198+
199+
200+
201+
EXCEPTION HANDLING DESIGN
202+
Broad to Specific Handling: Exception handling is structured from more general to more specific to allow a program to respond to errors at
203+
varying levels of granularity. A general handler (superclass) deals with a wide range of issues, while more specific handlers (subclasses)
204+
address particular problems. This hierarchical handling is intentional and practical, ensuring that errors do not go unaddressed while also
205+
allowing for specific responses when needed.
206+
207+
Type Matching Over Attribute Access: When an exception is raised, Python's error handling mechanism looks for a match based on the exception's
208+
type, not its attributes or methods. This is fundamentally different from how objects typically interact in OOP, where attributes and methods
209+
of an object (and by inheritance, of its subclasses) are crucial to how it behaves or is treated. In exception handling, the focus is on the
210+
type of error (i.e., its class) rather than on the properties or behaviors of the error object.
211+
212+
Designed for Error Propagation: Exceptions are designed to propagate up the call stack until they find a matching handler. This design ensures
213+
that errors are not silently ignored but are either handled explicitly or cause the program to terminate with an error message. The ability
214+
of a superclass to catch exceptions from its subclasses facilitates this by providing a "catch-all" mechanism for unhandled specific errors.
215+
216+
CONCEPTUAL SHIFT
217+
Operational, Not Structural: The operation of catching exceptions in a superclass doesn't rely on inheriting attributes or methods from
218+
subclasses (which, as you noted, is not how inheritance works). Instead, it's about structurally placing a safety net for any errors that fall
219+
within a broad category defined by the superclass. This mechanism is purpose-built for error handling and is structured to maximize code
220+
robustness and clarity.
221+
222+
Purposeful Design: This design choice is purposeful, reflecting the need for error handling mechanisms to be both comprehensive and manageable.
223+
By allowing superclasses to handle exceptions from their subclasses, Python's design ensures that developers have the flexibility to write
224+
error handlers that are as generic or as specific as needed without complicating the inheritance hierarchy.
225+
226+
In summary, while the mechanism of exception handling utilizes the class hierarchy in a way that mirrors inheritance, its logic and purpose are
227+
tailored specifically to the needs of error management, rather than reflecting the traditional OOP model of attribute and method inheritance.

Diff for: Misc/file.methods().md

+9-4
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ file.write(string) # Takes a string and appends it at the current file position.
88
file.writelines(lines, /) # Write a list of lines at the current file position. Newline separators ('\n') are not added.
99

1010
# READING (r, r+, w+, a+)
11-
file.read([size=- 1], /) # Reads entire file or number of characters/bytes from current position, returning empty string at EOF.
11+
file.read([size= -1], /) # Reads entire file or number of characters/bytes from current position, returning empty string at EOF.
1212

13-
file.readline([size=- 1], /) # Returns the next line from the file up to the newline character or size of byteas, whichever is first.
13+
file.readline([size = -1], /) # Returns the next line from the file up to the newline character or size of byteas, whichever is first.
1414
#If EOF, returns an empty string.
1515

16-
file.readlines(hint=- 1, /): # Returns the next list of lines from the file. If 'hint' bytes (approximate) are read, no further lines are read.
16+
file.readlines(hint = -1, /): # Returns the next list of lines from the file. If 'hint' bytes (approximate) are read, no further lines are read.
1717
# An empty list is returned if EOF.
1818

1919

@@ -26,7 +26,12 @@ file.write(bytearray): # Writes the contents of 'bytearray' to the current file
2626
file.read([size]): # Reads the entire file or up to 'number' bytes if specified. Returns a bytes object.
2727

2828
file.readinto(bytearray): # Reads bytes from the file into 'bytearray'. Returns the number of bytes read.
29-
# Example: bytearray_variable = bytearray(100); file.readinto(bytearray_variable)
29+
30+
31+
# Example:
32+
bytearray_variable = bytearray(100)
33+
file.readinto(bytearray_variable)
34+
3035

3136
"""REMEMBER: Use file.close() or a 'with' statement for automatic closing and saving.
3237

Diff for: Misc/keywords.py

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import keyword
2+
print(keyword.kwlist)

Diff for: Misc/string_.methods().py

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# type: ignore # pylint: disable=all
22
""" STRING METHODS """
3+
# NOTE: ALL string methods return something.
34

45
str.capitalize() # Return a copy of the string with ONLY its first character capitalised and THE REST LOWERCASED.
56
str.title() # makes the first letter in each word upper-case.
@@ -9,6 +10,7 @@
910

1011
str.center(width[, fillchar]) # centers the string inside the field of a known length;
1112

13+
# NOTE: String Methods with Slices: 'start' can be used without 'end' but 'end' cannot be used without 'start'.
1214
str.count(sub[, start[, end]]) # counts the occurrences of a given character;
1315
str.find(sub[, start[, end]]) # finds a substring returning its index, or -1 on failure; (start inclusive, end exclusive); string.find('text', start, end)
1416
str.rfind(sub[, start[, end]]) # Return the HIGHEST INDEX where the START of the substring is found (from left to right). Returns -1 if failed; (start inclusive, end exclusive);

Diff for: Python Essentials 2 - Intermediate/Module 3/exceptions.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ def print_args(args):
1313
print(e, e.__str__(), e.args) # Printing 'e' implicitly is the same as invoking e.__str__() explicitly. And 'args' is just an instance property (a tuple) storing the arguments passed to the exception object's constructor.
1414
print_args(e.args)
1515

16+
print(e) # <<< ERROR: This last line will raise a NameError because as 'e' is a LOCAL variable (alias) that refers to an instance of the exception class; it only has local variable scope inside the 'except' block it was created.
1617

1718

1819

20+
# e.__dict__ likely won't show the exception instance's variables such as e.args and e.errno because some exceptions are implemented in C at a deeper level, storing these attributes in C structures rather than the Python object's __dict__.
21+
1922

2023
# When creating user defined exceptions, they must be new subclasses derived from predefined ones. Either closely related, or not. For a structure not closely related to Python's existing tree, we can choose a top base, like BaseException or Exception.
2124

@@ -181,4 +184,7 @@ def update_company_sales(company, sales):
181184
Exception's constructor. Since we are overriding the built-in Exception class's constructor with our own class's constructor and 'args' tuple, we
182185
are still able to access an e.args tuple. If our custom __init__ method on lines 2/3 were remeoved and replaced only with 'pass', this would have no
183186
affect on the program because CustomError would start inheriting the built-in Exception class's constructor.
184-
"""
187+
"""
188+
189+
190+
# exception instance alias variables (such as 'e.args' or 'e.errno') are local variables that are only accessible within their except block.

Diff for: Python Standard Library/sys/argv.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# TERMINAL/COMMAND PROMPT ARGUMENTS (i.e., flags)
2+
3+
print('hello')
4+
5+
import sys
6+
print(sys.argv)
7+
8+
"""
9+
SCRIPT
10+
Running as a script only outputs a single element list containing this file's path.
11+
12+
COMMAND LINE
13+
Output when this file is run from a terminal, i.e., `python3 argv.py hi hello test` is:
14+
['argv.py', 'hi', 'hello', 'test']
15+
"""

0 commit comments

Comments
 (0)