Python
What happens in the background when you run for _ in mySet:
iterators and generators
What is lazy evaluation?
Who created Python, and when and why?
What is exit()
What is the <module>
What are two ways to execute Python code from the terminal?
python -c "<code>"
python my_script.py
What is a int64 and a float64 datatype in Python?
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 fixed acidity 1599 non-null float64Used to represent real numbers (numbers with whole and decimal parts), using 64 bits.
`int64
- A data type representing an integer (a whole number without a fraction) with 64 bits of memory, allowing for a large range of integer values.
- to .
Success
float64
- A data type representing a floating-point number (a number with a decimal point) with double precision, using 64 bits of memory.
- to
What I mean is that for the float64 data type, the range from approximately -1.7976931348623157e+308 to 1.7976931348623157e+308 indicates the limits of what can be accurately represented as a floating-point number using 64 bits. Beyond these limits, two types of numerical issues can occur:
-
Overflow: This happens when a number is too large to be represented in the given range. In the case of
float64, if a number is larger than approximately 1.7976931348623157e+308, it might be represented as “infinity” or cause errors. -
Underflow: This occurs when a number is too small (close to zero) to be represented in the given range. For
float64, extremely small numbers might be rounded down to zero or lose precision.
In summary, the specified range for float64 is the range within which numbers can be represented accurately and without these numerical issues.
No, that’s not correct. The range of a float64 (approximately -1.7976931348623157e+308 to 1.7976931348623157e+308) refers to the magnitude of the numbers it can represent, not the precision in terms of decimal places. The ‘e+308’ notation indicates the number is in scientific notation, meaning that float64 can handle numbers as large as approximately ( 1.797 \times 10^{308} ) and as small as approximately ( -1.797 \times 10^{308} ).
However, the precision of a float64 is not 308 decimal places. In reality, float64 has a precision of about 15-17 significant decimal digits, regardless of the magnitude of the number. This means that for very large or very small numbers, it can accurately represent only the first 15-17 digits, and the rest could be subject to rounding errors. The precision is more about how accurately the number is represented rather than the size of the number itself.
Certainly! Here are three interview questions about overflow and underflow in the context of machine learning, along with their answers:
Question 1:
Q: Can you explain what numerical overflow and underflow are and how they can affect a machine learning model?
A:
- Numerical Overflow: This occurs when a value exceeds the maximum limit that can be represented in a given data type. For example, in a
float64data type, values above approximately 1.797e+308 may cause overflow. In machine learning, this can happen during computations involving very large numbers, leading to results represented as infinity or causing errors. - Numerical Underflow: Underflow happens when a value is too small to be represented and is approximated as zero. In a
float64data type, values closer to zero than approximately 2.225e-308 might underflow. In machine learning, this is often seen in probabilities or likelihood calculations, where very small values become zero, leading to loss of precision or incorrect results.
Both overflow and underflow can lead to inaccuracies in machine learning models and should be handled, for instance, by normalizing data, using log-transformations, or choosing appropriate data types.
Question 2:
Q: In the context of gradient descent in machine learning, how can underflow and overflow become a problem, and what are common strategies to mitigate these issues?
A:
- Problem: In gradient descent, overflow can occur if the calculated gradients are excessively large, potentially causing the model to diverge. Underflow might happen with very small gradients, leading to stagnation or very slow convergence.
- Mitigation Strategies: To prevent these issues, normalization of input data is crucial to keep values within a manageable range. Using adaptive learning rates, like those in Adam or RMSProp optimizers, helps manage the scale of updates. Also, implementing gradient clipping can prevent gradients from becoming too large.
Question 3:
Q: Describe a scenario in a machine learning application where underflow is particularly problematic and suggest a solution.
A:
- Scenario: Underflow is particularly problematic in calculations involving probabilities, as in the case of Naive Bayes classifiers or in the softmax function in neural networks. When multiplying many small probabilities, the result might underflow to zero, leading to incorrect probability estimates or classifications.
- Solution: A common solution is to use logarithms. By converting multiplication of probabilities into sum of logs, we can avoid underflow. For instance, instead of directly multiplying probabilities, we sum their logarithms and exponentiate the result if necessary. This approach maintains numerical stability while preserving the relative magnitudes of the probabilities.
These questions and answers provide a concise overview of how numerical overflow and underflow issues can impact machine learning models and some strategies to mitigate these problems.
Asynchronous Programming
- Await
- Async
- Coroutine
How can you keep track of a variable across recursive function calls
Using a list (index = [1]) to keep track of the count is a clever way to handle the mutable state across recursive calls. However, it’s not immediately obvious why a list is being used here instead of a simple integer. This could confuse someone not familiar with Python’s handling of mutable default arguments.
When should you use recursive vs. iterative algorithms?
venv: why, how. Alternatives: conda
https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/
The collections library
↳ Scenario: Imagine you are working on a natural language processing project where you need to count the frequency of words in a large corpus of text. The words are tokenized and provided as a list of strings. How would you implement a solution for counting the frequency of each word efficiently? Specifically, explain which Python dictionary structure you would choose and why.
The candidate should mention using the collections.Counter class, explaining its efficiency in counting hashable objects and how it simplifies tasks involving counting occurrences, which is common in text processing and feature engineering in machine learning.
↳ Scenario: Consider a machine learning model training process where you need to cache large amounts of intermediate data (like partial results or feature sets) for quick access. However, this data should not prevent the objects from being garbage-collected when they are no longer in use elsewhere to avoid memory leaks. Which Python dictionary type would you use to implement this caching mechanism and why?
The ideal answer would be either weakref.WeakValueDictionary or weakref.WeakKeyDictionary. The candidate should explain how these dictionaries store weak references to their items, allowing the garbage collector to remove items if there are no strong references to them elsewhere, thus efficiently managing memory during intensive computation tasks like model training.
↳ Scenario: Imagine you have a collection of documents (like articles, web pages, or papers) and you want to quickly find all documents that contain a particular word. To do this efficiently, you can build an inverted index that maps each word to a list of document IDs where that word appears. Use defaultdict
What type of object does dict.values() return?
While dict.values() is able to show you all of the values in a dictionairy, the object itself is not a list object but rather a view object.
Success
view
- In Python, a view object is a special kind of object returned by certain methods of dictionary-like types (
dict,defaultdict, etc.). These objects provide a dynamic view on the dictionary’s entries- By dynamic this means that if you modify the dictionary after creating a view, the changes will be visible in the view. For instance, if you add a new key-value pair to a dictionary, this pair will appear in an existing view created from
dict.items().
-
Iterable: View objects are iterable. You can loop over them to access their elements. For example, you can iterate over a
dict.values()view to access all the values in the dictionary. -
Not a List: Despite being iterable, a view object is not a list. It does not store all its elements in memory; it dynamically queries the underlying dictionary. If you need a list, you can explicitly convert a view object to a list with
list(view_object). -
Efficiency: Because they don’t make a copy of the keys or values, view objects are more memory-efficient than manually creating a list of keys or values, especially for large dictionaries.
The 3 different types of errors

Success
SyntaxError
- Occurs when Python encounters incorrect syntax (something it doesn’t parse).
- Examples include missing colons, incorrect indentation, or wrong keywords.
Success
NameError
- Happens when a variable is not defined, i.e., it has not been assigned a value or simply does not exist.
- Typically caused by typos or using a variable before it is defined.
Success
TypeError
- Raised when an operation or function is applied to an object of an inappropriate type.
- Common when trying to perform operations on values of different types, like adding a number to a string.
Success
IndexError
- Occurs when trying to access an index that is not present in a list, tuple, or other indexable type.
- Common with lists or strings when trying to access an element that is outside the range of valid indices.
Success
KeyError
- Similar to
IndexError, but for dictionaries.- Happens when trying to access a dictionary with a key that does not exist.
Success
AttributeError
- Raised when an attribute reference or assignment fails.
- For example, trying to access a method or property of an object that doesn’t have that method or property.
Success
ValueError
- Occurs when a function receives an argument of the correct type but an inappropriate value.
- For example, trying to convert a string that does not represent a number into an integer.
Success
ZeroDivisionError
- Happens when trying to divide a number by zero.
- Division by zero is mathematically undefined and not allowed in Python.
Success
ImportError
- Raised when the
importstatement has trouble trying to load a module.- Can be due to the module not existing or circular imports.
Success
ModuleNotFoundError
- A subclass of
ImportErrorraised when a module could not be found.- Occurs when trying to
importa module that doesn’t exist in the Python path.
Success
IndentationError
- Specific to Python, due to its use of indentation to define code blocks.
- Occurs when the indentation is not consistent throughout the code.
Success
OverflowError
- Raised when an arithmetic operation exceeds the limits of a numeric type.
- Common in fixed-size numeric types like C longs in Python 2.x, less common in Python 3.x due to flexible integer size.
Success
MemoryError
- Occurs when an operation runs out of memory.
- More common in environments with limited memory, like embedded systems.
Success
RecursionError
- Happens when the maximum recursion depth is exceeded.
- Common in recursive functions that don’t have a proper base case.
- Nibble = 8, Byte = 8
What’s best practice for… venv
What’s wrong with this list initialization
dp = [[False] * int(sum(nums)//2+1)] * (len(nums)+1)