Coding > Python Mixed > Flashcards
Python Mixed Flashcards
NumPy Array
- A multi-dimensional array provided by the Numerical Python library.
- Homogeneous: All elements are of the same type (lists are heterogenous).
- Efficient in terms of memory and speed.
- Supports a wide range of mathematical operations natively.
- Fixed in size once created.
””””
More than one dimension:
np.array([[1, 2], [3, 4]])
array([[1, 2],
[3, 4]])
“”””
Minimum dimensions 2:
np.array([1, 2, 3], ndmin=2)
array([[1, 2, 3]])
“”””
Type provided:
np.array([1, 2, 3], dtype=complex)
array([ 1.+0.j, 2.+0.j, 3.+0.j])
zip function
- Combines two or more iterables into a sequence of tuples.
- Each tuple contains elements from the input iterables paired together.
- Stops when the shortest iterable is exhausted.
- Example: zip([1, 2, 3], [‘a’, ‘b’, ‘c’]) -> [(1, ‘a’), (2, ‘b’), (3, ‘c’)]
Iterables
- Objects that can be looped over or traversed.
- Returns an iterator to loop over its elements.
- Examples include lists, dictionaries, strings, and sets.
Tuples
- Ordered and immutable collections.
- Used to represent data where order is significant and modification is not permitted.
- Defined using parentheses, e.g., (1, ‘a’, 3.4) –> Can be unpacked: a, b, c = (1, ‘a’, 3.4)
Binary tree
Each node has at MOST 2 children
Binary search tree
a binary tree in which all the left children of a node <= n (node in question) < all right descendants
Static memory allocation
E.g., stacks or arrays: will manage memory for you and assume a fixed amount of memory upon instantiation with a cap on how much data may be added.
dynamic memory allocation
e.g., heaps or linked lists: allow you to allocate and reallocate memory within the life of the program.
Nodes
An individual node contains data and links to other nodes. Each data structure adds additional constraints or behavior to these features to create the desired structure.
Pointers
The link or links within the node are sometimes referred to as pointers. This is because they “point” to another node
What is the time complexity of a linear search algorithm?
O(N)
N/2 depicted as O(N) in Big O connotation
What is the time complexity for binary search?
O(log N)
How many search comparisons will a binary algorithm make in a sorted 1000-element list?
log(1000)
list of integers 1 to n, with one missing, find it
use n*(n+1)/2 formula to find sum of full list, then subtract sum of missing list
Display the first five rows of the DataFrame, including column titles
Df.head()
further commands:
Df.columns
Df.info()
Df.describe()
for a Dataframe df, create a rolling window for the “return” column
df[‘return’].rolling(window=…)
What does .apply(lambda x: (x + 1).prod() - 1) accomplish in the context of rolling windows?
- Applies a custom calculation to each rolling window.
- lambda x: Defines an anonymous function for the calculation.
- (x + 1): Adds 1 to each element (useful for compounding returns)
- .prod(): Computes the product of elements in the window, compounding the returns.
- 1: Adjusts the final compounded product back to a % format.
iterate over dict_x
for key, value in dict_x.items():
What are the three main operations for a stack?
- Push: adds data to the top of the stack
- Pop: removes and provides data from the top of the stack
- Peek: reveals data on the top of the stack
hash function will first compute…
a value using some scoring metric –> this is the hash value, hash code, or just the hash.
Our hash map implementation then takes that hash value …. the size of the array (missing word…)
mod
mod = modulo operation
a modulo n (abbreviated as a mod n) is the remainder of the Euclidean division of a by n, where a is the dividend and n is the divisor.
defining feature of all hash functions: they greatly reduce any possible inputs into a much smaller range of potential outputs –> thus known as…
compression functions.
Is hashing a reversible process?
No
Many hash functions implementations for strings take advantage of the fact that strings are represented internally as numerical data. Frequently a hash function will perform … of the data bitwise, which is computationally simple for a computer to do but also can predictably assign numbers to strings.
a shift
How is the storage location at the index given by a hash called?
hash bucket
avoid a hash collision - strategies
- separate chaining: updates the underlying data structure, e.g. linked lists instead of array
- open addressing: one common method: probing (i.d. finding new array indices)
open addressing techniques
- Linear probing systems: e.g. jump by 1 or 5 steps
- quadratic probing: e.g. 1, 4, 9, etc. to avoid clustering
determine whether a HTTP get request worked, otherwise output “Invalid response”
assert response.status_code == 200, “Invalid response”
parse the JSON content of an object and convert it into a Python data structure (in this case, a dictionary)
.json()
drop NaN values in a pd frame
dropna()
calculate a correlation matrix for a pd frame (with percentage changes as values
pd_frame.corr()
perform matrix multiplication with numpy
np.matmul(matrix1, matrix2)
function to in numpy and other numerical computing libraries identify the index of the maximum value in an array
argmax()
generate random numbers from a normal distribution
np.random.normal() –> numpy function which takes two key parameters: loc and scale, which represent the mean and standard deviation of the distribution, respectively.
calculate the exponential of all elements in an input array with e as the base of the logarithm
np.exp(x)
x can be a number, a list, or a NumPy array of numbers
Returns: An array of the same shape as x, with each element being e raised to the power of the corresponding element in x.
e^1 = e
matrix multiplication between a matrix and an array
np.dot(…, …)
transpose the weights vector from a column vector to a row vector - and for 1D numpy arrays?
.T –> transpose the weights vector from a column vector to a row vector
However, for 1D NumPy arrays, .T does not change its shape.
check whether something ends or starts with a certain string
.endswith() or .startswith() –> accepts only string or tuple
Recursion vs iteration
Recursion and iteration are both different ways to execute a set of instructions repeatedly. The main difference between these two is that in recursion, we use function calls to execute the statements repeatedly inside the function body, while in iteration, we use loops like “for” and “while” to do the same.
Traversal vs iteration
“Traversal” just means walking through (all or some) elements of a data structure.
Historically, “iteration” in computer science is a special form of recursion for which no additional stack space is needed – in other words, tail recursion. This form is computationally exactly equivalent to what we now colloquially know as “iteration”, namely a finite loop (such as a for loop with a fixed lower and upper bound).
Now this makes iteration especially well suited (compared to general recursion) for traversing linear data structures. Note that it does not work for all containers (e.g. general graphs) because here you need to remember the already visited nodes (e.g. using depth-first search, which is defined recursively in terms of adjacent nodes, rather than via the C++ concept of iterators).
It is in this context that the term “iteration” is used in C++ applied to containers.
In summary: not every traversal is an iteration but every iteration (over a data structure) is a traversal. However, it’s worth noting that many people make no such distinction and use the terms interchangeably.
tail-recursive function
A function is tail-recursive if it ends by returning the value of the recursive call
–> recursive function where the recursive call is the last statement the function executes
heap
Heap is a special tree structure in which each parent node is less than or equal to its child node. Then it is called a Min Heap. If each parent node is greater than or equal to its child node then it is called a max heap. It is very useful is implementing priority queues where the queue item with higher weightage is given more priority in processing.
What is Big O notation?
Big O Notation gives the upper-bound runtime or worst-case complexity of an algorithm
What Are Objects And Classes?
Sure! In programming, think of a “class” as a blueprint for making something. It’s like the concept of a “car” in general; you know a car has wheels, seats, and an engine, but this general idea doesn’t tell you anything about a specific car, like its color or make.
Objects are like individual instances or examples of that blueprint. If a “class” is the general concept of a “car,” then an “object” would be a specific car, like a red Toyota Corolla with a sunroof.
Classes and Objects in terms of Grammar:
- Class = Noun: A class is like a “noun,” a general concept that describes things. For example, “Dog” is a noun that represents a general concept of a four-legged animal that barks.
- Object = Proper Noun: An object is like a “proper noun,” a specific instance of that general concept. For example, “Fido” would be a specific dog with its own unique traits and behaviors.
- Attributes = Adjectives: Attributes are qualities or characteristics of the object. Just like adjectives describe nouns, attributes describe or provide more details about objects. For example, the color of the car, or the breed of the dog.
- Methods = Verbs: Methods are actions that the object can perform. Like how verbs show what a noun can do, methods define what an object can do. For example, a dog can “bark,” or a car can “accelerate.”
Example:
Let’s take a class called “Dog.”
- Class (Noun): Dog
- Attributes (Adjectives): Breed, Color, Age
- Methods (Verbs): Bark, Fetch
Now, let’s create an object from this class.
-
Object (Proper Noun): Fido
- Attributes (Adjectives): Golden Retriever, Yellow, 3 years
- Methods (Verbs): Fido can Bark, Fido can Fetch
So, a class is like the blueprint that tells us what a ‘Dog’ should have and be able to do, while an object is a specific ‘Dog’ with its own attributes and behaviors.
Treehouse Notes:
The class keyword lets us define a class. We use it just like we do the def keyword for making functions. Class definitions are blocks like function definitions.
class NewClass:
Inside of the class, variables are called attributes.
class NewClass: name_attribute = "Kenneth"
And functions that are defined inside of a class are called methods.
~~~
class NewClass:
name_attribute = “Kenneth”
def name_method(self): return self.name_attribute ~~~ Whenever we call a class, it creates an instance. Each instance has full access to the all of the attributes and methods of the class. ~~~ new_instance = NewClass() new_instance.name_method() ~~~
In Python, only dictionaries, lists, tuples, and sets are objects. Is this true?
No, that statement is not true. In Python, nearly everything is an object. This includes not just dictionaries, lists, tuples, and sets, but also numbers, strings, functions, and even modules and classes themselves. Python is an object-oriented language, which means that it uses objects as a fundamental building block for constructing programs.
Examples:
-
Numbers are objects: You can find out the type of an object using the
type()
function.
python x = 42 print(type(x)) # Output: <class 'int'>
-
Strings are objects: They have methods like
upper()
,lower()
, etc.
python s = "hello" print(s.upper()) # Output: "HELLO"
-
Functions are objects: You can assign them to variables, pass them as arguments, etc.
```python
def my_function():
print(“Hello from my_function”)func_var = my_function
func_var() # Output: “Hello from my_function”
``` -
Modules are objects: You can assign them to variables and manage them just like any other object.
python import math print(type(math)) # Output: <class 'module'>
-
Even Classes are objects: They are instances of a meta-class.
```python
class MyClass:
passprint(type(MyClass)) # Output: <class ‘type’>
```
So, in Python, the concept of an “object” is very broad and not limited to just a few data types.
Sequence 1: The file characters.py contains:
~~~
class Thief:
pass
~~~
The following is run within terminal/console:
~~~
python
from characters import Thief
kenneth = Thief()
kenneth
~~~
Sequence 2:
The file characters.py contains:
~~~
class Thief:
sneaky = True #attribute
~~~
The following is run within terminal/console:
~~~
python
from characters import Thief
kenneth = Thief()
kenneth.sneaky
~~~
Explain the sequence 1 and 2, what’s happening in it?
Certainly! Let’s go through both sequences step-by-step.
Sequence 1:
-
File Creation: The file
characters.py
contains a class definition forThief
. Thepass
statement is a placeholder indicating that the class is currently empty; it doesn’t have any attributes or methods yet.python class Thief: pass
-
Console/Terminal Steps:
-
python
: This command starts the Python interpreter. -
from characters import Thief
: This imports theThief
class from thecharacters.py
file. Now you can create instances (objects) of this class. -
kenneth = Thief()
: This creates a new object of theThief
class and assigns it to the variablekenneth
. -
kenneth
: This would display a representation of thekenneth
object, something like<\_\_main\_\_.Thief object at 0x7f8f9c0>
.
-
Sequence 2:
-
File Creation: The file
characters.py
has been updated to include an attributesneaky
in theThief
class, set toTrue
.python class Thief: sneaky = True # attribute
-
Console/Terminal Steps:
-
python
: Starts the Python interpreter. -
from characters import Thief
: Imports the updatedThief
class from thecharacters.py
file. -
kenneth = Thief()
: Creates a new object of theThief
class and assigns it to the variablekenneth
. -
kenneth.sneaky
: Accesses thesneaky
attribute of thekenneth
object. Sincesneaky
is set toTrue
in the class definition, this would returnTrue
.
-
Summary:
- In Sequence 1, you created an empty
Thief
class and made an instance of it. The instance didn’t have any special attributes or methods because the class was empty. - In Sequence 2, you added a
sneaky
attribute to theThief
class and set it toTrue
. When you made an instance of this updated class, you could access this attribute, which returnedTrue
.
In both sequences, the steps in the terminal are to import the class and create an instance (object) of that class. The key difference is in the attributes that the class and its instances have.
Sequence 1:
The file characters.py contains the following code:
~~~
import random
class Thief:
sneaky = True #attribute
def pickpocket(self): #methods
return bool(random.randint(0, 1))
~~~
The following code is run in console/terminal:
~~~
python
from characters import Thief
kenneth = Thief()
kenneth.pickpocket() #returns false
Thief.pickpocket() #returns error as has no self
Thief.pickpocket(kenneth) #kenneth is self, returns false
~~~
Sequence 2:
The file characters.py contains the following code:
~~~
import random
class Thief:
sneaky = True #attribute
def pickpocket(self): #methods
print(“Called by {}”.format(self))
return bool(random.randint(0, 1))
~~~
The following code is run in console/terminal:
~~~
python
from characters import Thief
kenneth = Thief()
kenneth.pickpocket()
Thief.pickpocket(kenneth)
~~~
Sequence 3:
The file characters.py contains the following code:
~~~
import random
class Thief:
sneaky = True #attribute
def pickpocket(self): #methods
if self.sneaky:
return bool(random.randint(0, 1))
return False
~~~
The following code is run in console/terminal:
~~~
python
from characters import Thief
kenneth = Thief()
kenneth.pickpocket() #returns True
kenneth.pickpocket() #returns Talse
kenneth.pickpocket() #returns True
kenneth.sneaky = False
kenneth.pickpocket() #returns False
kenneth.pickpocket() #returns False
kenneth.pickpocket() #returns False
~~~
Explain the sequence 1,2,3 and what’s happening in it?
Absolutely! Let’s break down what’s happening in each of the sequences.
Sequence 1:
-
File Code: In
characters.py
, aThief
class is defined with an attributesneaky
set toTrue
and a methodpickpocket
that returns a random boolean value (True
orFalse
).```python
import randomclass Thief:
sneaky = True
def pickpocket(self):
return bool(random.randint(0, 1))
``` -
Console Steps:
-
kenneth = Thief()
: Creates an objectkenneth
of classThief
. -
kenneth.pickpocket()
: Calls thepickpocket
method on thekenneth
object. This returnsFalse
due to the random number generated. -
Thief.pickpocket()
: Tries to callpickpocket
directly on the class, which results in an error because noself
argument is provided. -
Thief.pickpocket(kenneth)
: Callspickpocket
on the class, passingkenneth
as theself
argument. This works and returnsFalse
(due to random generation).
-
Sequence 2:
-
File Code: Similar to Sequence 1, but the
pickpocket
method now includes aprint
statement to show which object called it.python def pickpocket(self): print("Called by {}".format(self)) return bool(random.randint(0, 1))
-
Console Steps:
-
kenneth.pickpocket()
: Calls the method and prints “Called by <Thief>".</Thief> -
Thief.pickpocket(kenneth)
: Similar to the above but called directly on the class. It also prints the same message.
-
Sequence 3:
-
File Code: The
pickpocket
method now includes anif
condition that checks thesneaky
attribute before returning a random boolean.python def pickpocket(self): if self.sneaky: return bool(random.randint(0, 1)) return False
-
Console Steps:
-
kenneth.pickpocket()
: Called multiple times and returns eitherTrue
orFalse
based on random generation, becausesneaky
isTrue
. -
kenneth.sneaky = False
: Setssneaky
toFalse
. -
kenneth.pickpocket()
: Now always returnsFalse
assneaky
is set toFalse
.
-
Summary:
- Sequence 1: Demonstrates basic class and method usage, including how to call methods both on an instance and directly on the class.
- Sequence 2: Adds a print statement to show which instance is calling the method.
- Sequence 3: Adds conditional logic to the method based on an attribute, demonstrating how methods can access and use the attributes of the instance on which they are called. It also shows how changing an attribute affects the behavior of methods.
Challenge Task 1 of 1
This class should look familiar! First, I need you to add a method named praise
to the Student
class. It should take the self
argument. Then, inside the praise
method, return
a positive message about the student using the name
attribute. As an example, it could say “You’re doing a great job, Jacinta!” or “I really like your hair today, Michael!”. Feel free to change the name
attribute to your own name, too!
File: first_class.py:
~~~
class Student:
name = “Your Name”
~~~
Task 1:
Variant 1:
~~~
class Student:
name = “Sethu”
def praise(self): return "You're doing a great job {}".format(self.name) ~~~
Variant 2:
~~~
class Student:
name = “Sethu”
def praise(self): return f"You're doing a great job, {self.name}!" ~~~
Run:
~~~
# Adding a method named ‘praise’ to the Student class
class Student:
name = “Your Name”
def praise(self): return f"You're doing a great job, {self.name}!"
Create an instance of the Student class to test the praise method
student_instance = Student()
praise_message = student_instance.praise()
praise_message
~~~
Result:
~~~
“You’re doing a great job, Your Name!”
~~~
Sequence 1:
The file characters.py contains the following:
~~~
import random
class Thief:
sneaky = True #attribute
def pickpocket(self): #methods
if self.sneaky:
return bool(random.randint(0, 1))
return False
def hide(self, light_level):
return self.sneaky and light_level <10
~~~
The following code is run in Terminal/Console:
~~~
python
from characters import Thief
kenneth = Thief()
kenneth.hide(4)
kenneth.hide(14)
kenneth.sneaky = False
kenneth.hide(0)
~~~
Sequence 2:
The file characters.py contains the following:
~~~
import random
class Thief:
sneaky = True # attribute
def __init__(self, name, sneaky=True, **kwargs):
self.name = name
self.sneaky = sneaky
def pickpocket(self): # methods
return self.sneaky and bool(random.randint(0, 1))
def hide(self, light_level):
return self.sneaky and light_level < 10
~~~
The following code is run in Terminal/Console:
~~~
from characters import Thief
kenneth = Thief(“Kenneth”, False)
kenneth.name
kenneth.sneaky
~~~
Sequence 3:
The file characters.py contains the following:
~~~
import random
class Thief:
sneaky = True # attribute
def __init__(self, name, sneaky=True, **kwargs):
self.name = name
self.sneaky = sneaky
for key, value in kwargs.items(): setattr(self, key, value)
def pickpocket(self): # methods
return self.sneaky and bool(random.randint(0, 1))
def hide(self, light_level):
return self.sneaky and light_level < 10
~~~
The following code is run in Terminal/Console:
~~~
from characters import Thief
kenneth = Thief(“Kenneth”, scars=None, favorite_weapon=”Wit”)
kenneth.name
kenneth.sneaky
kenneth.favorite weapon
~~~
Explain the sequence 1,2,3 and what’s happening in it?
Certainly, let’s explore each sequence in more detail, taking into account both the code within characters.py
and the code run in the terminal.
Sequence 1
characters.py
- Thief
class is defined with a class attribute sneaky
set to True
.
- Two methods, pickpocket()
and hide(light_level)
, are also defined. pickpocket()
returns a random boolean if sneaky
is True
, and hide()
returns True
if sneaky
is True
and light_level
is less than 10.
Terminal/Console
- An object named kenneth
is created from the Thief
class.
- kenneth.hide(4)
is called and would return True
because light_level
(4) is less than 10 and sneaky
is True
.
- kenneth.hide(14)
would return False
because light_level
(14) is not less than 10.
- kenneth.sneaky
is set to False
.
- kenneth.hide(0)
is called and would now return False
because sneaky
is False
, irrespective of light_level
.
Sequence 2
characters.py
- Thief
class now includes an \_\_init\_\_
method to initialize name
and sneaky
attributes when a new object is created.
- pickpocket()
is modified to return a boolean based on both sneaky
and a random value between 0 and 1.
Terminal/Console
- A new object named kenneth
is created with sneaky
set to False
and name
set to “Kenneth”.
- Accessing kenneth.name
would return “Kenneth”.
- Accessing kenneth.sneaky
would return False
.
Sequence 3
characters.py
- Thief
class is further modified to accept arbitrary keyword arguments (**kwargs
) in the \_\_init\_\_
method.
- These keyword arguments are set as attributes on the object using the setattr
function.
Terminal/Console
- A new object named kenneth
is created with additional attributes: scars
is set to None
, and favorite_weapon
is set to “Wit”.
- Accessing kenneth.name
would return “Kenneth”.
- Accessing kenneth.sneaky
would return True
(default value as no value for sneaky
was provided during object creation).
- Accessing kenneth.favorite_weapon
would return “Wit”. Note: The code has a typo and uses kenneth.favorite weapon
which would actually result in a syntax error. It should be kenneth.favorite_weapon
.
In summary, these sequences display the evolution of the Thief
class, starting from a simple version to a more complex one that allows for custom attributes and initialization. The terminal/console interactions help to show how these class features can be accessed and modified for individual objects.
Challenge Task 1 of 1
Alright, I need you to make a new method named feedback
. It should take self
and an argument named grade
. Methods take arguments just like functions do.
Inside the feedback
method, if grade
is above 50, return the result of the praise
method. If it’s 50 or below, return the reassurance
method’s result.
first_class.py:
~~~
class Student:
name = “Your Name”
def praise(self): return "You inspire me, {}".format(self.name) def reassurance(self): return "Chin up, {}. You'll get it next time!".format(self.name) ~~~
Task 1:
Certainly! To implement the feedback
method, you can check the value of the grade
argument and return the result of either the praise
or reassurance
method accordingly. Here’s how you can update the Student
class in first_class.py
:
```python
class Student:
name = “Your Name”
def praise(self): return "You inspire me, {}".format(self.name) def reassurance(self): return "Chin up, {}. You'll get it next time!".format(self.name) def feedback(self, grade): if grade > 50: return self.praise() else: return self.reassurance() ~~~
Now, the Student
class has a feedback
method that takes a grade
argument. If grade
is greater than 50, the method returns the result of praise()
. Otherwise, it returns the result of reassurance()
.
You can test the feedback
method by creating an instance of the Student
class and calling it:
```python
student1 = Student()
student1.name = “Alice”
print(student1.feedback(60)) # Output: “You inspire me, Alice”
print(student1.feedback(40)) # Output: “Chin up, Alice. You’ll get it next time!”
~~~
Challenge Task 1 of 2:
Our Student
class is coming along nicely!
I’d like to be able to set the name
attribute at the same time that I create an instance. Can you add the code for doing that?
Override the \_\_init\_\_
method by adding your own \_\_init\_\_
method to the Student class. Add self and name as arguments to the \_\_init\_\_
method. Inside of \_\_init\_\_
, set self.name
to the argument name
.
first_class.py:
~~~
class Student:
name = “Your Name”
def praise(self): return "You inspire me, {}".format(self.name) def reassurance(self): return "Chin up, {}. You'll get it next time!".format(self.name) def feedback(self, grade): if grade > 50: return self.praise() return self.reassurance() ~~~
Challenge Task 2 of 2:
Sometimes I have other attributes I need to store on a Student
instance. Add **kwargs
as an argument to the \_\_init\_\_
method. Then use setattr
inside the \_\_init\_\_
method to add attributes for any other key/value pairs I want to send to the instance when I create it.
first_class.py:
~~~
class Student:
name = “Your Name”
def \_\_init\_\_(self, name): self.name = name def praise(self): return "You inspire me, {}".format(self.name) def reassurance(self): return "Chin up, {}. You'll get it next time!".format(self.name) def feedback(self, grade): if grade > 50: return self.praise() return self.reassurance() ~~~
Task 1:
~~~
class Student:
name = “Your Name”
def \_\_init\_\_(self, name): self.name = name def praise(self): return "You inspire me, {}".format(self.name) def reassurance(self): return "Chin up, {}. You'll get it next time!".format(self.name) def feedback(self, grade): if grade > 50: return self.praise() return self.reassurance() ~~~
Task 2:
~~~
class Student:
name = “Your Name”
def \_\_init\_\_(self, name, **kwargs): self.name = name for key, value in kwargs.items(): setattr(self, key, value) def praise(self): return "You inspire me, {}".format(self.name) def reassurance(self): return "Chin up, {}. You'll get it next time!".format(self.name) def feedback(self, grade): if grade > 50: return self.praise() return self.reassurance() ~~~