第1回 Pythonの基礎

目次

  • はじめに
    • 使える文字など
    • print関数
  • 変数と演算
    • 変数の生成
    • 演算
  • 配列
    • 1つの要素の指定
    • 複数の要素の指定
    • len関数
    • 型の確認
    • 型の変換
  • 繰り返し
    • for構文とインデントの基本
    • rangeを使った繰り返し
    • range以外についての繰り返し
    • 級数の計算
  • 条件分岐
    • 論理演算
    • if構文の基本
    • if ... elif ... else構文
  • 関数によるコードの再利用
    • 関数の基本
    • 引数が複数の場合、引数がない場合
    • デフォルト値
    • 値を返さない関数
    • 変数のスコープ
  • 追加で勉強するとよいこと

はじめに

この一連の資料を通して、プログラミング言語Pythonを用いて大気海洋分野のデータ解析や数値シミュレーションの基礎を解説することを目指します。 Pythonは、非常に多彩なライブラリ(拡張機能群)の力を借りることで力を発揮する言語です。(例:Numpy, Matplotlib, Pandas...) 今回は、その第一段階としてライブラリ無しの「生の」Pythonの文法を基礎から学びましょう。

Pythonプログラムは ○○.py という名前のテキストファイルに命令が一行一行書かれたもので、それを読み取って実行することでプログラムが実行されます。

この文書は、Jupyter labのノートブック形式で作成されています。 ノートブックはひとまとまりの「セル」が並んだ構造をしており、ここのようにテキストで書かれたセルと、数行のPythonの命令(グレーの背景)およびその結果を記したセルとをまとめて表示してくれます。 一つのページで説明と例を見ながら学んでいくことになります。ぜひ手元に実行環境を構築し、例を真似したり改変したりして理解を深めつつ読み進めてください。

それでは、早速Pythonの基礎を学んでいきましょう。

使える文字など

  • プログラミング言語の「変数」とは、数字や文字などのデータを格納する「入れ物」です。プログラミングが電卓と違う点のひとつは、具体的な数で計算させるのではなくて変数で計算式を作っておくことで、より複雑な計算や処理ができることです。プログラムではさまざまな変数を定義し、それらを用いて計算し、結果を得てゆきます。
  • Pythonの中では、変数名としてアルファベット(大文字小文字を区別する)・数字(1文字目には使えない)・アンダースコア_を用いることができます。
  • print, if, for, importなど一部の文字列はPython自体によって予約されており、自分で勝手に使うことはできません。
  • 半角スペースは無視されます。読みやすくなるように適宜挿入しましょう。ただし、後述の通り行頭のスペース(インデントと呼びます)は特別な意味を持ちますので無意味には使えません。
  • Pythonはコードを上から順に一行一行読み取り実行してゆきます。改行は一行でも二行以上でも同じですので、読みやすくなるよう適宜空行も活用しましょう。
  • 行の#以降は読み取られません。コメントに用います。

print関数

  • print(○○)は、カッコ内の変数などを文字として書き出す機能です。変数にどんな数が入っているのかなど、状況確認に非常によく使います。
  • このようにカッコ内を引数として、決まった命令を実行する機能を「関数」と呼びます。
In [1]:
print("Hello, world!") # "Hello, world!" という文字列を出力する
Hello, world!
In [2]:
a = 5 # 変数aに5を代入する
b = -2 # 変数bに-2を代入する
print(a+b) # a+bを出力する

b = 10 # 変数bに10を代入する、-2は上書きされる
print(a+b) # a+bを出力する
3
15

練習1-1

  1. "Hello, world!"を出力してみましょう。ダブルクォーテーション「"」もお忘れなく。
  2. xに5, yに3を代入し、x+y, x-y, x*y, x/yをそれぞれ出力してみましょう。

変数と演算

変数の生成

上の例のとおり、変数は変数名=値という文によって生成できます。同値を示す数学のイコールではなく、値を変数名に代入する、というイメージです。

変数には様々な「型」があります。値の書き方によって、型が自動的に判別されます。

  • 整数・浮動小数点数(実数):5, -3, 1.5, 5000.0, 5e3, 0.012, 1.2e-2など... eを使った書き方にも慣れよう
  • 文字列:引用符"または'で囲われた部分。"Hello world!", "123"など
  • 論理型(bool型):TrueFalseのみ。大文字小文字注意

演算

