HW for 6_15

This commit is contained in:
2023-06-15 11:34:03 -05:00
parent f4981fb8fd
commit fe40d7f00e
+165
View File
@@ -0,0 +1,165 @@
class BananaContextManager:
def __init__(self, banana_list):
self.banana_list = banana_list
def __enter__(self):
self.banana_list.append("🍌") # Add a banana to the list
return self
def __exit__(self, exc_type, exc_value, traceback):
if self.banana_list: # Check if the list is not empty
self.banana_list.pop() # Remove a banana from the list
my_banana_list = []
with BananaContextManager(my_banana_list):
print(my_banana_list)
print(my_banana_list) # Output: []
#Questions: can you use a with block inside of another with block?
class BananaContextManager:
def __init__(self, banana_list):
self.banana_list = banana_list
def __enter__(self):
self.banana_list.append("🍌") # Add a banana to the list
return self
def __exit__(self, exc_type, exc_value, traceback):
if self.banana_list: # Check if the list is not empty
self.banana_list.pop() # Remove a banana from the list
my_banana_list = []
with BananaContextManager(my_banana_list) as outer_cm:
print(my_banana_list)
with BananaContextManager(outer_cm.banana_list) as inner_cm:
inner_cm.banana_list.append("🍌") # Add another banana to the list
print(my_banana_list)
inner_cm.banana_list.pop() # Remove a banana from the list
print(my_banana_list)
print(my_banana_list)
print(my_banana_list)
#The number of bananas in the list are 1,3,2,1,0.
#question:can you structure the program so that you can get the class to have more than 0 bananas *outside* of a with block?
class BananaContextManager:
def __init__(self, banana_list, initial_bananas=0):
self.banana_list = banana_list
self.initial_bananas = initial_bananas
def __enter__(self):
for _ in range(self.initial_bananas):
self.banana_list.append("🍌")
self.banana_list.append("🍌") # Add a banana to the list
return self
def __exit__(self, exc_type, exc_value, traceback):
if self.banana_list: # Check if the list is not empty
self.banana_list.pop() # Remove a banana from the list
# Usage example
my_banana_list = []
banana_count = 1 # Number of bananas outside the with block
with BananaContextManager(my_banana_list, banana_count) as outer_cm:
print(my_banana_list)
with BananaContextManager(outer_cm.banana_list) as inner_cm:
inner_cm.banana_list.append("🍌") # Add another banana to the list
print(my_banana_list)
inner_cm.banana_list.pop() # Remove a banana from the list
print(my_banana_list)
print(my_banana_list)
print(my_banana_list)
#Update notes:
#salting:
#Let's say we have two users, Alice and Bob, who both have the same password, "password123". Without salting,
#if we were to hash their passwords directly, they would produce the same hash value:
'''''
Alice's Password: password123
Bob's Password: password123
Hashed Password (Alice and Bob): 7c6a180b36896a0a8c02787eeafb0e4c7b07a52e
'''''
#As you can see, the hashed passwords for both Alice and Bob are the same. This could be a problem because if an attacker obtains the hash value,
#they can easily determine that Alice and Bob have the same password.
#Now, let's introduce salting to the process. Each user will have a unique salt that is added to their password before hashing.
# Here's an updated example:
'''''
Alice's Password: password123
Bob's Password: password123
Alice's Salt: QGdG9jzV
Bob's Salt: d8K27fsE
Salted and Hashed Password (Alice): QGdG9jzVpassword123 -> 48cf6b7b4b04819f6d717c9bc67a4feae0f1081a
Salted and Hashed Password (Bob): d8K27fsEpassword123 -> d5fd5b3a42f8e6bc8c9844feeff24f4cb4fd8fa4
'''''
#Now, even though Alice and Bob have the same password, their hashed passwords are different
#because they used different salts. The salt makes each hash unique, even when the passwords are the same.
#Rich comparison methods:
#Rich comparison methods allow objects to be compared using operators like <, >, ==, etc. By implementing these
#methods in a class, you can define how objects of that class should be compared. Here's an example
#using the __eq__ method to compare two Point objects:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
return self.x == other.x and self.y == other.y
point1 = Point(1, 2)
point2 = Point(1, 2)
point3 = Point(3, 4)
print(point1 == point2) # Output: True
print(point1 == point3) # Output: False
#Swapped-argument versions:
#Swapped-argument versions of methods provide flexibility when working with commutative operations.
#For example, if you have a class representing a mathematical operation and want to support swapping the operands,
#you can define a swapped-argument version of the method.
#Hashed collections:
#Hashed collections like dictionaries (dict) and sets (set) use hash functions internally to efficiently store
#and retrieve data. Here's an example using a dictionary:
my_dict = {'apple': 5, 'banana': 3, 'orange': 2}
print(my_dict['apple']) # Output: 5
print(my_dict.get('banana')) # Output: 3
#Dictionary insertion:
#Dictionary insertion refers to adding key-value pairs to a dictionary. Here's an example:
my_dict = {'apple': 5, 'banana': 3}
# Inserting a new key-value pair
my_dict['orange'] = 2
print(my_dict) # Output: {'apple': 5, 'banana': 3, 'orange': 2}
#Multiple inheritance:
#Multiple inheritance allows a class to inherit from multiple base classes. Here's a simplified example:
class Base1:
def method1(self):
print("Base1 method")
class Base2:
def method2(self):
print("Base2 method")
class MyClass(Base1, Base2):
pass
my_object = MyClass()
my_object.method1() # Output: Base1 method
my_object.method2() # Output: Base2 method
#AI cannot give me practcial examples about Intentional asymmetry and Cryptography.