ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 17.04.2021

Просмотров: 3756

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

CHAPTER

SEVEN

FUNCTIONS

As you develop more complex computer code, it becomes increasingly important to or-
ganize your code into modular blocks. One important means for doing so is

user-defined

Python functions. User-defined functions are a lot like built-in functions that we have
encountered in core Python as well as in NumPy and Matplotlib. The main difference is
that user-defined functions are written by you. The idea is to define functions to simplify
your code and to allow you to reuse the same code in different contexts.

The number of ways that functions are used in programming is so varied that we cannot
possibly enumerate all the possibilities. As our use of Python functions in scientific pro-
gram is somewhat specialized, we introduce only a few of the possible uses of Python
functions, ones that are the most common in scientific programming.

7.1 User-defined functions

The NumPy package contains a plethora of mathematical functions.

You can find

a listing of the mathematical functions available through NumPy on the web page

http://docs.scipy.org/doc/numpy/reference/routines.math.html

While the list may seem

pretty exhaustive, you may nevertheless find that you need a function that is not available
in the NumPy Python library. In those cases, you will want to write your own function.

In studies of optics and signal processing one often runs into the sinc function, which is
defined as

sinc

x

sin

x

x

.

Let’s write a Python function for the sinc function. Here is our first attempt:

115


background image

Introduction to Python for Science, Release 0.9.23

def

sinc

(x):

y

=

np

.

sin(x)

/

x

return

y

Every function definition begins with the word

def

followed by the name you want to

give to the function,

sinc

in this case, then a list of arguments enclosed in parentheses,

and finally terminated with a colon. In this case there is only one argument,

x

, but in

general there can be as many arguments as you want, including no arguments at all. For
the moment, we will consider just the case of a single argument.

The indented block of code following the first line defines what the function does. In
this case, the first line calculates

sinc

x

= sin

x/x

and sets it equal to

y

. The

return

statement of the last line tells Python to return the value of

y

to the user.

We can try it out in the IPython shell. First we type in the function definition.

In [1]:

def

sinc

(x):

...:

y

=

sin(x)

/

x

...:

return

y

Because we are doing this from the IPython shell, we don’t need to import NumPy; it’s
preloaded. Now the function

sinc

x

is available to be used from the IPython shell

In [2]:

sinc(

4

)

Out[2]:

-

0.18920062382698205

In [3]:

a

=

sinc(

1.2

)

In [4]:

a

Out[4]:

0.77669923830602194

In [5]:

sin(

1.2

)

/

1.2

Out[5]:

0.77669923830602194

Inputs and outputs 4 and 5 verify that the function does indeed give the same result as an
explicit calculation of

sin

x/x

.

You may have noticed that there is a problem with our definition of

sinc

x

when

x=0.0

.

Let’s try it out and see what happens

In [6]:

sinc(

0.0

)

Out[6]:

nan

IPython returns

nan

or “not a number”, which occurs when Python attempts a division by

zero, which is not defined. This is not the desired response as

sinc

x

is, in fact, perfectly

well defined for

x

= 0

. You can verify this using L’Hopital’s rule, which you may have

116

Chapter 7. Functions


background image

Introduction to Python for Science, Release 0.9.23

learned in your study of calculus, or you can ascertain the correct answer by calculating
the Taylor series for

sinc

x

. Here is what we get

sinc

x

=

sin

x

x

=

x

x

3

3!

+

x

5

5!

+

...

x

= 1

x

2

3!

+

x

4

5!

+

... .

From the Taylor series, it is clear that

sinc

x

is well-defined at and near

x

= 0

and that, in

fact,

sinc(0) = 1

. Let’s modify our function so that it gives the correct value for

x=0

.

In [7]:

def

sinc

(x):

...:

if

x

==

0.0

:

...:

y

=

1.0

...:

else

:

...:

y

=

sin(x)

/

x

...:

return

y

In [8]:

sinc(

0

)

Out[8]:

1.0

In [9]:

sinc(

1.2

)

Out[9]:

0.77669923830602194

Now our function gives the correct value for

