Extending Built-in Types¶
Extending Types by Embedding¶
- The set functions can be brought back to life as a Python class. The following example implements a new set object type by moving some of the set functions to methods and by adding some basic operator overloading.
class Set:
def __init__(self, value = []): # Constructor
self.data = [] # Manages a list
self.concat(value)
def intersect(self, other): # other is any sequence
res = [] # self is the subject
for x in self.data:
if x in other: # Pick common items
res.append(x)
return Set(res) # Return a new Set
def union(self, other): # other is any sequence
res = self.data[:] # Copy of my list
for x in other: # Add items in other
if not x in res:
res.append(x)
return Set(res)
def concat(self, value): # value: list, Set...
for x in value: # Removes duplicates
if not x in self.data:
self.data.append(x)
def __len__(self): return len(self.data) # len(self), if self
def __getitem__(self, key): return self.data[key] # self[i], self[i:j]
def __and__(self, other): return self.intersect(other) # self & other
def __or__(self, other): return self.union(other) # self | other
def __repr__(self): return 'Set:' + repr(self.data) # print(self),...
def __iter__(self): return iter(self.data) # for x in self,...
To use this class, we make instances, call methods, and run defined operators as usual: .. code-block:: python
- from setwrapper import Set
- x = Set([1, 3, 5, 7]) print(x.union(Set([1, 4, 7]))) # prints Set:[1, 3, 5, 7, 4] print(x | Set([1, 4, 6])) # prints Set:[1, 3, 5, 7, 4, 6]
Overloading operations such as indexing and iteration also enable instances of the Set class to often masquerade as real lists.
Extending Types by Subclassing¶
- Beginning with Python 2.2, all the built-in types in the language can now be subclassed directly.
- Type-conversion functions such as list, str, dict, and tuple have become built-in type names—although transparent to your script, a type-conversion call (e.g.,list(‘spam’)) is now really an invocation of a type’s object constructor.
- This change allows one to customize or extend the behavior of built-in types with userdefined class statements: simply subclass the new type names to customize them.
- Instances of your type subclasses can generally be used anywhere that the original builtin type can appear.
Consider the Example:
# Subclass built-in list type/class
# Map 1..N to 0..N-1; call back to
built-in version.
class MyList(list):
def __getitem__(self, offset):
print('(indexing %s at %s)' %(self, offset))
return list.__getitem__(self, offset - 1)
if __name__ == '__main__':
print(list('abc'))
x = MyList('abc') # __init__ inherited from list
print(x) # __repr__ inherited from list
print(x[1]) # MyList.__getitem__
print(x[3]) # Customizes list superclass method
x.append('spam'); print(x) # Attributes from list superclass
x.reverse(); print(x)