整数型や浮動小数点型の変数は、計算式に当てはめていろいろな計算を行えます。

  • 四則演算:+, -, *, /
  • 商の整数部://
  • 余り:%
  • べき乗:**(例:2の8乗は2**8
  • カッコ () は通常の数式と同様、計算の順番を指定します。式の解釈に曖昧さがあるときは、特に使うようにしましょう。

数以外の型にも演算が定義されていることがあります。例えば文字列どうしの足し算 + は、文字列の結合を意味します。

In [3]:
# 上のセルのa=5, b=10を記憶している
c = a - b
print(c)
print(c**2)

myname = "Fujiwara"
print("My name is " + myname)
-5
25
My name is Fujiwara

練習1-2

24 ÷ 6 ÷ 2は解釈のしようによって結果が2通りあります。それぞれの場合を曖昧さが残らないように数式で表し、結果をprintしましょう。

配列

たとえば100人分の試験の点数を扱いたいときに、score1, score2, score3...と一つ一つ変数を用意していてはきりがありません。 そういったときは、データの「列」である配列を用います。 Pythonでは配列にあたる型がいくつもありますが、ここでは「リスト」を紹介します。

In [4]:
# リストは角カッコで定義し、中に要素をカンマで区切って入れていく
mylist1 = [0, 3, 1.5]
mylist2 = [c, c**2, c**3, c**4] # 上のc=-5を記憶している
mylist3 = ["apple", "orange"] # リストの要素はどんな型でもいい

# リストの足し算はリストの結合を表す
numbers = mylist1 + mylist2
print(numbers)

# len()はリストの要素数を返す関数
print(len(numbers))
[0, 3, 1.5, -5, 25, -125, 625]
7

1つの要素の指定

配列の要素は、角カッコで0から始まる要素番号を与えることで取り出せます。

In [5]:
# numbers = [0, 3, 1.5, -5, 25, -125, 625]
print(numbers[0]) # 一番前:0
print(numbers[2]) # 0から数え始めて2番目:1.5
print(numbers[-1]) # マイナスはリストの最後から数える:625
print(numbers[10]) # リストをはみ出す番号はエラーを吐きます
0
1.5
625
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Input In [5], in <cell line: 5>()
      3 print(numbers[2]) # 0から数え始めて2番目:1.5
      4 print(numbers[-1]) # マイナスはリストの最後から数える:625
----> 5 print(numbers[10])

IndexError: list index out of range

複数の要素の指定

「2番目から4番目」や「偶数番目」のように、複数の要素を抜き出すこともできます。スライスと呼びます。 スライスは、[start:end:interval]のように表記し、「start番目からend番目の手前まで、interval個おきに」要素を取り出します。 ここで、end番目自体はスライスに含まれないことに注意しましょう。癖がありますが、慣れると思います。

startを省略すると配列の最初の要素から、endを省略すると配列の最後の要素まで、intervalを省略すると要素を飛ばさないという意味になります。

In [6]:
# numbers = [0, 3, 1.5, -5, 25, -125, 625]
print(numbers[3:5]) # 0から数え始めて、3番目から5番目の手前まで
print(numbers[:-3]) # 最初の要素から、後から3番目の手前まで
print(numbers[::2]) # 0, 2, 4,...番目
[-5, 25]
[0, 3, 1.5, -5]
[0, 1.5, 25, 625]

練習1-3

まず、0から30までの、偶数のリストを作りましょう。後で説明するrange関数を用います。

In [7]:
x = list(range(0, 30, 2))
print(x)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28]

xができたら、次の要素を取り出すにはどうすればよいでしょうか。

  1. 0から数えて5番目(正解:10)
  2. 5番目から8番目(正解:10, 12, 14, 16)
  3. 後から4番目以降(正解:22, 24, 26, 28)

len関数

最後に、配列の長さ(要素数)を得る関数としてlen関数を紹介します。len関数は文字列の長さ(文字数)にも用いられます。

In [8]:
print(len([1,5,0])) # 3
print(len([5])) # 1
print(len([])) # 空っぽのリストの長さはゼロ

a = list(range(10, 2000, 30)) # 10から始まって2000を超えない範囲の、30おきの等差数列
print(len(a))
3
1
0
67

上で説明した通り、すべての変数にはその種別を表すがあります。 型によって、定義されている操作が異なるのでその確認は非常に重要です。

型の確認

変数の型は、type(変数)によって確認できます。型には以下のようなものがあります。

  • int 整数 (integer)
  • float 実数 (浮動小数点数、floating-point number)
  • complex 複素数 (complex number)
  • str 文字列 (string)
  • bool 論理型
  • list リスト
  • tuple タプル
  • func 関数
  • np.ndarray ndarray (NumPyの回で説明します)
