

# Imagine we didn’t have the built-in Python set. 
# We want to create our own "Set" class.

# Desired behavior:
#
# Given an instance of Set, we’ll need to be able to
#
#   (1) add items to it, 
#   (2) remove items from it, and 
#   (3) check whether it contains a certain value. 
#
# We’ll create all of these as member functions, which means 
# we’ll access them with a dot after a Set object

# by convention, we give classes PascalCase names
class Set:
    # these are the member functions
    # every one takes a first parameter "self" (another convention)
    # that refers to the particular Set object being used

    def __init__(self, values=None):
        """This is the constructor.
        It gets called when you create a new Set.
        You would use it like
        s1 = Set() 		# empty set
        s2 = Set([1,2,2,3]) 	# initialize with values"""

        self.dict = {}  # each instance of Set has its own dict property
                        # which is what we'll use to track memberships

        # Check for duplicates
        if values is not None:
            for value in values:
                self.add(value)

    def __repr__(self):
        """this is the string representation of a Set object
        if you type it at the Python prompt or pass it to str()"""

        return "Set: " + str(self.dict.keys())

    # we'll represent membership by being a **key** in self.dict 
    # with value True
    def add(self, value):
        self.dict[value] = True

    # value is in the Set if it's a key in the dictionary
    def contains(self, value):
        return value in self.dict

    def remove(self, value):
        del self.dict[value]


# Try it out:

s = Set([1,2,3])
print(s)

s.add(4)
print(s)

print(s.contains(4))		# True

s.remove(3)
print(s)
print(s.contains(3))		 # False
