AA - 3.05.発展的な文法 Editorial /

Time Limit: 0 msec / Memory Limit: 0 KiB

前のページ | 次のページ

キーポイント

  • X if (条件式) else Y は条件式の値が True であれば X 、そうでなければ Y を値にとる式。
  • 短絡評価
    • and 演算子の左側の式が False の場合、右側の式の評価は行われない。
    • or 演算子の左側の式が True の場合、右側の式の評価は行われない。
  • 関数名 = lambda 引数: 返り値 と記述することで関数を 1 行で定義できる。
  • 関数定義において def func(引数名=値) のように記述することで引数にデフォルト値(引数を与えなかった場合に使われる値)を設定することができる

便利な記法

本節ではこれまでに扱わなかった、Python の便利な記法を紹介します。
これらの記法を知ることでコードをより簡潔に書くことができるようになります。また、他の人が書いたコードを理解するのに必要となることもあるでしょう。

三項演算子

X if (条件式) else Y と書くことで、条件式の値が True であれば X 、そうでなければ Y を値にとる式を書くことができます。

次のプログラムでは、「i が偶数なら i そのもの、そうでなければ(奇数なら) i を 100 倍したもの」という式を三項演算子で記述しています1

l = [(i if i%2==0 else i*100) for i in range(10)]
print(l)
実行結果
[0, 100, 2, 300, 4, 500, 6, 700, 8, 900]

次のように書いても同じ結果が得られます:

l = []
for i in range(10):
    if i%2==0:
        l.append(i)
    else:
        l.append(i*100)
print(l)

論理演算の処理内容

1.07 節では論理演算子 andor を扱いました。本節では知っておくと役に立つ、これらの演算の細かい処理内容を説明します。

これらの演算では左から順に与えられた式を評価していき、最終的な結果を返します。このとき、必ずしもすべての式を評価するとは限りません。例えば、A and B の演算において AFalse となった場合、B の値によらず式全体の値も False であることが確定します。このような場合、B の評価は行われません。同様に、X or Y の演算において XTrue となった場合、Y の値によらず式全体の値も True であることが確定します。この場合も Y の評価は行われません。

このように、不要な評価をスキップして式全体の値を評価を行うことを「短絡評価」と呼びます。
以上をまとめると、次のようになります:

  • and 演算子の左側の式が False の場合、右側の式の評価は行われない。
  • or 演算子の左側の式が True の場合、右側の式の評価は行われない。

例えば次のコードでは2つある if 文のいずれにおいても短絡評価が行われた結果、hello 関数の呼び出しは行われません:

コード例
def hello():
    print("Hello")
    return True
if True or hello():
    print("条件式はTrue")
if False and hello():
    print("条件式はFalse")
実行結果
条件式はTrue

ラムダ式

1.13 節では関数定義は以下のように記述することを学びました:

def 関数名(引数):
    処理内容
    return 返り値

このとき、「処理内容」が存在しない関数であれば、実はこの記述は次のように一行で記述することが可能です。この記法を「ラムダ式」と呼びます:

関数名 = lambda 引数: 返り値

例で確認してみましょう。次の func1func2 は全く同じように動作します:

def func1(a):
    return a+10

func2 = lambda a: a+10

print(func1(1), func2(1))
実行結果
11 11

慣れないうちは無理にラムダ式を使わず、def ... を使えばよいでしょう。
コードを読む際に lambda ... が出てきたら関数定義をしている、ということが理解できれば十分です。

関数引数のデフォルト値

関数の定義 def 関数名(引数名): において、def 関数名(引数名 = デフォルト値) とすることで、引数を省略したときに デフォルト値 が使われるようになります。
次のコードでは引数 a にデフォルト値 10 を指定しています:

def func(a = 10):
    print(a * 3)

func(1) # 引数を与える -> 3
func() # 引数を省略 -> デフォルト値(10) が引数として使われる -> 30

この記法は同じ関数を何度も呼び出すが、一部を除いて同じ値を引数として与えることが殆どであるような場合に重宝します。特に、実装途中に関数に引数を増やした場合に便利です。

例えば以下のようなプログラムを書いたとします:

def add_vals(a):
    # リスト a の各要素に対し、先頭から順に 0,1,2,... を足し込む
    for i in range(len(a)):
        a[i] += i

a = [3,1,2]
b = [4,5,6]
c = [3,3,1]
add_vals(a)
add_vals(b)
add_vals(c)

ここで仮に「c に対してだけ 0,1,2... ではなく 1,2,3... を足したい」となったとします。
同じ関数を使いまわすために、次のように引数を追加してみましょう:

def add_vals(a, start):
    # リスト a の各要素に対し、先頭から順に start, start+1, start+2,... を足し込む
    for i in range(len(a)):
        a[i] += i + start

a = [3,1,2]
b = [4,5,6]
c = [3,3,1]
add_vals(a, 0) # start = 0 -> 0,1,2... が足し込まれる
add_vals(b, 0)
add_vals(c, 1) # start = 1 -> 1,2,3... が足し込まれる

ここで引数 start にデフォルト値 0 を指定することで、例外ケース c のときだけ引数を与えれば済むようになります。

def add_vals(a, start = 0):
    # リスト a の各要素に対し、先頭から順に start, start+1, start+2,... を足し込む
    # start はデフォルト値 0 を持つ
    for i in range(len(a)):
        a[i] += i + start

a = [3,1,2]
b = [4,5,6]
c = [3,3,1]
add_vals(a) # start の指定を省略 -> start = 0 が使われる -> 0,1,2... が足し込まれる
add_vals(b)
add_vals(c, 1) # start = 1 -> 1,2,3... が足し込まれる

このように、一度実装したあとに動作を変更したくなることは良くあるため、覚えておくと便利な記法です。
また、コードを読む際もデフォルト値が定義されていることは把握しておく必要があります。

補足と注意

複数のデフォルト値引数

デフォルト値を持つ引数は複数個同時に記述することも可能です。
このとき、呼び出し時に 変数名 = 値 のように記述することで特定の要素のみ値を指定することができます。
変数名を指定しない引数については前から順に割り当てられます。

def func(a=1, b=2):
    print(a+b)
func(3,4) # 3 + 4 = 7
func(10) # 10 + 2 = 12
func(b=3) # 1 + 3 = 4

なお、変数名を指定する引数のあとに変数名を指定しない引数を与えるとエラーになるため注意が必要です:

func(a=2, 4) # SyntaxError: positional argument follows keyword argument

位置引数とデフォルト値引数

デフォルト値を持たない引数のことを位置引数と呼びます。
ひとつの関数の引数に位置引数とデフォルト値を持つ引数の両方が存在するとき、位置引数を先に記述しないとエラーになります

def func(a, b=1):
    return a+b
def func(b=1, a):
    # SyntaxError: non-default argument follows default argument
    return a+b

問題

本節には練習問題はありません。

前のページ | 次のページ


  1. コードの中のカッコは読みやすさのために付しています。無くても結果は変わりません。