5. Data Structures

About this Tutorial –

Objectives –

Python is a powerful and popular object-oriented scripting language. This course provides a comprehensive introduction to the core syntax and functions provided by Python, including full coverage of its object-oriented features. The course also explores some of Python’s powerful APIs and techniques, including file handling, XML processing, object serialization, and Web service

Audience

This training course is aimed at new developers and experienced developers

Prerequisites

No previous experience in Python programming is required. But any experience you do have in programming will help. Also no experience in IDLE is required. But again any experience you do have with programming development environments will be a valuable.

Contents

The python course covers these topics and more:

  • Strings and Regular Expressions: Overview of strings in Python; Basic string manipulation; Introduction to regular expressions
  • XML Processing: XML essentials; Parsing XML documents; Searching for XML content; Generating XML data
  • Web Services: Overview of Web services; Implementing Web services using Python; Caching; Compression; Handling redirects

Download Solutions

HTML tutorial


Overview

Estimated Time – 1 Hour

Not what you are looking? Try the next tutorial – Object-Oriented Programming in Python

Lab 1: Sequence types

Lab 1: Sequence types
  1. Overview
    • Here’s a summary of the basic sequence types available in Python:
      • List – a mutable sequence.
      • Tuple – an immutable sequence.
      • Range – an immutable sequence of numbers, typically used in for loops.
    • Now for text sequences:
      • When we talk about text sequence types in Python, we really just mean strings. The fact that Python treats strings as sequences means that you can use all the standard sequence operations on strings (e.g. accessing characters using [], splicing strings using [start:end], getting the length of a string via len(), and so on). We’ll discuss these common sequence operations later in this section, so bear in mind these operations apply equally well to strings (as well as to lists, tuples, and ranges).
    • Here’s a summary of the binary sequence types:
      • bytes – an immutable sequence of single bytes, typically used for passing ASCII characters over networks.
      • bytesarray – a mutable counterpart to bytes.
      • memoryview – an object that allows Python code to access the internal data of an object that supports the buffer protocol (e.g. a bytes or bytesarray object) without copying.
  2. Creating a List
    • The simplest way to create a list is via one of the following mechanisms:
      • [] – Creates an empty list.
      • [item, item, item, … ] – Creates a list containing the specified items. The first item is index position 0.
      • list() – This is the list constructor, which creates an empty list
      • list(iterable) – You can call the list constructor with an “iterable object” as a parameter. An iterable object is an object capable of returning its members one at a time. Examples of iterables include all sequence types (e.g. list, tuple, range, string) and some non-sequence types (e.g. dict, file), plus any class that has an __iter__() or __getitem__() method.
    • Example
      list1 = []
      list2 = ["Italy", "France", "Spain"]
      list3 = [3, 12, 19, 1, 2, 7]
      list4 = list()
      list5 = list(list3)
      print("list1 has %d items: %s" % (len(list1), list1))
      print("list2 has %d items: %s" % (len(list2), list2))
      print("list3 has %d items: %s" % (len(list3), list3))
      print("list4 has %d items: %s" % (len(list4), list4))
      print("list5 has %d items: %s" % (len(list5), list5))
    • View Code File

    • Here is the output from the example
      list1 has 0 items: []
      list2 has 3 items: ['Italy', 'France', 'Spain']
      list3 has 6 items: [3, 12, 19, 1, 2, 7]
      list4 has 0 items: []
      list5 has 6 items: [3, 12, 19, 1, 2, 7]
  3. List Comprehensions
    • One of the most common ways to create a list is via a Python language mechanism called “list comprehensions”. This is how list comprehensions work:
      • First, you need an existing sequence (e.g. another list, a range, a tuple, etc.)
      • Then, you use the syntax shown to iterate over all the items in the existing sequence, and apply an operation on all the items. The results are collected into another list, which is the result of the statement
    • Consider the examples below:
      • squares is a list containing the squares of all the numbers in the range 0-5 inclusive.
      • ctemps is a list containing the Celsius equivalent of all the Fahrenheit temperatures in ftemps.
        squares = [x**2 for x in range(6)]
        ftemps = [32, 68, 212]
        ctemps = [(f-32)*5/9 for f in ftemps]
        print("squares: %s" % squares)
        print("ftemps: %s" % ftemps)
        print("ctemps: %s" % ctemps)
      • View Code File

    • Here is the output from the example above:
      squares: [0, 1, 4, 9, 16, 25]
      ftemps: [32, 68, 212]
      ctemps: [0.0, 20.0, 100.0]
  4. Common Sequence Operations
    • euro = ["GB", "ES", "NL", "F", "D", "I", "P"]
      asia = ["SG", "JP"]
      print("%s" % "F" in euro)        # True
      print("%s" % "F" not in euro)      # False
      print("%s" % (euro + asia))       # ['GB', 'ES', 'NL', 'F', 'D', 'I', 'P', 'SG', 'JP']
      print("%s" % (asia * 2))        # ['SG', 'JP', 'SG', 'JP']
      print("%s" % (2 * asia))        # ['SG', 'JP', 'SG', 'JP']
      print("%s" % (euro[1]))         # ES
      print("%s" % (euro[1:5]))        # ['ES', 'NL', 'F', 'D']
      print("%s" % (euro[1:5:2]))       # ['ES', 'F']
      print("%d" % len(euro))         # 7
      print("%s" % min(euro))         # D
      print("%s" % max(euro))         # P
      print("%d" % euro.index("NL"))     # 2
      print("%d" % euro.index("NL", 1))    # 2
      print("%d" % euro.index("NL", 1, 4))  # 2
      print("%d" % euro.count("ES"))     # 1
    • View Code File

    • This shows the common operations you can perform on any type of sequence, including lists, tuples, ranges, strings, etc. The example also shows the expected output, so you can see how the operations work.
      • in and not in indicate if the sequence contains the specified item.
      • + concatenates sequences, and returns a new sequence.
      • * concatenates n shallow copies of the sequence together.
      • s[i] accesses the item at the specified index in the sequence s, starting at 0.
      • s[i:j:k] returns a slice of the sequence s, from i to j with step k. You can omit j and k, so s[i] and s[i:j] are allowed.
      • len(s) returns the length of the sequence s.
      • min(s) and max(s) return the smallest and largest items in the sequence s.
      • s.index(item, i, j) returns the position of an item in a sequence s, or raises an error if not found. You can omit i and j, so s.index(item) and s.index(item, i) are allowed.
      • s.count(item) returns the count of times an item appears in a sequence s.
  5. Sequence Modification Operations
    • You can perform these operations on a mutable sequence such as a list:
      euro = ["GB", "ES", "NL", "F"]
      euro[0] = "CY"
      euro[1:3] = ["US", "AU", "AT"]
      euro.append("SW")
      euro.extend(["YU", "ZR"])
      euro.insert(1, "NI")
      print("%s" % euro) # ['CY', 'NI', 'US', 'AU', 'AT', 'F', 'SW', 'YU', 'ZR']
      euro.pop()
      euro.pop(1)
      del euro[2:4]
      print("%s" % euro) # ['CY', 'US', 'F', 'SW', 'YU']
      euro.remove("US")
      euro.reverse()
      print("%s" % euro) # ['YU', 'SW', 'F', 'CY']
      eurocopy = euro.copy()
      euro.clear()
      print("%s" % eurocopy) # ['YU', 'SW', 'F', 'CY']
      print("%s" % euro) # []
    • View Code File

    • This shows the modification operations you can perform on any mutable sequence, such as a list. The example also shows the expected output, so you can see how the operations work.
      • s[i:j:k] replaces a slice of the sequence s, from i to j with step k, with the items in the iterable object. You can omit j and k.
      • s.append(item) appends an item at the end of the sequence, s.
      • s.extend(iterable) appends all the items in the iterable object, to the end of the sequence, s.
      • s.insert(i,item) inserts an item at index i in the sequence, s.
      • s.pop(i) retrieves and removes the item at index i from the sequence, s. You can omit i, in which case it retrieves and removes the last item.
      • del s[i:j:k] removes a slice from the sequence s, from i to j with step k. You can omit j and k.
      • s.remove(item) removes first occurrence of item from the sequence, s.
      • s.reverse() reverses the items of the sequence, s, in place.
      • s.copy() returns a shallow copy of the sequence, s.
      • s.clear() removes all items from the sequence, s.
  6. Tuples
    • Tuples are immutable sequences, typically to store collections of heterogeneous data. Tuples are also used for cases where an immutable sequence of homogeneous data is needed, e.g. a set or dict.
    • You can create a tuple as follows. Note that the parentheses are optional – it’s the comma that makes it a tuple, not the parentheses:
      • () – Creates an empty tuple.
      • a, or (a,) – Using a trailing comma creates a singleton tuple.
      • a,b,c or (a,b,c) – Creates a tuple containing the specified items.
      • tuple() – This is the tuple constructor, which creates an empty tuple.
      • tuple(iterable) – Creates a tuple that contains the items from the iterable object.
    • Example:
      tuple1 = ()
      tuple2 = "Norway", # or: tuple2 = ("Norway",)
      tuple3 = 3, 19, 2 # or: tuple3 = (3, 19, 2)
      tuple4 = tuple()
      tuple5 = tuple(tuple3)
      print("tuple1 has %d items: %s" % (len(tuple1), tuple1))
      print("tuple2 has %d items: %s" % (len(tuple2), tuple2))
      print("tuple3 has %d items: %s" % (len(tuple3), tuple3))
      print("tuple4 has %d items: %s" % (len(tuple4), tuple4))
      print("tuple5 has %d items: %s" % (len(tuple5), tuple5))
    • View Code File

    • Here’s the output from the example:
      tuple1 has 0 items: ()
      tuple2 has 1 items: ('Norway',)
      tuple3 has 3 items: (3, 19, 2)
      tuple4 has 0 items: ()
      tuple5 has 3 items: (3, 19, 2)
  7. Ranges
    • To create a range, use the range constructor
      • range(start)
      • range(start, stop)
      • range(start, stop, step)
    • Example:
      def display_range(msg, r):
        print("\n" + msg)
        for i in r:
          print(i)
      range1 = range(5)
      range2 = range(5,10)
      range3 = range(5,10,2)
      display_range("range1", range1)
      display_range("range2", range2)
      display_range("range3", range3)
    • View Code File

    • Here is the output from the example:
      range1
      0
      ...
      4
      range2
      5
      ...
      9
      range3
      5
      7
      9
