Type checking functions

print(type("goodbye")) #<class 'str'>
print(type("goodbye") == type("hello"))  #True
print(type("goodbye") == type(3))  #False

class C:
  pass
class B(C):
  pass
class A(B):
  pass

a = A()
b = B()
c = C()

print(isinstance(a, A))  #True
print(isinstance(a, B))  #True
print(isinstance(a, C))  #True
print(isinstance(c, A))  #False

print(issubclass(A, A))  #True
print(issubclass(A, B))  #True
print(issubclass(A, C))  #True
print(issubclass(C, A))  #False

Duck Typing

If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.

# The sorted function is using the principle of duck typing
# This is a Duck Typing style design

print(sorted(['foo','bar','fox']))  #['bar', 'foo', 'fox']
print(sorted({'foo','bar','fox'}))  #['bar', 'foo', 'fox']
print(sorted({'key1':'foo', 'key2':'bar', 'key3':'fox'}))  #['key1', 'key2', 'key3']
print(sorted('foobarfox'))  #['a', 'b', 'f', 'f', 'o', 'o', 'o', 'r', 'x']

print(sorted(99644))  #TypeError: 'int' object is not iterable

try:
  print(sorted(99644))
except:
  print("Error happened while sorted")
def calculate(x, y,z):
  return (x + y) * z

print(calculate(3, 2, 2))  #10
print(calculate('foo', 'bar', 2))  #foobarfoobar
print(calculate([1, 3], [4, 2], 3))  #[1, 3, 4, 2, 1, 3, 4, 2, 1, 3, 4, 2]

try:
  print(calculate([1, 3], 3, 5))
except:
  print('we got error')

TypedList

The advantage of a one-type list includes tracking errors and making the list stable. If we add something that shouldn’t be in the list, we can quickly figure it out at the beginning of our development.

class TypedList:
    def __init__(self, example_element, initial_list):
        self.type = type(example_element)
        if not isinstance(initial_list, list):
            raise TypeError("Second argument of TypedLisst must be a list.")
        for element in initial_list:
            self.__check(element)
        self.elements = initial_list[:] #copy be value

    def __check(self, element):
        if type(element) != self.type:
            raise TypeError(
                "Attempted to add an element of incorrect type to a TypedList.")
    
    def __setitem__(self, i, element):
        self.__check(element)
        self.elements[i] = element
    
    def __getitem__(self, i):
        return self.elements[i]
    
    def __str__(self):
        return str(self.elements)
    
    def __add__(self, anotherList):
      return len(self.elements) + len (anotherList.elements)

x = TypedList('Hello', ['some', 'original', 'stuff'])
print(x)  #['some', 'original', 'stuff']
y = TypedList('', [''] * 5)
print(y)  #['', '', '', '', '']
print(x + y)  #8
class TypedList(list):
    def __init__(self, example_element, initial_list):
        self.type = type(example_element)
        if not isinstance(initial_list, list):
            raise TypeError("Second argument of TypedLisst must be a list.")
        for element in initial_list:
            self.__check(element)
        super().__init__(initial_list)

    def __check(self, element):
        if type(element) != self.type:
            raise TypeError(
                "Attempted to add an element of incorrect type to a TypedList.")

    def __setitem__(self, i, element):
        self.__check(element)
        super().__setitem__(i, element)

    def __getitem__(self, i):
        return super().__getitem__(i)

x = TypedList('Hello', ['Some', 'original', 'stuff'])
print(x)  #['Some', 'original', 'stuff']
y = TypedList('', [''] * 5)
print(y)  #['', '', '', '', '']
print(x + y)  #['Some', 'original', 'stuff', '', '', '', '', '']

Decimal, Binary, and Hexadecimal