Python、はじめました

非IT系私文卒リーマン vs Python の全記録

Python SoloLearn Functional Programing

 

More Typeの章は特に引っかかるとこなかったので、省略しました♨

Lambdas

 

Creating function nomally (using def) assigns it to variable automatically.

This is different from the creation of other objects - such as strings and

integers- which can be created on the fly without assigning them to variable.

 "関数を定義する際は、def function_name():以下定義

を書くが、これは以下定義の内容をfunction_nameという変数に

代入しているだけなのである。

一方、関数以外の型、例えばstringやintegersは変数を使わなくとも

直接書き示すことができる。"

 

 a_function(arg)の引数に関数を入れたい場合

まずその関数をx_functionという変数に代入したうえでなければ引数に取れない。

対して、stringやintegersは直接引数に入れることができる。

 

その手間を解決し、何ならたった1行で関数を作ることができるのが

Lambdasによる無名関数である。

 

次のコードの上下はどれも同じ内容を書いている。

上のコードに比べ下のコードの方が簡潔で読みやすい。

一行だもん。

 

def func(x):
return x**2 + 4*x + 4


print(func(2))
16

 これがこう

print((lambda x: x**2 + 4*x + 4)(2))
16

lambdaの無名関数に引数を渡す場合は

lambda x: x**2 + 4*x + 4, 4

という形で, arg でlambda以下に続けるか、

(lambda x: x**2 + 4*x + 4)(2))

という形で、(lambdax :~~~~)(arg)で渡すかになっている。

 

defにできてlambdaにできないことはないので

別に覚えなくてもいい。

ただ、一行で関数を書けるという便利さと

関数を作っても一度しか引数を渡さない(再利用しない)

の場合だと、lambdaの方がきれいなコードが書けるのでお得。

 

map & filter

両関数はiterable型のオブジェクトを戻す。

これは直接にはprintで出力できないため本文ではlist関数を使い

list化することで目に見える形で出力している。

 

The function map takes a function and an iterable as argument,

and returns a new iterable with the function applied to each argument.

 "map関数は関数とiterableを引数に持ち、その関数をiterableの

ひとつひとつに適用させ、新たなiterableを戻す。"

 

本文では引数にlistを取っていたが、stringもiterableであるため、

以下のようなコードにも対応できる。

def plus_a(x):
return x + "a"


print(list(map(plus_a, "abc")))
['aa', 'ba', 'ca']

iterableについてはまた別のコラムで(準備)

 

The function filter filters an iterable by removing items that don't match

a predicte(a function that return a Boolean).

"filter関数は、述語(真偽を戻す関数)と一致しない要素を削除することで、

引数のiterableをフィルタリングします。"

 

map関数で使ったのと同じ引数を使ってfilter関数を実行してみる。

def plus_a(x):
return x + "a"


print(list(filter(plus_a, "abc")))
['a', 'b', 'c']

iterable("a", "b", "c")が代入されるたび、plus_a関数は"aa","bb","cc"を戻す。

その戻り値はどれもtrueなので(noneやfalseでなければtrue)

trueになったiterableとして、"a","b","c"が戻される。

 

このコードの方がわかりやすいかも。

def string_check(x):
if type(x) == str:
return True
else:
return False


print(list(filter(string_check, ["a", 2, "3"])))
['a', '3']

これをlambdaを使って一行で書くとこんな感じ。

print(list(filter(lambda x: type(x) == str, ["a", 2, "3"])))
['a', '3']

 この無名関数は、引数にstrが入ったらTrueを、それ以外はFalseを戻す。

 

Generators

 

Generators are type of iterable, like lists or tuples.

Unlike lists, they don't allow indexing with arbitray indices,

but they can still be iterated through with for loop.

 

generatorオブジェクトが何か、という説明よりも、

iterableが何か、という説明になっている。

generator∊iterable であるため、generatorはiteratorの性質を持つということ。

 

def countdown():
i = 5
while i > 0:
yield i
i -= 1


print(type(countdown))
<class 'function'>
print(countdown())
<generator object countdown at 0x000001AB93DD5990>

genarator関数と言えどもdefで定義づけられる関数に過ぎず、

generatorオブジェクトとはその実行によって戻される値のこと。

 

Due to the fact that they yield one item at a time,

generetors don't have the memory restrictions of lists.

 

引数に限界があるrange()や内表記に限界があるlistとは違い、

呼び出すたびにひとつの値を戻すgeneratorには

iterableとしての限界がない。

 

