Python programming:関数を作成する PARTⅠ

Python programmingの基礎が全く出来ていないので、少し真剣にPython programmingの基礎をやってみようと思う。というのも、やはり簡単な関数くらい自分でちょちょいとコードが組めるようにならないと、いつまで経っても先に進めない気がしてきたからだ。

スポンサーリンク

Pythonで関数を作成する

Python Tutorialとしてこのサイトを参考にしながら粛々と作業を進めていく。先ずは必要なモジュールをインポートする。

import os
import sys
import glob
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
%matplotlib inline
%precision 4
'%.4f'

与えられた値を二乗、三乗して値を返す関数を作成する。

def square(x):
    """Square of x."""
    return x*x

def cube(x):
    """Cube of x."""
    return x*x*x
# create a dictionary of functions

funcs = {
    'square': square,
    'cube': cube,
}
x = 2

print (square(x))
print (cube(x))

for func in sorted(funcs):
    print (func, funcs[func](x))
4
8
cube 8
square 4

Higher-order functions

他の関数を入力引数として使う、もしくは、関数を返す関数は、高階関数(HOF)として知られている。最も馴染み深い例がmapとfilterだ。

# The map function applies a function to each member of a collection

list(map(square, range(10)))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
list(map(cube, range(10)))
[0, 1, 8, 27, 64, 125, 216, 343, 512, 729]
# The filter function applies a predicate to each memmber of a collection,
# retaining only those members where the predicate is True

def is_even(x):
    return x%2 == 0

def is_odd(y):
    return y%2

print(list(filter(is_even, range(25))))
print(list(filter(is_odd, range(26))))
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25]
# It is common to combine map and filter

list(map(square, filter(is_even, range(25))))
[0, 4, 16, 36, 64, 100, 144, 196, 256, 324, 400, 484, 576]
# The reduce function reduces a collection using a binary operator to 
#combine items two at a time

from functools import reduce

def my_add(x, y):
    return x + y

# another implementation of the sum function
print(reduce(my_add, [1,2,3,4,5]))
15

Returning a function

# Returning a function is also useful

# A closure
def make_logger(target):
    def logger(data):
        with open(target, 'a') as f:
            f.write(data + '\n')
    return logger

foo_logger = make_logger('foo.txt')
foo_logger('Hello')
foo_logger('World')
cat foo.txt
Hello
World

Anonymous functions

無名関数lambda(ラムダ)については過去にこのブログで実践済み。

print(reduce(my_add, [1,2,3,4,5]))
print(reduce(lambda x,y: x+y, [1,2,3,4,5]))
print(reduce(lambda x, y: x+y, range(1,6)))
print(reduce(lambda x, y: x+y, range(6)))
15
15
15
15
# what does this function do?
s1 = reduce(lambda x, y: x+y, map(lambda x: x**2, range(1,10)))
print(s1)
print

# functional expressions and lambdas are cool
# but can be difficult to read when over-used
# Here is a more comprehensible version
s2 = sum(x**2 for x in range(1, 10))
print(s2)

# we will revisit map-reduce when we look at high-performance computing
# where map is used to distribute jobs to multiple processors
# and reduce is used to calculate some aggreate function of the results
# returned by map
285
285

Pure functions

純粋関数は、グローバル変数に依存していない、同じ値がフィードされれば常に同じ値を返すピュアな関数のことで、並列処理が必要な時に便利な関数だ。

def pure(xs):
    """Make a new list and return that."""
    xs = [x*2 for x in xs]
    return xs
xs = list(range(5))
print ("xs =", xs)
print (pure(xs))
print ("xs =", xs)
xs = [0, 1, 2, 3, 4]
[0, 2, 4, 6, 8]
xs = [0, 1, 2, 3, 4]
def impure(xs):
    for i, x in enumerate(xs):
        xs[i] = x*2
    return xs
xs = list(range(5))
print ("xs =", xs)
print (impure(xs))
print ("xs =", xs)
xs = [0, 1, 2, 3, 4]
[0, 2, 4, 6, 8]
xs = [0, 2, 4, 6, 8]
# Note that mutable functions are created upon function declaration, not use.
# This gives rise to a common source of beginner errors.

def f1(x, y=[]):
    """Never give an empty list or other mutable structure as a default."""
    y.append(x)
    return sum(y)
print (f1(10))
print (f1(10))
print (f1(10, y =[1,2]))
10
20
13
# Here is the correct Python idiom

def f2(x, y=None):
    """Check if y is None - if so make it a list."""
    if y is None:
        y = []
    y.append(x)
    return sum(y)
print (f1(10))
print (f1(10))
print (f1(10, y =[1,2]))
30
40
13