4.6 KiB
[ Index | Exercise 5.6 | Exercise 6.2 ]
Exercise 6.1
Objectives:
- Learn more about function argument passing conventions
Files Created: structure.py
,
stock.py
IMPORTANT NOTE
This exercise is going to start a long road of rewriting the
stock.py
file in a more sane way. Before doing anything,
copy your work in stock.py
to a new file
orig_stock.py
.
We’re going to recreate the Stock
class from scratch
using some new techniques. Make sure you have your unit tests from Exercise 5.4 handy. You’ll want those.
If you define a function, you probably already know that it can be called using a mix of positional or keyword arguments. For example:
>>> def foo(x, y, z):
return x + y + z
>>> foo(1, 2, 3)
6
>>> foo(1, z=3, y=2)
6
>>>
You may also know that you can pass sequences and dictionaries as function arguments using the * and ** syntax. For example:
>>> args = (1, 2, 3)
>>> foo(*args)
6
>>> kwargs = {'y':2, 'z':3 }
>>> foo(1,**kwargs)
6
>>>
In addition to that, you can write functions that accept any number of positional or keyword arguments using the * and ** syntax. For example:
>>> def foo(*args):
print(args)
>>> foo(1,2)
1, 2)
(>>> foo(1,2,3,4,5)
1, 2, 3, 4, 5)
(>>> foo()
()>>>
>>> def bar(**kwargs):
print(kwargs)
>>> bar(x=1,y=2)
'y': 2, 'x': 1}
{>>> bar(x=1,y=2,z=3)
'y': 2, 'x': 1, 'z': 3}
{>>> bar()
{}>>>
Variable argument functions are sometimes useful as a technique for reducing or simplifying the amount of code you need to type. In this exercise, we’ll explore that idea for simple data structures.
(a) Simplified Data Structures
In earlier exercises, you defined a class representing a stock like this:
class Stock:
def __init__(self,name,shares,price):
self.name = name
self.shares = shares
self.price = price
Focus on the __init__()
method—isn’t that a lot of code
to type each time you want to populate a structure? What if you had to
define dozens of such structures in your program?
In a file structure.py
, define a base class
Structure
that allows the user to define simple data
structures as follows:
class Stock(Structure):
= ('name','shares','price')
_fields
class Date(Structure):
= ('year', 'month', 'day') _fields
The Structure
class should define an
__init__()
method that takes any number of arguments and
which looks for the presence of a _fields
class variable.
Have the method populate the instance from the attribute names in
_fields
and values passed to __init__()
.
Here is some sample code to test your implementation:
>>> s = Stock('GOOG',100,490.1)
>>> s.name
'GOOG'
>>> s.shares
100
>>> s.price
490.1
>>> s = Stock('AA',50)
Traceback (most recent call last):
...TypeError: Expected 3 arguments
>>>
(b) Making a Useful Representation
Modify the Structure
class so that it produces a nice
representation when repr()
is used. For example:
>>> s = Stock('GOOG', 100, 490.1)
>>> s
'GOOG',100,490.1)
Stock(>>>
(c) Restricting Attribute Names
Give the Structure
class a __setattr__()
method that restricts the allowed set of attributes to those listed in
the _fields
variable. However, it should still allow any
“private” attribute (e.g., name starting with _
to be
set).
For example:
>>> s = Stock('GOOG',100,490.1)
>>> s.shares = 50
>>> s.share = 50
Traceback (most recent call last):"<stdin>", line 1, in <module>
File "structure.py", line 13, in __setattr__
File raise AttributeError('No attribute %s' % name)
AttributeError: No attribute share
>>> s._shares = 100 # Private attribute. OK
>>>
(d) Starting Over
Create a new file stock.py
(or delete all of your
previous code). Start over by defining Stock
as
follows:
# stock.py
from structure import Structure
class Stock(Structure):
= ('name', 'shares', 'price')
_fields
@property
def cost(self):
return self.shares * self.price
def sell(self, nshares):
self.shares -= nshares
Once you’ve done this, run your teststock.py
unit tests.
You should get a lot of failures, but at least a handful of the tests
should pass.
[ Solution | Index | Exercise 5.6 | Exercise 6.2 ]
>>>
Advanced Python Mastery
...
A course by dabeaz
...
Copyright 2007-2023
.
This work is licensed under a Creative Commons
Attribution-ShareAlike 4.0 International License