diff --git a/Day 2 Homework - Karen.md b/Day 2 Homework - Karen.md new file mode 100644 index 0000000..ee50637 --- /dev/null +++ b/Day 2 Homework - Karen.md @@ -0,0 +1,182 @@ +**1. Annotate the following python expressions with the specific types of each literal, as well as the overall return value:** + + ``` + i = 3 # the literal "3" and the overall return "i" are both integer as `int` + f = 3.0 # the literal "3.0" and the overal return "f" are both floating-point literal of type `float` + c = 3+3i # the literal "3" is an integer as `int` while the literal "3i" is a complex literal with 0 as the real part and the 3i as the imaginary part; the overal return c is a complex number of type `complex` + b = b'abcdefg' # the literal "b'abcdefg'" and the overall return "b" are both bytes literal of type `bytes` + s = 'abcdefg' # the literal "'abcdegf'" and the overall return "s" are both string literal of type `str` + s = "abcdefg" # the literal ""abcdegf"" and the overall return "s" are both string literal of type `str` + ``` +❓ I have a question for the function 'c' as it gives a syntax error when I enter it in Python saying invalid decimal literal, so how can we enter such kind of complex number of type `complex` in python? + +**2. For each of the types string, bytestring, integer, floating point, and imaginary literals, construct a 5x5 table showing what happens when the character "0" or number 0 is compared to each other type.** + +```ruby +# Define literals +str_literal = "12345" +bytes_literal = b"12345" +int_literal = 12345 +float_literal = 123.45 +imag_literal = 123+45j + +# Define comparison function +def compare(literal): + # Create table header + print(f"\nComparison table for {type(literal).__name__} literals:\n") + print(f"{'':10} {'0':^5} {literal[0]:^5} {literal[1]:^5} {literal[2]:^5} {literal[3]:^5} {literal[4]:^5}") + + # Compare each element in the literal to 0 + for i, elem in enumerate(literal): + is_equal = "==" if elem == 0 else "!=" + print(f"{elem:<10} {is_equal:^5} {0:^5} {is_equal:^5} {i:^5} {is_equal:^5} {i+1:^5} {is_equal:^5} {i+2:^5} {is_equal:^5} {i+3:^5} {is_equal:^5} {i+4:^5}") + +# Call comparison function for each type of literal +compare(str_literal) +compare(bytes_literal) +compare(int_literal) +compare(float_literal) +compare(imag_literal) + +Comparison table for str literals: + + 0 1 2 3 4 +1 != == != != != +2 != != == != != +3 != != != == != +4 != != != != == +5 != != != != != + +Comparison table for bytes literals: + + 0 1 2 3 4 +49 != == != != != +50 != != == != != +51 != != != == != +52 != != != != == +53 != != != != != + +Comparison table for int literals: + + 0 1 2 3 4 +12345 != != != != != + +Comparison table for float literals: + + 0 1 2 3 4 +123.45 != != != != != + +Comparison table for complex literals: + + 0 1 2 3 4 +(123+45j) != != != != != +``` + + + +**3. Now do the same thing for the + and == operators for each pair of types in two other 5x5 tables.** + + + +**4. Write a small program that uses the AST module to open the lexer/parser example, and dumps the resulting AST. See if there are any arguments to the parse method which make the output easier to read.** +Maybe we can first write a simple lexer sample, and then import `astor` module to output the AST in a more human-readable format. + +``` +import ply.lex as lex + +# Define the list of token names +tokens = ( + 'NUMBER', + 'PLUS', + 'MINUS' +) + +# Define the regular expressions for each token +t_PLUS = r'\+' +t_MINUS = r'-' +t_NUMBER = r'\d+' + +# Define a rule to handle whitespace +def t_whitespace(t): + r'\s+' + pass + +# Define a rule to handle errors +def t_error(t): + print("Invalid character '%s'" % t.value[0]) + t.lexer.skip(1) + +# Create the lexer +lexer = lex.lex() + +# Test the lexer on a sample input +input_str = "3 + 4 * (2 - 1)" +lexer.input(input_str) +for token in lexer: + print(token.type, token.value) + +import ast +import astor + +tree = ast.parse(input_str) +print(astor.to_source(tree)) +``` + + +**5. What does this do? `print("\007")` Can you figure out why?** +It prints an ASCII bell character to the console, and it is used to produce an audible signal. The character is interpreted by the computer's terminal or console to produce a beep or flashing effect, typically used to alert something. + + +**6. What does this do? `print("abcdefg\rhijklmnop")` Can you figure out why?** +The `\r` character in the string is used to instructs the console to return the cursor to the beginning of the current line without advancing to the next line, so in this case, it will prints the string "hijklmnop" over the string "abcdefg" in the console, replacing the first seven characters of the first string with the second string. +``` +>>> print("abcdefg\rhijklmnop") +hijklmnop + +``` + + +**7. This is an HTTP server. Run it and connect to http://localhost:8000 . Why doesn't this do the same thing as what you see above? (don't forget to shut down the HTTP server afterward.)** + + ``` + import http.server + import socketserver + from urllib.parse import urlparse, parse_qs + + class MyRequestHandler(http.server.SimpleHTTPRequestHandler): + def do_GET(self): + self.send_response(200) + self.send_header('Content-type', 'text/plain') + self.end_headers() + output_string = "abcdefg\rhijklmnop" + self.wfile.write(output_string.encode()) + + PORT = 8000 + Handler = MyRequestHandler + httpd = socketserver.TCPServer(("", PORT), Handler) + print(f"Serving on port {PORT}") + + httpd.serve_forever() + ``` + +**8. Think of a way someone might try to commit a crime or hide an embezzlement scheme using the answers to the above two questions. Hint: applications usually output on web pages, but developers and system administrators usually troubleshoot in the console.** +**9. Think of how you would do input validation to prevent such a crime. Replace the code REPLACE ME here so the tests pass:** + +``` +def validate(str): + for char in str: + if REPLACE ME: + raise ValueError("Crime detected!") + +try: + validate("abcdefg") + print("✅ test1 pass!") +except: + print("❌ test1 pass!") + +try: + validate("abcdefg\rhijklmnop") + print("❌ test2 fail!") +except ValueError as err: + print("✅ test2 pass!") +``` \ No newline at end of file