Lab
  1. Sieve of Eratosthenes
    • We are going to be making a very simple application that uses good work of lists and is used very often in terms of academia and research; the application is a function that calculates all of the prime numbers up into a certain limit that we define
    • How it works is by going through all the number from 2 to our limit and if a number it is not in a list of multiples then it can be consider prime as it can therefore only be divided by 1 and itself. Now, this number is added to a prime list, it is also added to a multiple list with all of its multiples
    • Try and make it yourself but just encase you’re having any trouble just follow the steps below:
      • Define the function and create 2 lists (one for primes and one for multiples):
        def eratosthenes(n):
          multiples = []
          primes = []
      • View Code File

      • Create a for loop to move through all the numbers from 2 until the limit and check if this number is in multiples and if not add it to primes and print it
        def eratosthenes(n):
          multiples = []
          primes = []
          for i in range(2, n+1):
            if i not in multiples:
              print (i)
              primes.append(i)
      • View Code File

      • Now we have found our prime just go through all the multiples of this number up until the limit and add them to multiples. This works by going from the square of that number in increments of that number. The reason we go from the square is because the multiples lower than the square will already be in the list
        def eratosthenes(n):
          multiples = []
          primes = []
          for i in range(2, n+1):
            if i not in multiples:
              print (i)
              primes.append(i)
              for j in range(i*i, n+1, i):
                multiples.append(j)
      • View Code File

    • To run the code, simply call the function
      eratosthenes(100)

