Online Book Reader

Home Category

Learning Python - Mark Lutz [596]

By Root 1386 0

print(x[2])

print(x[1:])

print(x + ['eggs'])

print(x * 3)

x.append('a')

x.sort()

for c in x: print(c, end=' ')

% python mylist.py

['s', 'p', 'a', 'm']

a

['p', 'a', 'm']

['s', 'p', 'a', 'm', 'eggs']

['s', 'p', 'a', 'm', 's', 'p', 'a', 'm', 's', 'p', 'a', 'm']

a a m p s

Note that it’s important to copy the start value by appending instead of slicing here, because otherwise the result may not be a true list and so will not respond to expected list methods, such as append (e.g., slicing a string returns another string, not a list). You would be able to copy a MyList start value by slicing because its class overloads the slicing operation and provides the expected list interface; however, you need to avoid slice-based copying for objects such as strings. Also, note that sets are a built-in type in Python today, so this is largely just a coding exercise (see Chapter 5 for more on sets).

Subclassing. My solution (mysub.py) appears below. Your solution should be similar:from mylist import MyList

class MyListSub(MyList):

calls = 0 # Shared by instances

def __init__(self, start):

self.adds = 0 # Varies in each instance

MyList.__init__(self, start)

def __add__(self, other):

MyListSub.calls += 1 # Class-wide counter

self.adds += 1 # Per-instance counts

return MyList.__add__(self, other)

def stats(self):

return self.calls, self.adds # All adds, my adds

if __name__ == '__main__':

x = MyListSub('spam')

y = MyListSub('foo')

print(x[2])

print(x[1:])

print(x + ['eggs'])

print(x + ['toast'])

print(y + ['bar'])

print(x.stats())

% python mysub.py

a

['p', 'a', 'm']

['s', 'p', 'a', 'm', 'eggs']

['s', 'p', 'a', 'm', 'toast']

['f', 'o', 'o', 'bar']

(3, 2)

Attribute methods. I worked through this exercise as follows. Notice that in Python 2.6, operators try to fetch attributes through __getattr__, too; you need to return a value to make them work. Caveat: as noted in Chapter 30, __getattr__ is not called for built-in operations in Python 3.0, so the following expression won’t work as shown; in 3.0, a class like this must redefine __X__ operator overloading methods explicitly. More on this in Chapters 30, 37, and 38.>>> class Meta:

... def __getattr__(self, name):

... print('get', name)

... def __setattr__(self, name, value):

... print('set', name, value)

...

>>> x = Meta()

>>> x.append

get append

>>> x.spam = "pork"

set spam pork

>>>

>>> x + 2

get __coerce__

Traceback (innermost last):

File "", line 1, in ?

TypeError: call of non-function

>>>

>>> x[1]

get __getitem__

Traceback (innermost last):

File "", line 1, in ?

TypeError: call of non-function

>>> x[1:5]

get __len__

Traceback (innermost last):

File "", line 1, in ?

TypeError: call of non-function

Set objects. Here’s the sort of interaction you should get. Comments explain which methods are called:% python

>>> from setwrapper import Set

>>> x = Set([1, 2, 3, 4]) # Runs __init__

>>> y = Set([3, 4, 5])

>>> x & y # __and__, intersect, then __repr__

Set:[3, 4]

>>> x | y # __or__, union, then __repr__

Set:[1, 2, 3, 4, 5]

>>> z = Set("hello") # __init__ removes duplicates

>>> z[0], z[-1] # __getitem__

('h', 'o')

>>> for c in z: print(c, end=' ') # __getitem__

...

h e l o

>>> len(z), z # __len__, __repr__

(4, Set:['h', 'e', 'l', 'o'])

>>> z & "mello", z | "mello"

(Set:['e', 'l', 'o'], Set:['h', 'e', 'l', 'o', 'm'])

My solution to the multiple-operand extension subclass looks like the following class (file multiset.py). It only needs to replace two methods in the original set. The class’s documentation string explains how it works:from setwrapper import Set

class MultiSet(Set):

"""

Inherits all Set names, but extends intersect

and union to support multiple operands; note

that "self" is still the first argument (stored

in the *args argument now); also note that the

inherited & and | operators call the new methods

here with 2 arguments, but processing more than

2 requires a method call, not an expression:

"""

def intersect(self, *others):

Return Main Page Previous Page Next Page

®Online Book Reader