Pythonの言語学習におけるメモを残す。
主にC言語との違いが多い。
メソッドと関数の違いは、主に「.」(ドット)の有無。
「.」(ドット)は、助詞の「の」と読み替えることができる。
○○.△△ → ○○ の △△を実行する
関数名(引数)
・メソッド
データ.メソッド名(引数)
Pythonにあらかじめ備わっているメソッドの例。
大文字、小文字に変換した文字を出力するメソッド。
メソッドは戻り値として出力するだけなので、コールしただけでは変数のデータは変更されない。(非破壊的メソッド)
>>> a = "Text"
>>> print(a)
Text
>>> a.lower()
'text'
>>> print(a)
Text
>>> a.upper()
'TEXT'
>>> print(a)
Text
>>> a = a.upper()
>>> print(a)
TEXT
制御構造(分岐やループ)に関する内容。
Pythonはインデントも制御構造の仕組みの一つとなっている。
C言語がブレースでスコープを区切るのに対し、Pythonではインデントでスコープを区切っている。
以下のコードは、エラーが発生しない正常なコードである。
score = int(input("点数を入力してください:"))
if score >= 60:
print("合格です")
print("おめでとうございます!")
print("処理を終了します")
if文のあとには、条件を満たした場合に実行する字下げされた命令が必要となる。
字下げをしなかった場合のコードを実行してみる。
score = int(input("点数を入力してください:"))
if score >= 60:
print("合格です")
print("おめでとうございます!")
print("処理を終了します")
字下げをしなかった場合はエラー(Indentationerror)になる。
File "<ipython-input-13-31fa8ffec306>", line 3
print("合格です")
^
IndentationError: expected an indented block
また、字下げのレベルが不適切な場合もエラーになる。
たとえば、以下のコードのprint("おめでとうございます!")
のインデントを、if文でもそれ以外でもないインデントにしてみる。
score = int(input("点数を入力してください:"))
if score >= 60:
print("合格です")
print("おめでとうございます!")
print("処理を終了します")
すると、どこにも当てはまらないインデントレベルの処理がエラーとなる。
File "<tokenize>", line 4
print("おめでとうございます!")
^
IndentationError: unindent does not match any outer indentation level
これについては、逐次処理においても同様である。
print("合格です")
print("おめでとうございます!")
print("ありがとうございます?")
やはり、インデントの必要がないところでインデントした命令がエラーとなる。
File "<ipython-input-12-91a21539abf4>", line 2
print("おめでとうございます!")
^
IndentationError: unexpected indent
if文における注意点
C言語ではelse if ~
であったが、Pythonはelif ~
となる。(プリプロセスみたい)
こんな感じ。
season = input("季節を入力してください:")
if season == "春":
print("春はあけぼの")
elif season == "夏":
print("夏は夜")
elif season == "秋":
print("秋は夕暮れ")
elif season == "冬":
print("冬はつとめて")
else:
print("エラー")
print("処理を終了します")
else if ~
と書くとエラーになってしまう。
season = input("季節を入力してください:")
if season == "春":
print("春はあけぼの")
elif season == "夏":
print("夏は夜")
elif season == "秋":
print("秋は夕暮れ")
else if season == "冬":
print("冬はつとめて")
else:
print("エラー")
print("処理を終了します")
実行結果:
File "<ipython-input-31-ec4d3fac25a4>", line 9
else if season == "冬":
^
SyntaxError: invalid syntax
繰り返し構造のうち、for文について説明する。
in は、その後ろに続く要素から1件ずつ取り出して変数に格納する。
例えば、数字が並んでいる場合。
for i in 0, 1, 2:
print(i)
数字を1つずつ、iに代入して繰り返している。
0
1
2
また、数字の列挙であればrange()
が便利である。
ただし、range()
は単体で数字の列挙を出力する関数というわけではないので注意。
for i in range(5):
print(i)
引数が1つの場合、range()
は0から引数で指定された数値までを列挙する。
また、forループはrange()
で列挙された数値をすべて使用するまで繰り返される。
0
1
2
3
4
引数が2つの場合、第1引数の数値から、第2引数未満の数値を列挙する。
for i in range(3, 5):
print(i)
この場合、列挙する範囲は「3以上5未満」である。
3
4
引数が3つの場合、1つめと2つめは同様で、3つめは増分を示す。
for i in range(1, 5, 2):
print(i)
この場合、列挙する範囲は「3以上5未満で増分2」である。
1
3
また、増分を負の数(デクリメント方向)にすることも可能(範囲指定に注意)。
for i in range(5, 1, -2):
print(i)
この場合、列挙する範囲は「5以下1より大きく増分-2」である。
5
3
「例外」が発生した場合に対応するための制御文。
実行エラー(例外)が発生すると、プログラムは処理を終了してしまう。
しかし、try文を用いることで、上記エラーが発生しても処理を継続することができる。(try文が終了したあとの処理も)
ざっくり以下のとおりである。
try:
エラー有無の条件となる処理
except エラー名:
指定したエラーが発生に対する処理
except:
それ以外のエラーに対する処理
else:
エラー未発生時の処理
finally:
エラー有無に関わらず必ず実行する処理
エラー有無の条件となる処理の例:
score = int(input("数値を入力してください:"))
キーボードから数値以外が入力されると、キャストに失敗し、実行エラー(例外)が発生する。
指定のエラーの例:
except ValueError:
print("エラー:数値を入力してください")
値に関するエラーであるValueErrorなどがある。
参考:https://www.sejuku.net/blog/72383
except:
よりも前に記述しないと、先に左記に当てはまって実行されないので注意すること。
配列に近いが、それ以上の役割がある。
参考:https://techacademy.jp/magazine/19204
文字列のうち、特定の文字や文字列を取り出す操作をスライスという。
実際に文字列を用意して、スライスしてみる。
s = "abcdefghijklmnopqrstuvwxyz"
print(s[0])
print(s[1])
print(s[2])
C言語でいう配列と同じ要領で扱われる。
a
b
c
ただし、文字列の持つ領域を超えるとIndexError(インデックスエラー)となる。
print(s[25])
print(s[26])
文字数は26字であったため、27番目(s[27]
)をスライスするとエラーとなる。
z
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-6-7ba20cf8c27e> in <module>
1 print(s[25])
----> 2 print(s[26])
IndexError: string index out of range
C言語は配列の変数にインデックスを付けたものは単なる簡便法であり、変数の持つ領域を超えてもアクセスは可能である。
これに対してPythonのように領域を超えた場合にエラーとなるのはバグを防ぐのに有効である。つまり優秀。
マイナスにすると末端から順にアクセスできる。
この辺はスーパーマリオの感覚。(左端は右端とつながっている)
ただし、負方向も存在しない領域にアクセスするとインデックスエラーとなるので注意。
print(s[0])
print(s[-1])
print(s[-2])
print(s[-26])
print(s[-27])
print(s[-28])
a
z
y
a
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-8-6bd2365f764f> in <module>
3 print(s[-2])
4 print(s[-26])
----> 5 print(s[-27])
6 print(s[-28])
IndexError: string index out of range
一部の文字列をスライスする場合は、以下のように記述する。
文字列変数名[開始位置:終了位置]
このとき、取り出される文字列の位置は 開始位置 から 終了位置 - 1 である。(終了位置が紛らわしいけど)
このあたりは range()
と同じ要領。
print(s[0:7])
print(s[7:14])
print(s[14:7])
print(s[-5:-1])
print(s[-1:-5])
ただし、開始位置と終了位置の大小関係を間違えると、文字列はスライスされないため注意。
正の数、負の数のいずれも、取り出せる方向は同じ(左から右)であると考えれば良い。
abcdefg
hijklmn
vwxy
また、開始位置や終了位置は省略が可能。
このときも、文字列を取り出す方向は同じであることをイメージすること。
print(s[:10])
print(s[10:])
print(s[-5:])
print(s[:-20])
abcdefghij
klmnopqrstuvwxyz
vwxyz
abcdef
開始位置と終了位置の両方を省略すると、すべての文字列が出力される。
print(s[:])
abcdefghijklmnopqrstuvwxyz
増分を指定することで、「何個おきに」取り出すといった操作ができるようになる。
print(s[0:10:2])
print(s[1:20:3])
acegi
behknqt
なんと、増分を負方向に指定することで、逆方向の取り出しが可能。
print(s[-1:-6:-1])
print(s[-1:-10:-2])
zyxwv
zxvtr
増分を指定する記法の場合も、開始位置・終了位置・増分量の省略が可能である。
print(s[::-1])
print(s[::])
zyxwvutsrqponmlkjihgfedcba
abcdefghijklmnopqrstuvwxyz
シーケンスと似ているけど、違うもの。
この辺も見とくと良い:
https://docs.python.org/ja/3.8/tutorial/datastructures.html#more-on-lists
リスト型の変数の値は [ と ] で囲んで表現される。
a = [2, 3, 4]
print(type(a))
print(a)
どうやらリスト型というものがあるらしく、[ と ] を使って表現される。
<class 'list'>
[2, 3, 4]
数値と文字(文字列)の混在もできるみたいだが、明確な意図がない限りは 数値だけ、文字列だけ、のように1種類のみで要素を構成させることが推奨されるらしい。
b = [3, "test", 7, "hoge", "fuga", 10]
print(b)
[3, 'test', 7, 'hoge', 'fuga', 10]
空のリストも作成できる。(メリットがあるかはしらんけど)
c = []
print(c)
[]
シーケンスを使用してリスト変数を作成する場合は、list()を使うと楽みたい。
d = list("Test")
e = list(range(3))
print(d)
print(e)
文字列やrange()がシーケンスであることは「シーケンス」の章を参照。
['T', 'e', 's', 't']
[0, 1, 2]
シーケンスのスライスと同様に、リストも要素を取り出すことをスライスするという。
リスト変数内の要素の取り出しかた(アクセス方法)は、シーケンスの場合と同様である。
リスト変数名[番号]
リスト変数名[開始位置:終了位置]
リスト変数名[開始位置:終了位置:増分]
こんなかんじ。
b = [3, "test", 7, "hoge", "fuga", 10]
b[0:5:2]
[3, 7, 'fuga']
ただし、空のリストには要素がないため、スライスはできない。
c = []
c[]
File "<ipython-input-36-763d39ca79da>", line 2
c[]
^
SyntaxError: invalid syntax
リスト作成時に、制御文を組み合わせることができる。
for文を使ってリストを作成することができる。
list1 = [i for i in range(11)]
list2 = [(i * 2) for i in range(11)]
print(list1)
print(list2)
for i in range(11)
で繰り返すときのi
の値を作成し、i
または(i * 2)
に代入したものを要素としてリストを作成している。
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
for文とif文を組み合わせたリスト作成も可能。
if文はfor文よりも後に記述すること。
list3 = [i for i in range(11) if i % 3 == 0]
list4 = [i for i in range(11) if i % 2 == 0 and i % 3 == 0]
print(list3)
print(list4)
for文の繰り返しに対し、if文の条件を満たす場合だけ、最初の式i
に代入してリストを作成する処理である。
論理演算式も使用できる。
[0, 3, 6, 9]
[0, 6]
if-else文を使用する場合だけ特殊で、for文よりも前に書く必要がある。
list5 = ["even" if i % 2 == 0 else "odd" for i in range(11)]
print(list5)
条件を満たす場合はeven
、そうでないときはodd
であり、for文の条件に従って繰り返す。
['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even']
elif
は内包することができない。
3つ以上の条件を指定する場合は、以下のような書き方となる。
list6 = ["low" if i < 3 else "mid" if i < 8 else "hi" for i in range(11)]
print(list6)
['low', 'low', 'low', 'mid', 'mid', 'mid', 'mid', 'mid', 'hi', 'hi', 'hi']~~~~
リストは作りっぱなしじゃなく、データの変更が可能。
CRUDは、以下の言葉からなる。
リストの最後尾に要素を追加するには、リストがもつメソッドのひとつappend()
を使う。
参考:https://www.tech-teacher.jp/blog/python-append/
リストの途中に要素を追加するには、insert()
メソッドを使う。
参考:https://techacademy.jp/magazine/22300
リストを結合する場合は、+
や+=
を使う。
繰り返しの場合は、*
や*=
を使う。
このあたりは、文字列の結合や繰り返しと同じイメージ。
参考:https://techacademy.jp/magazine/29364
参考:https://www.javadrive.jp/python/list/index6.html#section5
要素を参照する方法として、以下の2つがある。
スライスを使用して、要素を上書きします。(専用のメソッドはない)
詳細な手順は省略。
リストの要素は以下の方法で削除できる。(いずれも破壊的メソッド)
pop()
メソッドを使用
引数なし:一番最後の要素を削除し、メソッドの戻り値として出力する。
引数あり:指定した要素の削除と出力を行う。(もちろん0から開始)
clear()
メソッドを使用
すべての要素を削除します。メソッドの戻り値はなし。
リストの中に指定の文字があるかどうかなどを調べる。
探索の仕方として、count()
メソッド、index()
メソッド、in
がある。
参考:https://techacademy.jp/magazine/18930
並び替えはsort()
メソッド、reverse()
メソッドが簡単。(破壊的メソッド)
非破壊的にリストを扱うにはsorted()
関数を使用すること。
C言語の2次元配列と同じように考えてよい。
C言語でいう{ }
は、Pythonでは[ ]
で表現される。
行、列といったスコープ概念も、C言語とPythonで同じである。
★「行、列」と覚えるよりも、シンタックスのスコープ順で参照する認識にしておいたほうが、多次元配列において理解がしやすい。
append()
メソッドの引数をリスト型のデータにすれば、二次元配列としてリスト要素が追加されていく。
また、C言語と違って要素数の異なるリストを扱うことができる。
型を変更できないリストのようなもの。
スライスしてアクセスする場合にその効果が発揮されるのかも。
リスト:[ ]
で囲む
タプル:( )
で囲む
ただし、要素数が1つの場合は注意が必要。
a = (1) # int型
a = (1,) # tuple型
リストではlist()
を使っていたが、タプルではtuple()
を使う。
引数はシーケンス(同じ)。
リストと同様、スライスを使う。
要素の追加・消去などはできないが、値を代入して変数の値を変更することは可能。
値の代入については、タプル型の値を代入するとその値で上書きが可能であるが、スライスによる代入はエラーとなる。
a = (0, 1, 2, 3, 4)
print(a)
a = (0, 3, 5)
print(a)
a[0] = 10
(0, 1, 2, 3, 4)
(0, 3, 5)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-12-5072b42910db> in <module>
4 print(a)
5
----> 6 a[0] = 10
TypeError: 'tuple' object does not support item assignment
リストと同様にcount()
、index()
、in
が使用可能。
複数のリストから1つのタプルを作成する。
戻り値はタプル型。
行と列の関係が特殊なので注意。(単なる連結ではない)
そのリストがタプル型になるみたい。(タプルを格納したリスト)
構造的には以下のような感じ。
[ ( ), ( ), ( )]
リストを引数に、タプルを格納したリストを生成することができるみたい。
変数等のオブジェクトにはIDが割り振られている。
これはC言語のような変数自体を識別するものではなく、値の識別と考えたほうが良い。
値が同じ変数は、異なる変数でもあっても同じIDとなる。
ただし、タプルは同じ要素であったとしても異なるIDを持つ。
調べ方:
id(オブジェクト名)
オブジェクトの値の重複は、オブジェクトのハッシュ値で判断される。
オブジェクトが異なるものでも、中身のデータが完全に一致していれば同じハッシュ値になる 。
調べ方:
hash(オブジェクト名)
セット変数を作成する際に、set()
に同じ値のタプルを引数にした場合には、作成される要素は一つとなる。
このときになぜ異なるIDであるのに同じ値であるかを判断できるかというと、ハッシュ値で判断されていたから。
ハッシュ値はデータの値に応じて決まるもので、タプルであっても同じ値であれば、同じハッシュ値を持つ。
2つの変数を比較する場合、==
とis
で比較結果が異なる場合がある。
演算子 | 比較する値 | 比較の内容 |
---|---|---|
== | ハッシュ値 | データが同じかどうか |
is | ID | 同じオブジェクトかどうか |
オブジェクトと値は異なる存在であると認識したほうが良いのかも。(確認すること)
インデックス(数字)ではなく、キー名(要素につける名前)を指定してアクセスする。
要素はキー:値
で記述し、{ }
で囲む。
キー名は文字列以外にも、数字で定義しても良い。
d = {"foo": 1, "foo": 3, "bar": 5, "hoge": 7}
print(d)
キーが重複する場合、そのキーの値は上書きされてしまうことに注意すること。
{'foo': 3, 'bar': 5, 'hoge': 7}
タプルも要素として定義できるみたい。
タプルは、要素の値が変化しないからである。
一方、値が変化するリストはキーにすることができない。
以下の形式で記述することで、要素を追加することができる。
変数[キー] = 値
例えばこんなかんじ。
dic={}
print(type(dic))
print(dic)
dic["test"] = 1
dic["hoge"] = "hogege"
dic[5] = "日本語"
print(type(dic))
print(dic)
dic["test"] = "OK"
print(dic)
定義済みのキーがある場合は、上書きされる。
<class 'dict'>
{}
<class 'dict'>
{'test': 1, 'hoge': 'hogege', 5: '日本語'}
{'test': 'OK', 'hoge': 'hogege', 5: '日本語'}
2つの方法がある。
どちらにするかは、例外処理の要否で決めれば良い。
キーがタプルの場合も、タプルを渡せばよい。
print(dic["hoge"])
print(dic["super"])
キーが存在しない場合は「KeyError」となる。
hogege
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-5-0cb8b3fad786> in <module>
1 print(dic["hoge"])
----> 2 print(dic["super"])
KeyError: 'super'
get()
メソッドprint(dic.get("hoge"))
print(dic.get("fuga"))
キーが存在しない場合には何も起こらず、エラーにもならない。(print()
ではNone
と出力される)
hogege
None
2つの方法がある。
pop()
メソッド引数にキーを渡すこと。
dic={}
dic["test"] = 1
dic["hoge"] = "hogege"
dic[5] = "日本語"
print(dic)
dic_p = dic.pop("hoge")
print(dic_p)
print(dic)
{'test': 1, 'hoge': 'hogege', 5: '日本語'}
hogege
{'test': 1, 5: '日本語'}
引数を渡さなかった場合は、TypeErrorとなる。
dic_p = dic.pop()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-12-040e53f5bd46> in <module>
----> 1 dic_p = dic.pop()
TypeError: pop expected at least 1 argument, got 0
clear()
メソッド他の型と同じで、すべての要素をクリアする。
dic={}
dic["test"] = 1
dic["hoge"] = "hogege"
dic[5] = "日本語"
print(dic)
dic.clear()
print(dic)
{'test': 1, 'hoge': 'hogege', 5: '日本語'}
{}
in
を使用する。(省略)
辞書型には以下のメソッドがある。(詳細は省略)
keys()
values()
items()
これらのメソッドは、返し値をシーケンスとして扱うことができる。
dic = {'Hokkaido': 1, 'Aomori': 2, 'Tokyo': 13, 'Osaka': 27}
print(dic.items())
for key, value in dic.items():
print(f"{key} : {value}")
dic.items()
では、各要素をタプルとして出力している。
そのため、forで使用する場合は、タプルの形式と合うように2つの変数を用いていることに注意する。
dict_items([('Hokkaido', 1), ('Aomori', 2), ('Tokyo', 13), ('Osaka', 27)])
Hokkaido : 1
Aomori : 2
Tokyo : 13
Osaka : 27
ファイルの先頭でインポートする。
ただし、拡張子までは必要なく、ファイル名.py
をインクルードする場合は、以下のとおりでよい。
import ファイル名
C言語はソース(.c)とヘッダ(.h)が存在するが、この時点でPythonは「*.pyのみ」と考えてよい。
ファイルをインポートした場合、インポートしたファイルはオブジェクトとして扱われる。
つまり、以下のように扱われる。
* ファイル → オブジェクト
* 関数 → メソッド
C言語とは勝手が異なるので、このあたりは気をつけること。
他のファイルの関数をメソッドではなく、関数として扱う場合は、以下の記述でインポートする。
from ファイル名 import 関数名
メソッドではなくなるため、関数コールを直接記述することができる。
インポートしたオブジェクトやメソッド、関数の名称が長い場合や、可読性が低い場合に有効。
インポート文のあとに、as 別名
を加えることで、インポートしたものを別名で扱うことができる。
import ファイル名 as 別名 # オブジェクトを別名で読み替え(メソッド名はそのまま)
from ファイル名 import 関数名 # 関数を別名で読み替え
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント