Python & Perl: Lecture 17


Published on

Published in: Technology, Education
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Python & Perl: Lecture 17

  1. 1. Python & Perl Lecture 17 Vladimir Kulyukin Department of Computer Science Utah State
  2. 2. Outline ● Inheritance from Built-In Classes ● Properties ● Iterators ●
  3. 3. Inheritance from Built-In
  4. 4. Built-in Inheritance ● If a built-in class implements most of the functionality that you need, there is no need to reinvent the wheel ● You can inherit from the built-in classes: list, dict, and str ● Caveat: If you find that you need to re- implement most of the methods you may as well implement your own
  5. 5. Example class MyList(list): def __init__(self, *args): super(MyList, self).__init__(*args) def __getitem__(self, key): return super(MyList, self).__getitem__(key) def __len__(self): return super(MyList, self).__len__()
  6. 6.
  7. 7. Properties & Accessor Methods ● Accessors are methods with names that start with get and set ● Accessors are used to manipulate object properties ● Some attributes are derived in that they are combined from the values of real
  8. 8. Example Define a class that constructs right triangle objects. The class must allow its clients to access the base and height of a right triangle and compute its
  9. 9. Example: Standard Solution class RiTri01: def __init__(self, base=0, height=0): self.base, self.height = base, height ## Two Getters def getBase(self): return self.base def getHeight(self): return self.height ## Two Setters def setBase(self, base): self.base = base def setHeight(self, height): self.height = height ## Two Deleters def delBase(self): del self.base def delHeight(self): del self.height ## Area method def area(self): return 0.5 * self.base *
  10. 10. Example >>> tri01 = RiTri01(base=10, height=15) >>> tri01.getBase() 10 >>> tri01.getHeight() 15 >>> tri01.area() 75.0 >>> tri01.setBase(15) >>> tri01.setHeight(20) >>> tri01.area()
  11. 11. Problems with Standard Solution ● The standard solution is OK but has two potential problems: – Class clients must know the interface – If class developers decide to change the internal representation of the class, they must change all of the affected getters, setters, and
  12. 12. Problems with Standard Solution Suppose that the developers of the right triangle class decide to change the class representation to have only one property, called size, that stores a list of two numbers: base and height. All methods must
  13. 13. Problems with Standard Solution class RiTri02: def __init__(self, base=0, height=0): self.size = [base, height] def getBase(self): return self.size[0] def getHeight(self): return self.size[1] def setBase(self, b): self.size[0] = b def setHeight(self, h): self.size[1] = h def delBase(self): del self.size[0] def delHeight(self): del self.size[1] def area(self): return 0.5 * self.size[0] * self.size[1]
  14. 14. Addressing Problems with property Function ● Pythons property function (works only on new style classes) allows programmers to address problems associated with the standard solution ● Syntax: prop = property([fget [, fset [fdel [, doc]]]]) ● fget is the getter for the property prop ● fset is the setter for the property prop ● fdel is the deleter for the property prop ● doc is the documentation string of
  15. 15. Example class A: def __init__(self, p=None): self._p = p def getP(self): return self._p def setP(self, v): self._p = v def delP(self): del self._p ## p is a managed property; note one underscore in __init__ p = property(getP, setP, delP, "As p property.") >>> a = A() >>> a.p = 10 >>> a.p 10 >>> del
  16. 16. Example ● This implementation of A allows the client to interact with A objects through the standard Python data attribute interface: ● a.p; a.p = 10; del a.p ● We can further improve As implementation by making the getters, setters, and deleters (semi)private ● Why is this better? The client will have to know only the names of
  17. 17. Example class A2: def __init__(self, p=None): self._p = p def __getP(self): return self._p def __setP(self, v): self._p = v def __delP(self): del self._p p = property(__getP, __setP, __delP, "A2s p property.") >>> a2 = A2() >>> a2.p = 10 >>> a2.p 10 >>> del
  18. 18. Example Use properties to change the implementation of the right triangle class so that the clients must know only the names of the properties: base, height, and
  19. 19. Example class RiTri01_Prop: def __init__(self, base=0, height=0): self._base, self._height = base, height def __getB(self): return self._base def __getH(self): return self._height def __setB(self, b): self._base = b def __setH(self, h): self._height = h def __delB(self): del self._base def __delH(self): del self._height def __area(self): return 0.5 * self._base * self._height ## Setting up three properties; note that area is a derived property base = property(__getB, __setB, __delB, "base of right triangle") height = property(__getH, __setH, __delH, "height of right triangle") area = property(__area, None, None, "area of triangle")
  20. 20. Example ● Strings that start with “@” in Python source files are called decorators (same term is used in other programming languages) ● You can use @property decorator to save yourself some typing when defining
  21. 21. @property Example 01 class B: def __init__(self, p=None): self._myprop = p ## myprop is a read-only property @property def myprop(self): return self._myprop >>> b = B(p=1000) >>> b.myprop 1000 >>> b,myprop = 2000 Attribute Error: Cannot set
  22. 22. @property Example 01 ## myprop is a fully defined property with its own getter, setter, and deleter. class B2: def __init__(self, p=None): self._myprop = p @property def myprop(self): "B2s property myprop." return self._myprop @myprop.setter def myprop(self, pv): self._myprop = pv @myprop.deleter def myprop(self): del
  23. 23.
  24. 24. Iterator Protocol ● Iterators are objects that allow us to iterate over other objects one item at a time (e.g., iterate over values in a range, over lines in a file, over nodes in a tree, over records in a database) ● In principle, any Python object can be turned into an iterator so long as it implements the Iterator Protocol ● The Iterator Protocol is another standard Python protocol like the Sequence Protocol we have studied
  25. 25. Iterator Protocol ● In Python 2.7, the Iterator Protocol consists of two methods __iter__ and next() ● __iter__ returns the iterator object (typically self) that implements the next() method ● The next() method on first call returns the first element, on the second call – the second element, etc ● When there are no more elements a call to next() should raise a StopIteration
  26. 26. Example 01 Define an iterator over prime
  27. 27. Example 01 class Primes: def __nextPrime(self): def __init__(self): n = self.__currentPrime + 1 self.__currentPrime = 2 while True: if self.__isPrime(n): def next(self): return n currprime = self.__currentPrime else: self.__currentPrime = self.__nextPrime() n += 1 return currprime def __isPrime(self, n): def __iter__(self): for d in xrange(2, int(math.floor(math.sqrt(n)))+1): return self if n % d == 0: return False return
  28. 28. Example 02 Define an iterator that iterates over prime numbers in the interval [lower, upper]
  29. 29. Example 02 class PrimeInterval: def __init__(self, lower=2, upper=2): if lower < 2 or upper < 2: raise ValueError elif lower > upper: raise ValueError self.__lower, self.__upper = lower, upper if self.__isPrime(lower): self.__currentPrime = lower else: self.__currentPrime = self.__nextPrimeGreaterThan(lower) def next(self): if self.__currentPrime > self.__upper: raise StopIteration currprime = self.__currentPrime self.__currentPrime = self.__nextPrimeGreaterThan(currprime) return
  30. 30. Example 02 >>> pi = PrimeInterval(2, 3) >>> 2 >>> 3 >>> StopIteration Exception >>> [x for x in PrimeInterval(10, 20)] [11, 13, 17, 19] >>> pi = PrimeInterval(10, 50) >>> list(pi.__iter__()) [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
  31. 31. Built-in iter() Function ● If you know that a Python object is iterable, you can use the built-in function iter() to obtain an iterator for that object >>> lstit = iter([1, 2, 3, 4]) >>> 1 >>> 2 >>> strit = iter(abcd efg) >>>
  32. 32.
  33. 33. Generators ● A generator is a lazy function that remembers its state from call to call ● A lazy function returns (or, in Python terminology, yields) its values one at a time ● Generators are typically used for handling really large ranges or solving combinatorial optimization problems ● In a combinatorial optimization problem, we have to enumerate all objects and find some (or all) that satisfy all specific
  34. 34. Combinatorial Optimization Example ● Find all subsets of a given set that contain at least one prime number n ● A set of n elements has 2 subsets ● We can list all of the subsets and then iterate through the list checking for the subsets with at least one prime ● Problem: The function 2n is exponential and grows pretty fast – the memory requirements to maintain the list of all subsets are prohibitively expensive ● It is better to generate subsets one at a time without having to store all of
  35. 35. Generator Comprehension ● The most straightforward method of obtaining a generator is through generator comprehensions (aka generator expressions) ● Generator comprehension is similar to list comprehension except it uses parentheses around generator expressions and it does not enumerate all elements in the range >>> g1 = (x**3 for x in xrange(1, 100001)) >>> 1 >>> 8 >>> g2 = (i**2+10 for i in xrange(1, 100001)) >>>
  36. 36. Feedback Bugs, comments to vladimir dot kulyukin at usu dot
  37. 37. Reading & References ● ● Ch 09 M. L. Hetland. Beginning Python From Novice to Pro- nd fessional, 2 Ed., APRESS ● Source code for this lecture is at