Lab 2: Set types

Lab 2: Set types
  1. Creating a Set
    • You can create a set via one of the following mechanisms:
      • {item, item, item, … } – Creates a set from the items in the braces. The braces must not be empty.
      • set() – Creates an empty set.
      • set(iterable) – Creates a set that contains the items from the iterable object.
      • Via a comprehension, i.e. by performing an operation on items in a collection.
    • Example:
      set1 = {"dog", "ant", "bat", "cat", "dog"}
      set2 = set()
      set3 = set(("dog", "ant", "bat", "cat", "dog"))
      set4 = set("abracadabra")
      set5 = {c.upper() for c in "abracadabra"}
      print("set1 has %d items: %s" % (len(set1), set1))
      print("set2 has %d items: %s" % (len(set2), set2))
      print("set3 has %d items: %s" % (len(set3), set3))
      print("set4 has %d items: %s" % (len(set4), set4))
      print("set5 has %d items: %s" % (len(set5), set5))
    • View Code File

    • The example illustrates these features. Note the following points:
      • For set3, where we call the set constructor, we must enclose the items in another pair of parentheses (i.e. a range). Without these parentheses, Python would try to pass the items as separate parameters into the constructor.
      • For set4, we pass a string into the set constructor. Python treats the string as a collection of characters, so the set will be populated with the unique characters from this string.
    • Here’s the output from the example:
      set1 has 4 items: {'bat', 'ant', 'cat', 'dog'}
      set2 has 0 items: set()
      set3 has 4 items: {'bat', 'ant', 'cat', 'dog'}
      set4 has 5 items: {'r', 'a', 'c', 'b', 'd'}
      set5 has 5 items: {'D', 'B', 'R', 'A', 'C'}
  2. Creating a Frozen Set
    • A frozenset is an immutable set, so frozensets are to sets what tuples are to lists.
    • Creating a frozenset is similar to creating a set
      • Use the frozenset constructor
    • Example:
      set1 = frozenset({"dog", "ant", "bat", "cat", "dog"})
      set2 = frozenset()
      set3 = frozenset(("dog", "ant", "bat", "cat", "dog"))
      set4 = frozenset("abracadabra")
      set5 = frozenset({c.upper() for c in "abracadabra"})
      print("set1 has %d items: %s" % (len(set1), set1))
      print("set2 has %d items: %s" % (len(set2), set2))
      print("set3 has %d items: %s" % (len(set3), set3))
      print("set4 has %d items: %s" % (len(set4), set4))
      print("set5 has %d items: %s" % (len(set5), set5))
    • View Code File

  3. Common Set Operations
    • You can perform these operations on any set:
      s1 = {"GB", "US", "SG"}
      s2 = {"GB", "US", "AU"}
      s3 = {"F", "BE", "CA"}
      print("%s" % ("GB" in s1))     # True
      print("%s" % ("GB" not in s1))   # False
      print("%s" % (s1.isdisjoint(s2))) # False
      print("%s" % (s1.isdisjoint(s3))) # True
      print("%s" % (s1.issubset(s2)))  # True
      print("%s" % (s1 <= s2))      # True print("%s" % (s1 < s2))      # True print("%s" % (s1.issuperset(s2))) # False print("%s" % (s1 >= s2))      # False
      print("%s" % (s1 > s2))      # False
      print("%s" % (s1.union(s2, s3)))  # {'GB', 'US', 'BE', 'F', 'CA', 'AU', 'SG'}
      print("%s" % (s1 | s2 | s3))    # {'GB', 'US', 'BE', 'F', 'CA', 'AU', 'SG'}
      print("%s" % (s1.difference(s2, s3))) # {'SG'}
      print("%s" % (s1 - s2 - s3))     # {'SG'}
      print("%s" % (s1.symmetric_difference(s2))) # {'AU', 'SG'}
      print("%s" % (s1 ^ s2))           # {'AU', 'SG'}
    • View Code File

    • This shows the common operations you can perform on any type of set. The example also shows the expected output, so you can see how the operations work.
      • in and not in indicate if the set contains the specified item.
      • s.isdisjoint(other) returns true if the set s has no elements in common with the other.
      • s.issubset(other) returns true if every item in the set s is also in the other. The <= operator has the same effect. The < has a similar effect, except that it requires that set s is not exactly the same as the other.
      • s.issuperset(other) returns true if every item in the other is also in the set s. The >= operator has the same effect. The > has a similar effect, except that it requires that set s is not exactly the same as the other.
      • s.union(other1,other2,…) returns a new set with the items from s and all the others. The | operator has the same effect.
      • s.difference(other1,other2,…) returns a new set with the items from s that are not in any of the others. The – operator has the same effect.
      • s.symmetric_difference(other) returns a new set with the items that are either in set s or the other, but not both. The ^ operator has the same effect.
  4. Set Modification Operations
    • You can perform these operations on a mutable set:
      s1 = {"GB", "US", "SG"}
      s2 = {"GB", "US", "AU"}
      s3 = {"GB", "US", "F", "CA"}
      s4 = {"GB", "US", "I", "D"}
      s5 = {"GB", "US", "P", "N"}
      s1.add("HK")
      s1.remove("US")
      s1.discard("D")
      print("%s" % s1)    # {'SG', 'HK', 'GB'}
      print("%s" % s1.pop()) # SG
      print("%s" % s1)    # {'HK', 'GB'}
      s1.update(s2,s3)
      s1 |= s4 | s5
      print("%s" % s1)    # {'D', 'AU', 'US', 'I', 'F', 'P', 'N', 'GB', 'CA', 'HK'}
      s1.intersection_update(s2,s3)
      s1 &= s4 & s5
      print("%s" % s1)    # {'GB', 'US'}
      s1.difference_update({"AA", "BB"},{"CC", "GB"})
      s1 -= {"DD", "EE"} | {"FF", "GG"}
      print("%s" % s1)    # {'US'}
      s1.symmetric_difference_update(s2)
      s1 ^= s2
      print("%s" % s1)    # {'US'}
    • View Code File

    • This shows the modification operations you can perform on a mutable set (but not on an immutable frozenset). The example also shows the expected output, so you can see how the operations work.
      • s.add(item) adds an item to the set, s.
      • s.remove(item) removes an item from the set, s (error if not found).
      • s.discard(item) is similar, except it doesn’t raise an error if not found.
      • s.pop() retrieves and removes a random item from the set, s.
      • s.update(other1,other2,…) updates the set s, adding items from all the others. You can also use the |= and | operators.
      • s.intersection_update(other1,other2,…) updates the set s, keeping only items found in it and all others. You can also use the &= and & operators.
      • s.difference_update(other1,other2,…) updates the set s, removing items found in the others. You can also use the -= and | operators.
      • s.symmetric_difference_update(other) updates the set s, keeping only elements found in either set, but not in both. You can also use the ^= operator.

