Javaラーな僕がPythonで遊び始めたのでメモ。本当にただのメモ。
開発環境
Eclipseで開発環境ができる。Python用のPleiades All in Oneがあるので落としてくるといい。
プロジェクト作成
パッケージエクスプローラ 右クリック→「新規」→「プロジェクト」→「Pydevプロジェクト」で作れる。
Eclipse操作
パッケージ
Pythonにもパッケージという概念がある様子。
パッケージエクスプローラ 右クリック→「新規」→「Pydevパッケージ」で作れる。
pyファイル
Pythonのソースファイルはpyという拡張子のファイル
パッケージエクスプローラ 右クリック→「新規」→「Pydevモジュール」で作れる。
クラスやメイン(実行用)のテンプレートを選択できる。
実行
メインメソッド(?)のあるpyファイルを 右クリック→「実行」→「Python実行」
Python構文
メイン
javaでいうpubloc void main(String... args)
的なやつは下記のように記述する
if __name__ == '__main__':
print("I am a beginner")
コンソールにI am a beginner
とでる
EclipseからPydevモジュールの作成で「メイン」のテンプレートを選べば用意される
インデント
Pythonはインデントでブロックを定義する。
if __name__ == '__main__':
print("1")
if True:
print("2") # ifの中
print("3") # ifの中
else:
print("4") # elseの中
print("5") # elseの中
print("6") # ブロックを抜ける
と書くと、1、2、3、6と出力される
変数
代入すれば変数宣言と同じこと。
i = 1
s = "文字列"
b = True
条件式
論理演算子
and
,or
,not
を利用する
特殊な判定
Noneかどうか
objectを条件式で利用するとNoneのとき「偽」の扱いになる
o = None
if not o:
print("oはNoneです")
NoneはPythonのnull(みたいなもの)
文字列が空白かどうか
文字列を条件式で利用すると空白のとき「偽」の扱いになる
s = ""
if not s:
print("sは空白です")
0かどうか
数値を条件式で利用すると0のとき「偽」の扱いになる
i = 0
if not i:
print("iは0です")
配列が空かどうか
配列(等)を条件式で利用すると空のとき「偽」の扱いになる
a = []
if not a:
print("aは空です")
if・ループ
if
if文はすでに一部書いてしまったけど、下記のように記述する
if 条件1:
print("条件1は真")
elif 条件2:
print("条件1は偽")
print("条件2は真")
else:
print("条件1は偽")
print("条件2は偽")
else if
はelif
と書く。
for
for文は下記のように記述する。
for i in range(10):
print(i) # 0から9までが順番に出力される
for i in range(3, 7):
print(i) # 3から6までが順番に出力される
for i in range(1, 12, 2):
print(i) # 1,3,5,7,9,11が順番に出力される
for s in ["A", "B", "C"]:
print(s) # AとBとCが順番に出力される
Pythonのfor文はJavaの拡張for文のようなもの。
indexによるfor文や、脱出条件や、インクリメント数とかはrangeとかを使ってうまいことやる様子。
while
while文は今までの雰囲気で勘で書けば動く。あまりにも普通なので例は書かない。
なぜかwhile...elseという構文があるが使いどころがわからない。。。
switch-case
無い様子。
三項演算子
三項演算子という名前ではなく、「条件式」・「条件演算子」と説明されている。
for i in range(10):
a = "odd number" if i % 2 else "even number" # 「条件式」というやつ
print(str(i) + " is an " + a)
配列・イテレータ
list
javascriptのノリでインスタンスを生成する
items1 = []
items2 = ["A", "B"]
追加とか削除とか
items = ["A", "B"]
items.append("C") # JavaのList#add
items.extend(["D", "E", "F"]) # JavaのList#addAll
del items[4] # JavaのList#remove(int)
items.remove("F") # JavaのList#remove(Object)
size = len(items) # JavaのList#size
print("size:" + str(size)) # 4
index2 = items[2] # JavaのList#get
print("index2:" + index2) # C
idx = items.index(index2) # JavaのList#indexOf
print("idx:" + str(idx)) # 2
for item in items:
print(item) # A,B,C,Dを順番に出力
items2 = items[:] # コピーしたlistインスタンス生成
print(items2) # ['A', 'B', 'C', 'D'](itemsと同じ要素が入ってる)
print(items is items2) # False(別インスタンス)
items.insert(0, "INS") # JavaのList#add(int, Object)
print(items) # ['INS', 'A', 'B', 'C', 'D']
[:]
って?
items3 = items[1:3] # index 1から2を抽出したlist生成
print(items3) # ['B', 'C']
items4 = items[1:] # index 1から後ろ全部を抽出したlist生成
print(items4) # ['B', 'C', 'D']
items5 = items[:3] # index 3からより前全部を抽出したlist生成
print(items5) # ['A', 'B', 'C']
イテレータ
イテレータというか「iterable」という概念がある。JavaのIterableクラスと似てる。
「iterable」はPythonのfor文で回せる。
listも「iterable」だし、実はPythonの文字列(str)も「iterable」。
自作もできるようだけど今回は割愛。
tuple・dict・set
というのもある。
t = ("A") # tuple
print(type(t))
d = {"A" : 1} # dict
print(type(d))
s = {"A"} # set
print(type(s))
詳しいことは調べていない。下記参考
http://www.tohoho-web.com/python/list.html
文字列
基本
シングルクォートでもダブルクォートでも表現できる。
s1 = "I am a beginner"
s2 = 'I am a beginner'
どっちが一般的かはわからないけど探している感じはダブルクォートかな?
クォート3つなんて技もある。
s = """パイソンや
ああパイソンや
パイソンや"""
print(s)
結果
パイソンや
ああパイソンや
パイソンや
文字列連結
+
使う。
暗黙キャストはされないので次を利用。
文字列へのキャスト
str
を使う。
i = 10
print("数値を文字列に" + str(i))
print("文字列と数値を連結" + i) # エラー
自作クラスの文字列化
__str__
というメソッドを作成すると文字列化されるときに呼ばれる。
__str__
がJavaでいうtoStringメソッドの役割の雰囲気(直接は呼べない)。
メソッド
defと書いて定義する。
# メソッドはdefで定義する
def method1():
print("foo")
# 引数は括弧内に書いていく
def method2(arg1, arg2):
print(arg1)
print(arg2)
# 返り値はreturnで返す
def method3():
return "bar"
引数
いろいろな引数の渡し方
こだわらなければ普通に渡せばいいが、(Javaには無い)変わった渡し方もある。
def method2(arg1, arg2):
print("---")
print(arg1)
print(arg2)
if __name__ == '__main__':
method2("A", "B") # 普通の
method2(arg1="A", arg2="B") # こんな渡し方もできる(キーワード引数)
method2(arg2="B", arg1="A") # この場合順不同でもいいらしい
method2(*["A", "B"]) # 配列で渡す
method2(**{"arg2":"B", "arg1":"A"}) # dictで渡す
結果は全部一緒
デフォルト引数
C++とかにあるやつ。
# 引数はデフォルト値が定義できる callするとき引数が1つならarg2には"DefaultArg"が入る
def method4(arg1, arg2 = "DefaultArg"):
print("---")
print(arg1)
print(arg2)
if __name__ == '__main__':
method4("A", "B")
method4("A") # 2つ目の引数はdefaultを利用
結果
---
A
B
---
A
DefaultArg
dict渡しを前提にすれば第一引数にもデフォルト引数にできそうだがそれは無理っぽい
def method5(arg1 = "DefaultArg", arg2):
print(arg1)
print(arg2)
SyntaxErrorになる
可変長引数
tuple型で受け入れるやり方と、dict型で受け入れるやり方がある
tuple型の場合
# *を使うと、tuple型で受け入れる可変長引数
def method_variadic_tuple(arg1, *others): # othersはtuple型の可変長引数
print("---" )
print("第一引数:" + arg1)
print("可変長引数:" + str(others))
print("可変長引数の長さ:" + str(len(others)))
if __name__ == '__main__':
method_variadic_tuple("A")
method_variadic_tuple("A", "B")
method_variadic_tuple("A", "B", "C")
method_variadic_tuple("A", *("B", "C")) # 直接tupleで渡すことも可能
method_variadic_tuple("A", *["B", "C"]) # listもOK
method_variadic_tuple(*("A", "B", "C")) # 全部tuple渡しも可能
結果
---
第一引数:A
可変長引数:()
可変長引数の長さ:0
---
第一引数:A
可変長引数:('B',)
可変長引数の長さ:1
---
第一引数:A
可変長引数:('B', 'C')
可変長引数の長さ:2
---
第一引数:A
可変長引数:('B', 'C')
可変長引数の長さ:2
---
第一引数:A
可変長引数:('B', 'C')
可変長引数の長さ:2
---
第一引数:A
可変長引数:('B', 'C')
可変長引数の長さ:2
dict型の場合
# **を使うと、dict型で受け入れる可変長引数
def method_variadic_dict(arg1, **others): # othersはdict型の可変長引数
print("---" )
print("第一引数:" + arg1)
print("可変長引数:" + str(others))
print("可変長引数の長さ:" + str(len(others)))
if __name__ == '__main__':
method_variadic_dict("A")
method_variadic_dict("A", d1="B") # dict可変長引数はこのように渡す
method_variadic_dict("A", d1="B", d2="C")
method_variadic_dict(arg1="A", d1="B", d2="C") # dict型を使うなら第一引数も=使った表記のほうがきれい
method_variadic_dict(d1="B", arg1="A", d2="C") # この場合、第一引数は真ん中でもOK
method_variadic_dict("A", **{"d1":"B", "d2":"C"}) # 直接dictで渡すことも可能
method_variadic_dict(**{"arg1":"A" , "d1":"B", "d2":"C"}) # 第一引数もdictにできる。
# method_variadic_dict(*["A", {"d1":"B", "d2":"C"}]) # 配列渡しはさすがに無理かな?
結果
---
第一引数:A
可変長引数:{}
可変長引数の長さ:0
---
第一引数:A
可変長引数:{'d1': 'B'}
可変長引数の長さ:1
---
第一引数:A
可変長引数:{'d1': 'B', 'd2': 'C'}
可変長引数の長さ:2
---
第一引数:A
可変長引数:{'d1': 'B', 'd2': 'C'}
可変長引数の長さ:2
---
第一引数:A
可変長引数:{'d1': 'B', 'd2': 'C'}
可変長引数の長さ:2
---
第一引数:A
可変長引数:{'d1': 'B', 'd2': 'C'}
可変長引数の長さ:2
---
第一引数:A
可変長引数:{'d1': 'B', 'd2': 'C'}
可変長引数の長さ:2
クラス
定義
class クラス名(継承元)
という宣言をする。
Eclipseのテンプレートを使えば下記のように書いてくれる。
class MyClass(object):
'''
classdocs
'''
def __init__(self, params):
'''
Constructor
'''
__init__
すでにコメント(docstring)があるのでわかるが、コンストラクタは__init__
と書いて定義する。
引数のself
は自分のインスタンスで、後ろにコンストラクタで受け入れたいパラメータを書いていく。
インスタンス生成
if __name__ == '__main__':
obj = MyClass("param") # 引数"param"でMyClassを生成してobjに代入
インスタンス フィールド変数・メソッド
フィールド変数はインスタンス内部からの場合、self.フィールド名
で代入すれば変数ができる。
外からの場合は普通にインスタンスを格納している変数.フィールド名
で代入する。
メソッドはクラスに合わせてインデントしてdef
で定義する。
(__init__
と同じく)第一引数はself
になる。
外から、呼び出しの際はself
を抜いた引数を与えて呼び出す。
class MyClass(object):
def __init__(self, param):
self.field1 = "field1" # self.フィールド名に代入すればそれがフィールド変数になる
print("init param:" + param)
def foo(self, param): # インスタンスメソッド
self.field2 = "field2" # フィールド変数はいつでも作れる
print("foo param:" + param)
if __name__ == '__main__':
obj = MyClass("A")
print(obj.field1)
obj.foo("B")
print(obj.field2)
obj.field3 = "field3" # 何なら外からでもフィールド変数を作れる
print(obj.field3)
結果
init param:A
field1
foo param:B
field2
field3
スコープ
名前の付け方で表現する。
参考:
http://docs.python.jp/3.5/reference/lexical_analysis.html#reserved-classes-of-identifiers
http://docs.python.jp/3.5/tutorial/classes.html#tut-private
アンダースコアを頭に2つ付ければprivateになる。
(厳密に言えばアクセスする方法はあるのでprivateとは言い切れないかもしれない。)
ただし、__hoge__
というような後ろにもアンダースコアが2つある名前はPythonのシステム用なので勝手に新しくつけたらダメ。
また、習慣としてアンダースコア1つは非publicとするらしい。
class MyClass(object):
def foo(self): # public
print("foo" )
def _foo(self): # 習慣としての非public
print("_foo" )
def __foo(self): # private
print("__foo" )
def call_private_foo(self): # __fooを呼び出すためのメソッド
self.__foo() # privateのメソッドが呼び出せる
if __name__ == '__main__':
obj = MyClass()
obj.foo()
obj._foo()
# obj.__foo() # 呼び出し不可
obj.call_private_foo()
obj._MyClass__foo() # 厳密に言えばアクセスする方法はある。「_クラス名+メソッド名」に置き換えられている。ただしEclipseの保管には出てこない
結果
foo
_foo
__foo
__foo
継承
(object)
と書いてある部分を継承したいクラスに変えればとりあえず継承はできる。
多重継承もできるらしいが、初心者の僕は使いこなせる気がしないので今回は割愛。
親クラスのメソッドを呼び出す
ただ継承しただけでは親クラスのコンストラクタは呼ばれない。
下記のようにsuper(自クラス, self).メソッド名()
と記載して呼び出す。
class AbsMyClass(object):
def __init__(self):
print("AbsMyClass__init__が呼ばれた")
class MyClass(AbsMyClass):
def __init__(self):
super(MyClass, self).__init__() # 継承元の__init__を呼び出す
print("MyClass__init__が呼ばれた")
if __name__ == '__main__':
obj = MyClass()
結果
AbsMyClass__init__が呼ばれた
MyClass__init__が呼ばれた
何なら親クラスの__init__
を呼び出さないこともできるし、タイミングも任意だし、何度でも呼べるし自由度がハンパない。
Pythonにまだ慣れない僕は、しょっちゅう書くのを忘れてしょっちゅうハマってる。
インポート
Eclipseが補完して書いてくれる。
構文については割愛。
Python初心者メモ(その2)を書きました。