>>> mysin(30,"deg") # 30 goes to ang and "deg" goes to unit based on order 0.49999999999999994 >>> mysin(1.5,"rad") 0.9974949866040544 >>> mysin(1.5,"deg") 0.026176948307873153 >>> mysin(1.5,"deeg") Exception: unit must be deg or rad, received: deeg >>> mysin("deg",45) # fails b/c 45 goes to unit and "deg" goes to ang! Exception: unit must be deg or rad, received: 45So, when calling using positional arguments, you need to get the order of the arguments right! However, we can call the function in a different way if we want. We can call using keyword arguments. What this means is that we give the arguments as name=value pairs when we call the function, and when we call functions this way, the order does not matter!
>>> mysin(ang=30,unit="deg") 0.49999999999999994 >>> mysin(unit="deg",ang=30) 0.49999999999999994 >>> mysin(ang=0.2,unit="rad") 0.19866933079506122 >>> mysin(unit="rad",ang=0.2) 0.19866933079506122Note: this is a property of how the function is called, not how it is defined.
mysin from the previous section
will always be called with an angle. But perhaps we anticipate
that the unit would usually be radians. We could make it easier
on the user by making "rad" the default value of
parameter unit, which means that if the caller
neglects to provide a second argument to mysin, the
second argument will default to "rad". We do this by putting
unit="rad" in the prototype/signature of the
function, as shown below.
>>> mysin(0.2) 0.19866933079506122 >>> mysin(0.2,"rad") 0.19866933079506122 >>> mysin(0.2,"deg") 0.003490651415223732 >>> mysin(0.2,unit="deg") 0.003490651415223732 >>> mysin(unit="deg",ang=0.2) 0.003490651415223732You'll notice another new thing in this function definition: a string delimited by triple-quotes that immediately follows the prototype/signature. This is called a docstring. It documents the use of the function, and users cal look it up by calling:
help(funcname). In this case, typing
help(mysin) brings up:
mysin(ang, unit='rad')
mysin(ang,unit) returns sin(ang), where ang is given in unit.
Supported unit values are "rad" and "deg". Default is "rad".
If you want to write functions that are easy for others to use,
providing docstrings is a good idea!
For example, the function below prints out the elements of a list of points (which are represented as 2-tuples). It provides three additional parameters with default arguments that allow the caller to control how the output is presented.
>>> L = [ (3.2,-2), (5,0.5), (0,2.25) ] >>> printPoints(L) (3.2,-2) (5,0.5) (0,2.25) >>> printPoints(L,dir="horizontal") (3.2,-2) (5,0.5) (0,2.25) >>> printPoints(L,dir="horizontal",parens=False,sep=":") 3.2:-2 5:0.5 0:2.25 >>> printPoints(L,parens=False,sep="\t") 3.2 -2 5 0.5 0 2.25
ASCIIRectangle that takes a width
(number of columns) and a height (number of rows), and prints
out a box with that number of rows and columns. There should
be optional argument offset that gets a numerical
value and indents the box by that many spaces (default 0), optional
argument bchar that gets a character and uses that
to write the box sides (default is #) and optional
argument filled (default is False) that, when True,
specifies that the rectangle should be filled in with
the bchar character, not merely outlined.
>>> ASCIIRectangle(7,5) ####### # # # # # # ####### >>> ASCIIRectangle(7,5,offset=5) ####### # # # # # # ####### >>> ASCIIRectangle(7,5,bchar="+") +++++++ + + + + + + +++++++ >>> ASCIIRectangle(7,5,filled=True) ####### ####### ####### ####### ####### >>> ASCIIRectangle(7,5,filled=True,bchar='.',offset=7) ....... ....... ....... ....... .......Hint: Remember that if w is a string and k is an int,
w*k creates a string that is k copies of
w, all concatenated together.
ASCIIRectangle the option to specify a text
message that should appear inside the box. It should (of course)
be centered vertically and horizontally. In this case, we want
a new parameter msg with a default value that
somehow indicates that there is no message. Python has a
value None that literally means no value, and we
can assign a variable the value None, like
x = None. I suggest making the default value of
the msg parameter None.
Hint:
You can test whether something is None exactly as
you would expect:
msg == None.
Alternatively,
you can test whether msg is actually a
string using
isinstance(msg,str), which
returns True if msg is an object of type str, False otherwise.
>>> ASCIIRectangle(7,5,bchar='.',offset=7,msg="rat") ....... . . . rat . . . ....... >>> ASCIIRectangle(7,5,bchar='.',offset=7,msg="rat",filled=True) ....... ....... ..rat.. ....... .......
'm' for the
message, key 'v' for vertical positioning (top/center/bottom),
and key 'h' for horizontal positioning (top/center/bottom).
>>> ASCIIRectangle(7,5,bchar='.',offset=7,msg={'m':"rat",'v':'top','h':'center'})
.......
. rat .
. .
. .
.......