まずはiterable基礎から。

def plus(x):
return x + 5


for i in range(5):
print(plus(i))





10

for構文は後述文の関数のパロメーターに、in以下のiterableを順次入れていく

という意味がある。

上のコードでは、(0,1,2,3,4)が入ったiteratorのひとつひとつの値を

plus関数の引数にとって出力している。

 

では次はgenerator関数の話。

def count_down(x):
while x < 10:
yield x
x += 1


def plus(x):
return x + 5


for i in count_down(5):
print(plus(i))
10
11
12
13
14

generator関数であるcount_down(5)は、iteraterとして

関数外部のforで呼び出されるたびに、5,6,7,8,9を戻す。

 generatorについて詳しくはこちら。

python3.hatenadiary.jp

 

 Decorators

 

Decorators provide a way to modify functions using other functions.This is ideal when you need to extend the functionally of functions that you don't want to modify.

 

関数を引数に取り、その引数に取った関数の出力結果を

装飾する関数のことをdecoratorと呼ぶ。

書いていることはわかるんだけど、その例文コードが難しい。

def deco(func):
def wrap():
print("==========")
func()
print("==========")
return wrap


def print_text():
print("Hello World")


decorated = deco(print_text)
decorated()
>>>
==========
Hello World
========== 

deco関数が初めに定義される。

deco関数内にはwrap関数が定義されており、

wrap関数は実行されると引数func関数を実行する。

deco関数は実行されると内包するwrap関数を戻す。

 

ここwrap関数の実行ではなく、
wrap関数自身ってところが重要。

 

その後print_text関数が定義される。

print_text関数自身を引数に取ったdeco関数の実行結果

変数decoratedに代入される。

 

ここで、変数docoratedの中身を見てみる。

def deco(func):
def wrap():
print("==========")
func()
print("==========")
return wrap


def print_text():
print("Hello World")


decorated = deco(print_text)
print(decorated)
>>>
<function deco.<locals>.wrap at 0x000002E269ED4048>

戻り値はwrap関数自身である。

何故なら、deco(print_text)でreturnされるのはwrap関数自身だから。

変数decoratedには、関数が代入されているため、

その実行を表す()をつけることで、意図した戻り値を出せるのだ。

 

代入を使わなければ、こんな感じになる。

def deco(func):
def wrap():
print("==========")
func()
print("==========")
return wrap


def print_text():
print("Hello World")


deco(print_text)() #←deco(print_text)=wrap + () = wrap()!!
>>>
==========
Hello World
==========

上記のようなコードにおいて、

関数を装飾するdeo関数は何度も使いたいけど、
それに引数として渡される関数はここでしか使わないな

というときに使えるのが@deco

これをdecoratedされる関数の定義の先頭につけるだけで、

その関数は実行時deco関数の引数に渡されたものが実行される。

def deco(func):
def wrap():
print("==========")
func()
print("==========")
return wrap

@deco
def print_text():
print("Hello World")


print_text() 
>>>
==========
Hello World
==========

 少しコードがスッキリするのと、この関数はあのdeco限定なんだ、

というのが一目で明らかになるので運用が楽?

 

Recursion

関数内でその関数を再び呼ぶ、という再帰処理のこと。

base caseという繰り返し処理の終着点の処理は、

しっかりif等を使い再帰しない形で定義しましょうと説いている。

 

そこまで難しい項目でもないので飛ばそうと思ったけど、

例文コードに気になる記載があったので、それについて書く。

def is_even(x):
if x == 0:
return True
else:
return is_odd(x - 1)


def is_odd(x):
return not is_even(x)


print(is_even(17))
>>>False
print(is_odd(23))
>>>True

return not とすることで、戻り値のboolean値を反転させている。

ここかっこいい。

 

 Sets

setオブジェクトはlistと多くの機能を共有していることから、

mustなオブジェクトではない。

 

Set can be combined using mathematical operations.

 

とあるように、これだけにしかできな機能と言えば演算子が使えること。

list1 = [1,2,3,4,5]
list2 = [6,7,8,9]
print(list1 & list2)
>>>TypeError: unsupported operand type(s) for &: 'list' and 'list'

set1 = set(list1)
set2 = set(list2)
print(set1 | set2)
>>>{1, 2, 3, 4, 5, 6, 7, 8, 9}

 

They unordered,which means that they can't be indexed.

They can't contain duplicate elements.

 

という特徴から、listよりも早く処理を行うことができるという性質もある。

 

今回はこんな感じ。