In [9]:
x = 3
y = 3.14
z = "3.14"
print(type(x))
print(type(y))
print(type(z))
<class 'int'>
<class 'float'>
<class 'str'>

型の変換

実数→整数や整数→文字列、リスト→np.ndarrayなどのように、型を変換したいことが出てきます。 そのようなときは、型名(変数)とすると型を変換できます。

In [10]:
# y = 3.14, z = "3.14"
print(y + float(z)) # 実数 + 実数
print(str(y) + z) # 文字列 + 文字列
print(y + z) # 実数 + 文字列、怒られる
6.28
3.143.14
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [10], in <cell line: 4>()
      2 print(y + float(z)) # 実数 + 実数
      3 print(str(y) + z) # 文字列 + 文字列
----> 4 print(y + z)

TypeError: unsupported operand type(s) for +: 'float' and 'str'

繰り返し

for構文とインデントの基本

同じ処理をたくさん繰り返したいときは、ループを用いるのが有効です。Pythonでの代表的なループ構文は、for構文です。

for文は for ○○ in 配列等: という構文から始まります。コロン:を忘れないようにしましょう。 配列の成分をひとつづつ取り出して、それを○○として、それに続く行頭が字下げされた「ブロック」内の処理を繰り返し行います。

字下げ(インデント)はPythonでプログラムのひとまとまりを指定する方法で、for(あるいは次に説明するif)などの影響を受ける範囲を明確に指定するために、字下げの有無やスペースの個数の一貫性は厳密に守る必要があります。

In [11]:
# 例:リスト[1, 2, 3]の要素をnとして、n+10を順にprintする
for n in [1,2,3]:
    # 字下げされた部分を繰り返す
    a = n + 10
    print(a)
    print("inside loop")

# 行頭が戻ったので、ここ以降は繰り返さない
print("end of loop")
11
inside loop
12
inside loop
13
inside loop
end of loop

rangeを使った繰り返し

for構文のin以下には、配列のように順番をもつ(変数[0]のように要素を指定できる)変数が入ります。 中でも多く使うのはrange関数で、range(start, end, interval)によって、「初項start, 公差interval, 末項がendの手前までの等差数列」が作られます。 intervalstartは省略可能で、省略した場合interval=1, start=0と解釈されます。

以下の例ではrange(6)の要素を順にnに代入して、nの2乗を順にprintしてゆきます。

In [12]:
# 例: n=0から5までのnについて、n**2をprintする
# range(6)はrange(0, 6)およびrange(0, 6, 1)と同じで、[0,1,2,3,4,5]のこと
for n in range(6):
    print(n**2)
    
0
1
4
9
16
25
In [13]:
# 例: 単純に「n回繰り返す」というときもrange(n)が使えます
for n in range(3):
    print("Hello")
Hello
Hello
Hello

range以外での繰り返し

最初の例でお見せした通り、for ... in の後ろには、range以外にもリストなどを入れられます。その場合、配列の成分を前から順に拾ってゆきます。

In [14]:
# 例: a = ["orange", "apple", "banana", "peach"]について、順に"I like ○○"という文をprintする
a = ["orange", "apple", "banana", "peach"]
for fruit in a:
    print("I like " + fruit)
I like orange
I like apple
I like banana
I like peach

級数の計算

級数$\sum$などは繰り返し構文で計算できます。はじめに変数totalにゼロを設定しておき、for構文内でtotalに第1項、第2項...と順に足してゆけばよいのです。

実用ではNumpyなどのライブラリを用いればより高速に計算できますが、基本的な計算の仕組みを知っておくのは非常に大事です。

In [15]:
# 例: 等比級数 1 + 1/2 + 1/4 + 1/8 + ... の部分和を10項めまでprintする
sum = 0   # 合計、最初にゼロに設定しておく
for n in range(10):
    sum = sum + 1 / (2**n) # べき乗は掛け算割り算より優先されるので、1 / 2**nと書いても同じ
    print(sum)
1.0
1.5
1.75
1.875
1.9375
1.96875
1.984375
1.9921875
1.99609375
1.998046875

練習1-4

次の操作をfor文を使って書いてみましょう。

  1. 0, 1, ..., 9までのnについて、$2n$をprint
  2. 1, 3, 5, 7, ..., 19までのnについて、$2n$をprint(ヒント:rangeの使い方)
  3. 0, 1, ..., 9までのnについて、$2^n$を順にprint
  4. 0, 1, ..., 9までのnについて、$\sum_{k=0}^nk$を順にprint(0, 1, 3, 6, 10...)

条件分岐

論理演算

