Here we are going to see how we can make an object to have the list capability. before we start, let's first review what is supported by a list.
- get item from the obj
- set an item at specified index
we will review one example that simulate some type safe list, where you can only insert types of the homogeous types, and you cannot insert object of incorrect types. Here is the code.
<!-- lang: python -->
class TypedList:
'''
classdocs
'''
def __init__(self, example_element, initial_list = []):
'''
Constructor
'''
self.type = type(example_element)
if not isinstance(initial_list, list):
raise TypeError("second argument of TypeList must be a list")
for element in initial_list:
self.__check(element)
self.elements = initial_list[:] # copy the element , rather than copy the list reference
def __check(self, element):
if type(element) != self.type:
raise TypeError("Attempt to add an element of incorrect type to a typed list.")
def __setitem__(self, i, element):
self.__check(element)
self.elements[i] = element
def __getitem__(self, i):
return self.elements[i]
if __name__ == "__main__":
x = TypedList("", 5 * [""])
x[2] = "Hello"
x[3] = "There"
print(x[2] + " " + x[3])
a,b,c,d,e = x # this works in a list context (it actually will retrieve the element one by one and assign to the variable to the left
print(a, b, c, d)
in python 3, we are alllowed to subclass built-in classes, below shows a code that uses the list as the base classes.
<!-- lang: python -->
class TypedListList(list):
'''stlist
classdocs
'''
def __init__(self, example_element, initial_list = []):
'''
Constructor
'''
self.type = type(example_element)
if not isinstance(initial_list, list):
raise TypeError("second argument of TypeList 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("Attempt to add an element of incorrect type to a typed list.")
def __setitem__(self, i, element):
self.__check(element)
super().__setitem__(i, element)
# no need to provide the __getitem__ method because it the super class list already provide one
# def __getitem__(self, i):
# return self.elements[i]
if __name__ == "__main__":
x = TypedListList("", 5 * [""])
x[2] = "Hello"
x[3] = "There"
print(x[2] + " " + x[3])
a,b,c,d,e = x # this works in a list context (it actually will retrieve the element one by one and assign to the variable to the left
print(a, b, c, d)
And there is yet another way, which is effective in pre pyton 3.0 era, where you can subclass a UserList , here is the code.
<!-- lang: python -->
from collections import UserList
class TypedUserList(UserList):
'''
classdocs
'''
def __init__(self, example_element, initial_list = []):
'''
Constructor
'''
super().__init__(initial_list)
self.type = type(example_element)
if not isinstance(initial_list, list):
raise TypeError("second argument of TypeList must be a list")
for element in initial_list:
self.__check(element)
def __check(self, element):
if type(element) != self.type:
raise TypeError("Attempt to add an element of incorrect type to a typed list.")
def __setitem__(self, i, element):
self.__check(element)
self.data[i] = element
pass
def __getitem__(self, i):
return self.data[i]
if __name__ == "__main__":
x = TypedUserList("", 5 * [""])
x[2] = "Hello"
x[3] = "There"
print(x[2] + " " + x[3])
a,b,c,d,e = x # this works in a list context (it actually will retrieve the element one by one and assign to the variable to the left
print(a, b, c, d)