Lab 3: Mapping types

Lab 3: Mapping types
  1. Creating a Dictionary
    • You can create a dict via one of the following mechanisms:
      • {key:value, key:value, … } – Creates a dict from the key/value pairs in the braces. The braces can be empty, in which case it creates an empty dictionary.
      • dict() – Creates an empty dict.
      • dict(anotherDict) – Creates a dict that contains the items from the supplied dictionary.
      • dict(keyword=value, keyword:value, … ) – Creates a dict from the list of keyword=value pairs. The keywords must adhere to the normal rules for identifiers in Python.
      • dict(zip(keysIterable, valuesIterable)) – zip() is a standard Python function. It returns a collection of tuples, where each tuple represents a key/value pair (i.e. each tuple contains a key from the keysIterable, plus the corresponding value from the valuesIterable).
    • Example:
      dict1 = {"us":"+1", "nl":"+31", "no":"+47"}
      dict2 = dict()
      dict3 = dict({"us":"+1", "nl":"+31", "no":"+47"})
      dict4 = dict(us="+1", nl="+31", no="+47")
      dict5 = dict(zip(["us", "nl", "no"], ["+1", "+31", "+47"]))
      print("dict1 has %d items: %s" % (len(dict1), dict1))
      print("dict2 has %d items: %s" % (len(dict2), dict2))
      print("dict3 has %d items: %s" % (len(dict3), dict3))
      print("dict4 has %d items: %s" % (len(dict4), dict4))
      print("dict5 has %d items: %s" % (len(dict5), dict5))
    • View Code File

    • Here is the output from the example:
      dict1 has 3 items: {'nl': '+31', 'us': '+1', 'no': '+47'}
      dict2 has 0 items: {}
      dict3 has 3 items: {'nl': '+31', 'us': '+1', 'no': '+47'}
      dict4 has 3 items: {'nl': '+31', 'us': '+1', 'no': '+47'}
      dict5 has 3 items: {'nl': '+31', 'us': '+1', 'no': '+47'}
  2. Iterating over a Dictionary
    • There are several ways to iterate over a dict:
      • Call the items() method to obtain the key/value pairs for the dict.
      • Call the keys() method to obtain the keys for the dict.
      • Call the values() method to obtain the values for the dict.
    • Example:
      dialcodes = {"us": "+1", "nl": "+31", "no": "+47"}
      print("Items:")
      for k,v in dialcodes.items():
        print(k, v)
      print("\nKeys:")
      for k in dialcodes.keys():
        print(k)
      print("\nValues:")
      for v in dialcodes.values():
        print(v)
    • View Code File

    • Here’s the output from the example:
      Items:
      nl +31
      no +47
      us +1
      Keys:
      nl
      no
      us
      Values:
      +31
      +47
      +1
  3. Accessing Items in a Dictionary
    • There are various operations for accessing items in a dict
      dialcodes = {"us": "+1", "nl": "+31", "no": "+47"}
      print("%s" % "us" in dialcodes)     # True
      print("%s" % "us" not in dialcodes)   # False
      dialcodes["uk"] = "+44"
      print(dialcodes["uk"])          # +44
      print(dialcodes.get("fr"))        # None
      print(dialcodes.get("fr", "xxx"))    # xxx
      del dialcodes["no"]
      print(dialcodes.pop("uk"))        # +44
      print(dialcodes.pop("uk", "xxx"))    # xxx
      print(dialcodes.setdefault("it", "???")) # ???
      dialcodes.update({"ca":"+1", "it":"+39"})
      print(dialcodes) # {'ca': '+1', 'us': '+1', 'nl': '+31', 'it': '+39'}
    • View Code File

    • This shows the operations you can perform on a dictionary, to access its items.
      • in and not in indicate if the dictionary contains the specified key.
      • d[key]=value either inserts a new key/value item, or overwrites the value for an existing item.
      • d[key] returns the value for the specified key (error if not found).
      • d.get(key,default) returns the value for the specified key. If the key isn’t found, it returns the specified default value (if you didn’t specify a default value, it just returns None).
      • del d[key] removes the item with the specified key (error if not found).
      • d.pop(key,default) removes the item with the specified key, and returns its value. If the key isn’t found, it returns the specified default value (if you didn’t specify a default value, it raises an error).
      • d.setdefault(key,default) returns the value for the specified key, if it exists. If the key doesn’t exist, it inserts a new item with the specified key and default value (if you didn’t specify a default value, it sets the new item’s value to None).
      • d.update(other) updates the dictionary with the key/value pairs from other, overwriting existing keys. Return None.
      • Note that dict also supports len(), copy(), and clear().