ある条件が満たされるか否か、を式で表します。結果は論理型のTrueまたはFalseになります。

  • 数の大小:>, <, >=, <=, ==, !=
  • 数以外の一致・不一致:==, !=
  • aかつb:a and b
  • aまたはb:a or b
  • aの否定:not a
  • 要素pが配列qの中にあるか否か:p in q

論理演算もカッコを使えます。and/or/notの優先順位を明確化するため、適宜用いましょう。

In [16]:
x = 10
y = 12
z = 15
print(x < y) # True

s = x < y  # s = Trueのように、変数に割り当てることもよくある
t = x > z  # t = False
print(s and t) # True and False = False
print(s or t)  # True or False = True
print(s and (not t)) # True and True = True
True
False
True
True

if構文の基本

ある条件のときは特定の処理を行う、ということをif文によって行えます。 if文は、if 論理式:という構文から始まり、論理式がTrueならば、それ以下のブロック内の処理を実行します。コロン:を忘れないように!

In [17]:
# 上のセルから、x=10, y=12
if x <= y:
    print("x is smaller than y")

if x == y:
    # Falseなので実行されない
    print("x is equal to y")
x is smaller than y

if ... elif ... else構文

また、条件を枝分かれさせることもできます。if ... else構文ではifの条件が満たされなかった場合はelse以下の処理が実行されます。

さらにif ... elif ... else構文ではifの条件が満たされなかった場合はelif(else ifの略です)の条件の判別が行われ、それも満たされなかった場合はelse以下の処理が実行されます。elifの分岐の個数はゼロ個を含め何個でもよく、elseもあってもなくても構いません。

In [18]:
like_meat = False

if like_meat:
    lunch = "Tonkatsu"
else:
    lunch = "Sandwich"

print(lunch)
Sandwich
In [19]:
like_meat = False
like_fish = True

if like_meat:
    lunch = "Tonkatsu"
elif like_fish:
    lunch = "Sushi"
else:
    lunch = "Sandwich"

print(lunch)
Sushi
In [20]:
# 応用例:数字nが素数 (prime number) かどうかを判別する
n = 47  # 1以上の数字、自由に変えられる

if n == 1: 
    prime = False
else:
    # 2以上n未満の数字のすべてで割り切れなかったら素数
    prime = True  # はじめにTrueとしておき、どこかで割り切れたらFalseに書き換える
    for c in range(2, n):
        if n % c == 0:
            prime = False

# 結果の書き出し
if prime:
    print("n is a prime number")
else:
    print("n is not a prime number")
n is a prime number

練習1-5

条件分岐を使って、2つの数nmの大小を判別するプログラムを組んでみましょう。 いろんなn, mの組み合わせについてプログラムが正常に動作していることを確かめましょう。

関数によるコードの再利用

関数の基本

数学で関数とは、ある引数xに対応した別の数yを返す対応関係で、y=f(x)のように書かれました。 プログラムでも同様に、引数に対応してある量を返す関数を定義できます。 関数を用いることで、同じ処理を何度も書きなおすことなくプログラム内でいろんな引数に対して再利用できます。

Pythonで関数を定義するときは、def 関数名(引数):という構文から始まり、関数の内容をブロック内に記述し、最終的な関数の値(返り値と呼ぶ)をreturn ○○で返します。 関数を使うときは関数名(引数)とします。

In [21]:
# いくつかの例
def func(x):
    return x**2 - 5*x + 3

def absolute(x):
    # 絶対値を返す
    # こういった単純な処理は自分で作らなくてもすでにPythonやNumpyに入っていますが、
    # 中身の処理を理解するのによい例です
    if x >= 0:
        absx = x
    else:
        absx = -x
    return absx

print(func(10))
print(absolute(10)) 
print(absolute(-5))

y = absolute(-2) + func(3)*0.5  # 普通に計算式に組み込めます
print(y)  # |-2| + 0.5 * (3**2 - 5*3 + 3) = +0.5
53
10
5
0.5
In [22]:
# 数字だけでなく、論理式や文字列を返す関数も作れます

def is_prime(n):
    # 素数ならTrue, そうでなければFalseを返す関数、前例の流用
    if n == 1: 
        prime = False
    else:
        # 2以上n未満の数字のすべてで割り切れなかったら素数
        prime = True  # はじめにTrueとしておき、どこかで割り切れたらFalseに書き換える
        for c in range(2, n):
            if n % c == 0:
                prime = False
    
    return prime

def odd_or_even(n):
    # 奇数なら"odd number", 偶数なら"even number", それ以外なら"not integer"(整数ではない)を返す関数
    if n % 2 == 1:
        result = "odd number"
    elif n % 2 == 0:
        result = "even number"
    else:
        result = "not integer"
    
    return result


