From 0f133528b3c34b795c5c00605875c66ae2b818b8 Mon Sep 17 00:00:00 2001 From: "scott.liu" Date: Wed, 14 Jun 2023 15:50:08 -0700 Subject: [PATCH] 3.3 notes, 3.2 questions, and test file --- .../10_Questions_about_Section3.2.rtf | 141 ++++++++++++++++++ Scott_Submissions/3.3_Reading_Note.rtf | 68 +++++++++ Scott_Submissions/Test_613.py | 89 +++++++++++ 3 files changed, 298 insertions(+) create mode 100644 Scott_Submissions/10_Questions_about_Section3.2.rtf create mode 100644 Scott_Submissions/3.3_Reading_Note.rtf create mode 100644 Scott_Submissions/Test_613.py diff --git a/Scott_Submissions/10_Questions_about_Section3.2.rtf b/Scott_Submissions/10_Questions_about_Section3.2.rtf new file mode 100644 index 0000000..0ba437d --- /dev/null +++ b/Scott_Submissions/10_Questions_about_Section3.2.rtf @@ -0,0 +1,141 @@ +{\rtf1\ansi\ansicpg1252\cocoartf2580 +\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red26\green26\blue26;\red255\green255\blue255;} +{\*\expandedcolortbl;;\cssrgb\c13333\c13333\c13333;\cssrgb\c100000\c100000\c100000;} +\margl1440\margr1440\vieww11520\viewh8400\viewkind0 +\deftab720 +\pard\pardeftab720\parhyphenfactor20\partightenfactor0 + +\f0\fs32 \cf2 \cb3 \expnd0\expndtw0\kerning0 +1. What is a type hierarchy?\ + The type hierarchy in Python refers to the organization and relationships among different types or classes in the Python programming language. \ + It defines how types are related to each other and how they inherit attributes and behaviors from their parent types.\ + the type hierarchy in Python provides a structured organization of types, allowing for code reuse, inheritance, and polymorphism, which are fundamental principles of object-oriented programming.\ +\ +\ +\ +2. What is the difference between __repr__() and __str__()?\ + The __repr__() method is intended to provide a detailed and unambiguous representation of the object. It is primarily used for debugging and development purposes.\ + the __str__() method is used to provide a more user-friendly and readable representation of the object. It is intended for displaying the object to end-users.\ +\ +\ +\ +3. What is the range of an integer?\ + In Python 2, the int type is a fixed-size integer, typically represented using 32 bits or 64 bits depending on the platform. The maximum value for an int in Python 2 is sys.maxint, which is usually 2^31 - 1 or 2^63 - 1. Or you need to use \'91Long\'92 instead.\ + In Python 3, there is only one integer type, int, which behaves like the long type in Python 2. The int type in Python 3 can represent integers of arbitrary size limited only by the available memory.\ +\ + Ex:\ + import sys\ +\ + # Python 2\ + print(sys.maxint) # Output: 2147483647 (on most platforms)\ +\ + # Python 3\ + print(sys.maxsize) # Output: 9223372036854775807 (on most platforms)\ +\ +\ +\ +4. Why string is a immutable sequence but you can still assign or change the index from a string?\ + Strings are immutable sequences, which means that once a string is created, its elements cannot be modified. But you can still create new strings by using concatenation or string manipulation methods to achieve the desired modifications.\ +\ +\ +\ +5. Describe the __closure__ attribute.\ + The __closure__ attribute returns a tuple of cell objects, where each cell object represents a captured variable. \ + A cell object holds a reference to the variable's value, allowing the function to access and use the value even after the original scope has finished executing.\ + The cell objects stored in the __closure__ attribute have the cell_contents attribute, which provides direct access to the value of the captured variable.\ +\ +\ +\ +6. What is a code object and a function object? Any difference between them?\ + Code object:\ + A code object represents byte-compiled executable Python code, or bytecode. \ + It contains the instructions that make up the logic of a function, method, module, or other executable code. \ + The code object includes information such as the bytecode instructions, the constants used by the bytecode, the names used by the bytecode, the filename from which the code was compiled, and more. \ + Code objects are immutable and do not contain any references to mutable objects.\ + Function object:\ + A function object, on the other hand, is a callable object that represents a Python function. \ + It contains a reference to a code object, which defines the implementation of the function. \ + In addition to the code object, a function object also includes references to the function's globals (the module in which it was defined), the default argument values, and other attributes such as the function name, qualified function name, and more. \ + Function objects are mutable and can have additional attributes assigned to them.\ + \ + In summary, a code object represents the bytecode and metadata of Python code, while a function object is a callable object that encapsulates a code object and provides additional functionality, such as the ability to be called and have attributes assigned to it. A function object is essentially a runtime representation of a function defined in Python code, with the code object containing the actual implementation details.\ +\ +\ +\ +7. What is a traceback object and how we use it?\ + Traceback objects represent a stack trace of an exception. \ + They are created when an exception occurs and provide information about the sequence of function calls leading up to the exception.\ +\ + One way to use it we can figure it out by using \'91try\'85 except\'85\'92 function:\ +\ + try:\ + # Some code that may raise an exception\ + except Exception as e:\ + # Handle the exception\ + print("An exception occurred:", type(e).__name__)\ + print("Error message:", str(e))\ +\ + Exception is the base class for all built-in exceptions in Python. \ + It is a superclass that encompasses a wide range of exceptions, such as TypeError, ValueError, NameError, and many others. \ + By using Exception in the except statement, you catch any exception that is raised during the execution of the try block.\ +\ +\ +\ +8. What is the \'91auditing event\'92 meaning?\ + It refers to a mechanism in Python that allows custom auditing or monitoring of attribute access on objects. When accessing the tb_frame attribute of a traceback object, an auditing event of type __getattr__ is raised. This event provides an opportunity to intercept and customize the attribute access behavior, if desired.\ +\ + In simple terms, an auditing event is a way to track or log attribute access on objects for monitoring or auditing purposes. It allows you to observe and potentially modify the behavior when accessing specific attributes.\ +\ + The auditing events are specific to the implementation of Python and are typically used in specialized scenarios where attribute access needs to be monitored or customized.\ +\ +\ +\ +9. How to find the common values and different values from two lists?\ + list1 = [1, 2, 3, 4, 6]\ + list2 = [2, 4, 6, 7, 8]\ +\ + # Find common values\ + common_values = []\ + for item in list1:\ + if item in list2:\ + common_values.append(item)\ +\ + # Find different values\ + different_values = []\ + for item in list1:\ + if item not in list2:\ + different_values.append(item)\ + for item in list2:\ + if item not in list1:\ + different_values.append(item)\ +\ + print("Common values:", common_values) # Common values: [2, 4, 6]\ + print("Different values:", different_values) # Different values: [1, 3, 7, 8]\ +\ +\ + \ + # Or there is another way to do this by using set() method\ + # Find common values\ + common_values = set(list1) & set(list2) # The '&' operator performs an intersection\ +\ + # Find different values\ + different_values = set(list1) ^ set(list2) # The '^' operator performs a symmetric difference\ +\ + print("Common values:", common_values) # Common values: \{2, 4, 6\}\ + print("Different values:", different_values) # Different values: \{1, 3, 7, 8\}\ +\ +\ +\ +10. The difference between list and set?\ + In summary, lists are ordered, allow duplicate elements, and are mutable. \ + Sets are unordered, do not allow duplicates, and are also mutable. \ +\ + The following detailed explanations are provided by AI:\ + 1. Order: Lists are ordered collections, meaning they preserve the order of elements. Each element in a list has an index associated with it. Sets, on the other hand, are unordered collections. They do not preserve the original order of elements and do not have indices.\ + 2. Duplicate elements: Lists allow duplicate elements, which means you can have multiple occurrences of the same value in a list. Sets, on the other hand, do not allow duplicate elements. Each element in a set is unique.\ + 3. Mutable vs. Immutable: Lists are mutable, which means you can modify individual elements, add new elements, or remove elements from a list. Sets are also mutable, allowing the addition and removal of elements. However, you cannot modify individual elements in a set since they are unordered.\ + 4. Membership testing: Checking for membership (whether an element exists in a collection) is faster in sets compared to lists. Sets use a hashing mechanism that provides efficient membership testing, while lists require iterating over the elements to check for membership.\ + 5. Mathematical set operations: Sets support various set operations like union, intersection, difference, and symmetric difference. These operations can be performed using operators (|, &, -, ^) or methods. Lists do not provide built-in operations for set operations.\ + 6. Data uniqueness: Sets are often used to ensure the uniqueness of elements in a collection. You can easily eliminate duplicates from a list by converting it to a set and then back to a list if the order of elements is not important.\ + } \ No newline at end of file diff --git a/Scott_Submissions/3.3_Reading_Note.rtf b/Scott_Submissions/3.3_Reading_Note.rtf new file mode 100644 index 0000000..faa1cdb --- /dev/null +++ b/Scott_Submissions/3.3_Reading_Note.rtf @@ -0,0 +1,68 @@ +{\rtf1\ansi\ansicpg1252\cocoartf2580 +\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;} +{\*\expandedcolortbl;;} +\margl1440\margr1440\vieww28300\viewh17700\viewkind0 +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 + +\f0\fs24 \cf0 1. They have same output:\ + class MyClass:\ + def __getitem__(self, index):\ + return f"Item at index \{index\}"\ +\ + x = MyClass()\ + item = x[3]\ + print(item) # Output: Item at index 3\ +\ + # Equivalent to type(x).__getitem__(x, 3)\ + item = type(x).__getitem__(x, 3)\ + print(item) # Output: Item at index 3\ +\ +2. The object.__new__() method is a special method in Python that is called to create a new instance of a class. It is responsible for the low-level creation of an object before its initialization. \ +\ +3. The object.__init__() method is a special method in Python that is called after an instance of a class has been created by the __new__() method. It is responsible for initializing the object's attributes and performing any necessary setup.\ +\ +4. The object.__del__() method is a special method in Python that is called when an instance of a class is about to be destroyed or garbage-collected.\ +\ +5. The cyclic garbage collector in CPython is responsible for detecting and breaking reference cycles, ensuring that memory is properly deallocated even in the presence of reference cycles.\ +\ +6. the __format__() method allows objects to define their own customized string representations when used with format-related operations.\ +\ +7. x < y calls x.__lt__(y)\ +x <= y calls x.__le__(y)\ +x == y calls x.__eq__(y)\ +x != y calls x.__ne__(y)\ +x > y calls x.__gt__(y)\ +x >= y calls x.__ge__(y)\ +\ +8. The methods __get__, __set__, and __delete__ are used to implement descriptors in Python. Descriptors are a way to customize attribute access in classes. These methods are defined in a descriptor class, and when an instance of the descriptor class is present in an owner class, they are invoked to control attribute access.\ +\ +9. In Python, a descriptor is an object attribute that has "binding behavior" due to the overriding of attribute access through methods in the descriptor protocol: __get__(), __set__(), and __delete__(). If an object defines any of these methods, it is considered a descriptor.\ +\ +10. Using __slots__ can save significant memory compared to using __dict__, and it can also improve attribute lookup speed.\ +\ +11. class Philosopher:\ + def __init_subclass__(cls, /, default_name, **kwargs):\ + super().__init_subclass__(**kwargs)\ + cls.default_name = default_name\ +\ + class AustralianPhilosopher(Philosopher, default_name="Bruce"):\ + pass\ +\ + \ + This code sets up a base class called Philosopher that defines a custom behavior for its subclasses when they are created. \ + The default_name parameter allows each subclass to have a default name attribute, and the AustralianPhilosopher subclass demonstrates the usage by setting its default_name to "Bruce".\ +\ +12. The purpose of __set_name__() is to provide a hook for objects to perform any necessary initialization or setup when they are assigned to a class attribute. It allows the objects to be aware of their assigned name within the class they belong to, which can be useful for various purposes such as introspection or customization.\ +\ +13. The C3 linearization algorithm is a method used to determine the order in which base classes are searched for a particular attribute or method during multiple inheritance in Python. It ensures that the resolution order respects the consistency and priority of the inheritance hierarchy.\ +\ +14. MRO (Method Resolution Order) entries are resolved: This refers to the determination of the order in which base classes are searched for a particular attribute or method. The MRO defines the inheritance hierarchy and is calculated using the C3 linearization algorithm.\ +\ +15. Type annotations in Python refer to the practice of adding hints or metadata about the types of variables, function parameters, and return values in code. They are used to provide static type checking and improve code clarity, maintainability, and tooling support. They are optional and do not affect the runtime behavior of the code. Python remains a dynamically typed language, but type annotations allow developers to specify the expected types and enable type checking tools to catch potential errors.\ +\ + x: int = 5\ + def add(a: int, b: int) -> int:\ + return a + b\ +\ +16. The purpose of __class_getitem__() is to allow runtime parameterization of standard-library generic classes in order to more easily apply type hints to these classes.} \ No newline at end of file diff --git a/Scott_Submissions/Test_613.py b/Scott_Submissions/Test_613.py new file mode 100644 index 0000000..8419876 --- /dev/null +++ b/Scott_Submissions/Test_613.py @@ -0,0 +1,89 @@ +# import sys +# # Python 3 +# print(sys.maxsize) # Output: 9223372036854775807 (on most platforms) + + + + +# list1 = [1, 2, 3, 4, 6] +# list2 = [2, 4, 6, 7, 8] +# # Find common values +# common_values = [] +# for item in list1: +# if item in list2: +# common_values.append(item) + +# # Find different values +# different_values = [] +# for item in list1: +# if item not in list2: +# different_values.append(item) +# for item in list2: +# if item not in list1: +# different_values.append(item) + +# print("Common values:", common_values) # Common values: [2, 4, 6] +# print("Different values:", different_values) # Different values: [1, 3, 7, 8] + + +# # Find common values +# common_values = set(list1) & set(list2) + +# # Find different values +# different_values = set(list1) ^ set(list2) + +# print("Common values:", common_values) +# print("Different values:", different_values) + + + + +# def outer_function(): +# outer_variable = 10 + +# def inner_function(): +# inner_variable = 20 +# print("Inner function: ", inner_variable) +# print("Outer function (captured variable): ", outer_variable) + +# return inner_function + +# # Create a closure by calling the outer function +# closure = outer_function() + +# # Access the cell object from the closure +# cell_object = closure.__closure__[0] + +# # Access and print the value stored in the cell +# print("Cell contents: ", cell_object.cell_contents) + +# # Set a new value to the cell +# cell_object.cell_contents = 30 + +# # Access and print the updated value from the closure +# print("Updated cell contents: ", closure.__closure__[0].cell_contents) + + + +def greet(name): + message = f"Hello, {name}!" + print(message) + +# Accessing code object +code_obj = greet.__code__ +print(code_obj.co_name) # Output: greet +print(code_obj.co_argcount) # Output: 1 (number of arguments) +print(code_obj.co_varnames) # Output: ('name', 'message') + +# Accessing function object +print(greet.__name__) # Output: greet +print(greet.__defaults__) # Output: None (no default arguments) +print(greet.__globals__) # Output: {'__name__': '__main__', ...} (global namespace) + +# Modifying function object attributes +greet.__name__ = 'say_hello' +greet.__defaults__ = ('John',) +greet.__globals__['message'] = 'Welcome!' + +# Call the modified function +greet() # Output: Hello, John! \ No newline at end of file