Lab
  1. Employee system
    • We are going to build an employee system that allows you to create a simple employee collection in the form of a dictionary
    • To start create a new python file e.g. Employee.py and edit this in IDLE
    • For hints if you cannot think of how to do it follow below:
      • First thing we are going to need to do is first create 2 variables our dictionary and a variable to hold the current ID for each employee that increments each time one is added
        Employees = {}
        ID = 0
      • View Code File

      • Our next task is to add our functions to add, remove and update employees:
        • Add:
          def AddEmployee(name, payLevel, sector,Id):
          Employees[Id] = [name, payLevel, sector]
          global ID
          ID += 1
        • View Code File

        • Remove:
          def RemoveEmployee(Id):
          del Employees[Id]
        • View Code File

        • Update:
          def UpdateEmployee(Id):
          personName = input('Enter the new name: ')
          personPay = input('Enter the new pay level: ')
          personSector = input('Enter the new sector: ')
          Employees[Id] = [personName, personPay, personSector]
        • View Code File

      • When we add an employee we store the current ID number by accessing this from the client code, this is its key and its value is made up of a list containing values for the employees name, pay level and the department they work in
      • Here is the client code to test the application:
        AddEmployee("Steven", "5", "Soft Dev",str(ID))
        print ("Added Steven")
        print (Employees)
        AddEmployee("James", "4", "Assurance",str(ID))
        AddEmployee("Kerry", "6", "UX",str(ID))
        print ("Added James and Kerry - Here is what ID now equals")
        print (ID)
        RemoveEmployee("2")
        print ("Removed Employee with ID = 2")
        print (Employees)
        UpdateEmployee("1")
        print ("Employees after update")
        print (Employees)
        print ("All Employees Listed Below:")
      • View Code File

      • As a bonus you can also iterate over all the items in the dictionary to print every employee:
        def ShowAllEmployees():
          for Identifier, Details in Employees.items():
            print ('{0} has name {1}, paylevel {2} and works in {3}'.format(Identifier,Details[0], Details[1], Details[2]))
      • Client Code
        ShowAllEmployees()

 

Well done. You have completed the tutorial in the Python course. The next tutorial is

6. Object-Oriented Programming in Python


Back to beginning
Copyright © 2016 TalkIT®






If you liked this post, please comment with your suggestions to help others.
If you would like to see more content like this in the future, please fill-in our quick survey.
Scroll to Top