x=0

as well as for values different from zero.

7.1.1 Looping over arrays in user-defined functions

The code for

sinc

x

works just fine when the argument is a single number or a variable

that represents a single number. However, if the argument is a NumPy array, we run into
a problem, as illustrated below.

In [10]:

x

=

arange(

0

,

5.

,

0.5

)

In [11]:

x

Out[11]:

array([

0.

,

0.5

,

1.

,

1.5

,

2.

,

2.5

,

3.

,

3.5

,

4. ,

4.5])

In [12]:

sinc(x)

----------------------------------------------------------

ValueError

Traceback (most recent call last)

----> 1 sinc(x)

1 def sinc(x):

----> 2

if x==0.0:

3

y = 1.0

7.1. User-defined functions

117


background image

Introduction to Python for Science, Release 0.9.23

4

else:

5

y = np.sin(x)/x

ValueError: The truth value of an array with more than one

element is ambiguous.

The

if

statement in Python is set up to evaluate the truth value of a single variable, not of

multielement arrays. When Python is asked to evaluate the truth value for a multi-element
array, it doesn’t know what to do and therefore returns an error.

An obvious way to handle this problem is to write the code so that it processes the array
one element at a time, which you could do using a

for

loop, as illustrated below.

1

def

sinc

(x):

2

y

=

[]

# creates an empty list to store results

3

for

xx

in

x:

# loops over all elements in x array

4

if

xx

==

0.0

:

# adds result of 1.0 to y list if

5

y

+=

[

1.0

]

# xx is zero

6

else

:

# adds result of sin(xx)/xx to y list if

7

y

+=

[np

.

sin(xx)

/

xx]

# xx is not zero

8

return

np

.

array(y)

# converts y to array and returns array

9

10

import

numpy

as

np

11

import

matplotlib.pyplot

as

plt

12

13

x

=

np

.

linspace(

-

10

,

10

,

256

)

14

y

=

sinc(x)

15

16

plt

.

plot(x, y)

17

plt

.

axhline(color

=

"gray"

, zorder

=-

1

)

18

plt

.

axvline(color

=

"gray"

, zorder

=-

1

)

19

plt

.

show()

The

for

loop evaluates the elements of the

x

array one by one and appends the results to

the list

y

one by one. When it is finished, it converts the list to an array and returns the

array. The code following the function definition plots

sinc

x

as a function of

x

.

In the program above, you may have noticed that the NumPy library is imported

after

the

sinc(x)

function definition. As the function uses the NumPy functions

sin

and

array

, you may wonder how this program can work. Doesn’t the

import numpy

statement have to be called before any NumPy functions are used? The answer it an em-
phatic “YES”. What you need to understand is that the function definition is

not executed

when it is defined, nor can it be as it has no input

x

data to process. That part of the code

is just a definition. The first time the code for the

sinc(x)

function is actually executed

is when it is called on line 14 of the program, which occurs after the NumPy library is

118

Chapter 7. Functions


background image

Introduction to Python for Science, Release 0.9.23

imported in line 10. The figure below shows the plot of the

sinc

x

function generated by

the above code.

10

5

0

5

10

0.4

0.2

0.0

0.2

0.4

0.6

0.8

1.0

Figure 7.1: Plot of user-defined

sinc(x)

function.

7.1.2 Fast array processing in user-defined functions

While using loops to process arrays works just fine, it is usually not the best way to
accomplish the task in Python. The reason is that loops in Python are executed rather
slowly. To deal with this problem, the developers of NumPy introduced a number of
functions designed to process arrays quickly and efficiently. For the present case, what we
need is a conditional statement or function that can process arrays directly. The function
we want is called

where

and it is a part of the NumPy library. There

where

function

has the form

where(condition, output

if

True

, output

if

False

)

The first argument of the

where

function is a conditional statement involving an array.

The

where

function applies the condition to the array element by element, and returns the

second argument for those array elements for which the condition is

True

, and returns the

third argument for those array elements that are

False

. We can apply it to the

sinc(x)

function as follows

7.1. User-defined functions

119