print(is_prime(10))
print(is_prime(101))
print(odd_or_even(10))
print(odd_or_even(10.5))
False
True
even number
not integer

引数が複数の場合、引数がない場合

引数が複数の関数も同様に作れます。例えばxとyとzを引数とする場合def f(x,y,z):のかたちで関数定義を行い、関数呼び出しの際には同じ数の引数を与えます。

また、引数がない関数も作れます。その場合も関数定義の構文のカッコは飛ばさずdef f():の形で定義し、関数呼び出しの際もf()とカッコ付きで呼び出します。 ある決まった値を得るために関数を使う必要性は薄いですが、後で説明するように関数内で行う処理を目的として引数無しの関数を使う場合があります。

In [23]:
def func(x, y, z):
    return z - (x**2 + y**2)

print(func(0, 1, 2)) # x=0, y=1, z=2
print(func(-3, 4, 30)) # x=-3, y=4, z=30

def const():
    return 3.141592

print(2*const())
1
5
6.283184

デフォルト値

また、関数の引数にデフォルト値を設定することもできます。例えばy=10, z=20をデフォルトとする場合def func(x, y=10, z=20):のように、定義時にイコールでデフォルト値を設定します。 デフォルト値を設定すれば、関数呼び出しの際にその引数を省略することができます。

In [24]:
# デフォルト値を指定する例
def func(x, y=10, z=20):
    return z - (x**2 + y**2)

print(func(0))        # x=0, y=10, z=20
print(func(0, 5, 10)) # x=0, y=5,  z=10
print(func(0, z=10))  # x=0, y=10, z=10

def greeting(name, message="Good morning!"):
    return "Hi " + name + ", " + message

print(greeting("Ichiro"))
print(greeting("Jiro", "Good afternoon!"))
-80
-15
-90
Hi Ichiro, Good morning!
Hi Jiro, Good afternoon!

値を返さない関数

関数は値を返すだけでなく、その中で処理を行わせることを目的として使うこともできます。この場合、return ○○を与えずにそのまま字下げを戻すか、returnのみで関数を終わらせることができます。

In [25]:
# nの約数を出力する
def print_divisor(n):
    for m in range(1,n+1):
        if n % m == 0:
            # m = 1~nまでで、nがmで割り切れたらprint
            print(m)

print_divisor(72)
1
2
3
4
6
8
9
12
18
24
36
72
In [26]:
# 引数無しの関数
def greet():
    print("Good morning")

greet()
greet()
Good morning
Good morning

変数のスコープ

ここでは詳細まで解説しませんが、関数外にも同名の変数があるときに関数内で変数を上書きすると、基本的には外側の変数は書き換えられません。 これには変数のスコープが関係しており、関数内でglobal文でスコープを変更してやることで変数上書きの影響範囲を変えることができます。

In [27]:
# localスコープとglobalスコープの例

x = 10

def update_x():
    x = 100
    print("update_x: after overwriting", x)


def update_global_x():
    global x
    x = 100
    print("update_global_x: after overwriting", x)


print("outside:", x)
update_x()
print("outside:", x)
update_global_x()
print("outside:", x)
outside: 10
update_x: after overwriting 100
outside: 10
update_global_x: after overwriting 100
outside: 100

練習1-6

関数の使い方に慣れましょう。

  1. 引数をxとし、(x+5) / (x-5)を返す関数を定義しましょう。
  2. 様々なxについて、1.の関数の結果を見てみましょう。
  3. 引数をnとし、"Hello"をn回printする関数を定義しましょう。
  4. 3.の関数を好きなnについて呼び出しましょう。

追加で勉強するとよいこと

簡単にまとめるのみにとどめますが、必要に応じて使ってみたり勉強してみましょう。

  • タプル型: リストの友達。[ ]ではなく( )。要素を上書きできない。
  • 辞書型: リストの友達。番号で要素を指定する代わりに、文字列で要素を指定する。
  • 複素数型: 1 + 2j などのように表す。
  • break: forループから抜け出す
  • continue: forループのコードブロック途中で実行を打ち切り、次の要素に移る
  • enumerate: forループの配列指定で用いて、要素番号と要素を同時に与える
  • zip: forループの配列指定で用いて、複数の配列のn番目の要素を同時に与える
  • pass: 「なにもしない」コードブロックを作る方法。文法的に空白は許されないので、開発中に仮に入れておくことがある
  • while: forループと並ぶ、もう一つの繰り返し構文。while後に指定される条件が満たされている限り実行をくり返す
In [ ]: