pythonメモ

python書くときの自分用メモ。
主に以下のページで勉強した際のもの。
http://www.tohoho-web.com/python/index.html

```python:python.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-

#以下参照
#  http://docs.python.jp/3/library/functions.html
#  http://www.tohoho-web.com/python/index.html
#  http://docs.python.jp/3.5/


print("pythonでは先頭に文字コードを書かないとエラーになるらしい")


"""
複数行コメント
本来は文字列リテラルだが、コメントとしても使われるらしい
"""


print("\n\n----------")
print("○importとprint")
import random
num = random.randint(1,10)
print("numは"+str(num))


print("\n\n----------")
print("○if文")
if num == 1:
    print("numは1だよ")
elif num < 5:
    print("numは5以下だよ")
else:
    print("その他だよ")


print("\n\n----------")
print("○while文")
n = 0
while n < 3:
    print("while "+str(n))
    n += 1
else:
    print('while END')
print("while文にelseを書くと、whileの条件に合致しなくなって抜けた場合にelseが実行されます。")
print("最初から条件に合わない場合も実行されます。")
print("break等で抜けた場合は実行されません。")


print("\n\n----------")
print("○for文")
for n in [1, 2, 3]:
    print(n)                 # => 1, 2, 3
else:
    print("END")
for n in (1, 2, 3):
    print(n)                 # => 1, 2, 3
for k,v in {'one': 1, 'two': 2, 'three': 3}.items():
    print(str(k)+":"+str(v)) # => one:1, two:2, three:3
for c in "123":
    print(c)                 # => 1, 2, 3
for line in open("data.txt"):
    print(line)              # => 1行ずつ表示
for n in range(3,6):
    print(n)                 # => 3, 4, 5
for c in 'あいうえお':
    print(c)                 # => あ, い, う, え, お

print("for文にもelseを書くことが出来ます。")
print("意味はwhileと同じです。")
for x in range(2, n):
    if n % x == 0:
        print(n, 'equals', x, '*', n//x)
        break
else:
    # loop fell through without finding a factor
    print(n, 'is a prime number')


print("\n\n----------")
print("○printfっぽい方法")
errmsg = "文字列"
errcode = 12
msg = "文字列を作る段階でprintfっぽいことができます [%s] (%d)" % (errmsg, errcode)
print(msg)
print("%(name)s is %(age)d years old." % {'age': 28, 'name': "Tanaka"})


print("\n\n----------")
print("○リストとfor文")
a = [1, 2, "AAA", 4, (1+3j)*(2+2j)]
print('0から数えて3番目は'+str(a[3])) # => 4
print("1から2番目(3番は含まず)はスライスを使って"+str(a[1:3])) # => [2, 'AAA']
print("開始や終了を省略できます。2番目までは"+str(a[:3])) # => [1, 2, 'AAA']
print("負の値も使えます。後ろから2番目まで(ただし2番目自体は含まない)は"+str(a[:-2])) # => [1, 2, 'AAA']
print("刻み幅(ステップ)も変えられます"+str(a[0:1:2])) # => [1, 'AAA']
print("刻み幅も負の値が使えます"+str(a[::-1])) # => [(-4+8j), 4, 'AAA', 2, 1]

print("値も変えられます")
print("  変更前:"+str(a)) # => [1, 2, 'AAA', 4, (-4+8j)]
a[1]=999
print("  変更後:"+str(a)) # => [1, 999, 'AAA', 4, (-4+8j)]
print("追加もできます。")
a.append(777)
print("  変更後:"+str(a)) # => [1, 999, 'AAA', 4, (-4+8j), 777]

for n in a:
    print("[for文]"+str(n)+"だよ")

print("list結合" + str([1, 2, 3] + [4, 5, 6])) # => [1, 2, 3, 4, 5, 6]
print("len()で長さを求めます"+str(len([1, 2, 3]))) # => 3

a = [[1, 2], [3, 4], [5, 6]]
a.append([7,8])
print("多重リストもOK"+str(a)) # => [[1, 2], [3, 4], [5, 6], [7, 8]]
for line in a:
    for n in line:
        print(str(n)+" ", end="")
    print("") # => 1 2
              #    3 4
              #    5 6
              #    7 8
print("a[2][1]は"+str(a[2][1])) # => 6


print("\n\n----------")
print("○タプル")
a = (11,22,33,)
print("リストの固定値版のタプルというものがあります"+str(a))
print("0から数えて1番め"+str(a[1])) # => 22
#a[1]=12 # => エラー


print("\n\n----------")
print("○辞書")
d = {'Yamada': 30, 'Suzuki': 40, 'Tanaka': 80}
print("辞書(連想配列)もあります"+str(d))
print("Yamadaは"+str(d["Yamada"]))
for key,val in d.items():
    print("[for文]"+key+"は"+str(val))


print("\n\n----------")
print("○関数")
def doublefunc(x):
    return x * 2
print("7をdoublefuncにかけると"+str(doublefunc(7))) # => 14
a = [1, 2, 3]
print(str(a)+"をdoublefuncにかけると"+str(doublefunc(a))) # => [1, 2, 3, 1, 2, 3]


print("\n\n----------")
print("○map")
print("mapは各要素をそれぞれ処理した結果を返します")

print("・関数方式")
print(map(doublefunc, a))       # => map object
print(list(map(doublefunc, a))) # => [2, 4, 6]

print("・lambda方式")
print(map(lambda x: x * 2, a))       # => map object
print(list(map(lambda x: x * 2, a))) # => [2, 4, 6]

print("・内包表記")
print([x * 2 for x in a]) # => [2, 4, 6]

print("○filter")
print("filterは各要素をそれぞれ処理して、真なものだけ返します")
a = [1, 2, 3]
def kisuucheck(x): return x % 2
print("・関数方式")
print(filter(kisuucheck, a)) # => filter object
print("奇数のものは"+str(list(filter(kisuucheck, a)))) # => [1, 3]
print("・lambda方式と内包表記は省略")


print("○reduce")
print("reduceは1つ目と2つ目の要素を処理し、その結果と3つ目を処理し…と繰り返す")
print("でもあまり使われないからかpython3ではimportしてからでないと使えません")
from functools import reduce
a = [1, 2, 3, 4, 5]
def add(x, y): return x + y
print(reduce(add, a))                # => 15 : 関数方式
print(reduce(lambda x, y: x + y, a)) # => 15 : lambda方式

print("○内包表記")
a = [1, 2, 3]
print([x * 2 for x in a])           # => [2, 4, 6]
print([x * 2 for x in a if x%2==1]) # => [2,6]
print([[x, x * 2] for x in a])      # => [[1, 2], [2, 4], [3, 6]]
print([(x, x * 2) for x in a])      # => [(1, 2), (2, 4), (3, 6)]
a = [[1, 2], [3, 4], [5, 6]]
print([[x[0]*2,x[1]*3] for x in a]) # => [[2, 6], [6, 12], [10, 18]]

print("○セット")
print("セット(set)は重複の無いリストです")
a = set(['red', 'blue', 'green'])
b = set(['green', 'yellow', 'white'])
print("set aは"+str(a))                    # => set(['red', 'blue', 'green'])
print("set bは"+str(b))                    # => set(['green', 'yellow', 'white'])
print("a-bは"+str(a-b))                    # => set(['red', 'blue'])
print("a|bは"+str(a|b))                    # => set(['red', 'blue', 'green', 'yellow', 'white'])
print("a&bは"+str(a&b))                    # => set(['green'])
print("a^bは"+str(a^b))                    # => set(['red', 'blue', 'yellow', 'white'])
print("'green' in aは"+str('green' in a))  # => True
a.add('black')
print("aにblackを追加したら"+str(a))       # => set(['red', 'blue', 'green', 'black'])
a.add('black')
print("さらにaにblackを追加したら"+str(a)) # => set(['red', 'blue', 'green', 'black'])


print("\n\n----------")
print("○予約後とか組み込み関数名は上書きできてしまうので注意")
print("list([1,2])は"+str(list([1,2]))) # => [1,2]
list_temp = list
list = doublefunc
print("list([1,2])は"+str(list([1,2]))) # => [1,2,1,2]
list = list_temp
print("list([1,2])は"+str(list([1,2]))) # => [1,2]


print("\n\n----------")
print("○例外処理")

mystring = 'ABC'
try:
    c = mystring[5]                    # 5番目の文字が無いので、IndexError例外が発生します
except IOError:
    print('IOError')              # IOError例外の場合、このブロックが実行されます
except IndexError:
    print('IndexError')           # IndexError例外の場合、このブロックが実行されます
except:
    print('Unknown')              # 上記以外の例外の場合、このブロックが実行されます
else:
    print('Error not occur')      # 例外が発生しなかった場合、このブロックが実行されます
finally:
    print('Finally')              # 常に、このブロックが実行されます

try:
    f = open('sample.txt', 'r')
except:
    print('cannot open sample.txt')
else:
    lines = f.readlines()

try:
    raise SystemError("Sorry, my fault!")
except SystemError as e:
    print("SystemError")
    print(e)


print("\n\n----------")
print("○with")
print("with内で処理をするとオブジェクトの終了処理を自動で行ってくれる")
# withを用いない書き方
f = open("data.txt")
print(f.read())
f.close()

# withを用いた書き方1
with open("data.txt") as f:
    print(f.read())

# withを用いた書き方2
f = open("data.txt")
with f:
    print(f.read())


print("\n\n----------")
print("○pass")
print("passは何もしません 空の関数を作る時などに使います")
def myfunc():
    pass
class MyClass:
    pass


print("\n\n----------")
print("○del")
print("delはオブジェクトを削除します")
x = 5
y = [1, 2, 3]
z = MyClass()
del x, y, z


print("\n\n----------")
print("○printでファイルに出力")
f = open("gomi.txt", "a")
print("Hello world!", file=f)
f.close()


print("\n\n----------")
print("○exec")
print("execで文字列を実行できます")
exec("print('hello')")


print("\n\n----------")
print("○関数")
print("関数の引数は名前指定で渡すことも出来ます")
print("また、引数のデフォルトの値も決められます")
def repeat_msg(msg, repeat=2, a=1):
    for i in range(repeat):
        print(msg+" a="+str(a))
repeat_msg('Hello')      # => Hello a=1, Hello a=1
repeat_msg('Yahho', a=5) # => Yahho a=5, Yahho a=5

print("c言語のargvみたいなことも出来ます")
def func(a1, a2, *args, **params):
    print(a1)        # => A
    print(a2)        # => B
    print(args)      # => ('C', 'D')
    print(params)    # => {'k1': 'K1', 'k2': 'K2'}
func('A', 'B', 'C', 'D', k1='K1', k2='K2')

args = ('C', 'D')
params = {'k1': 'K1', 'k2': 'K2'}
func('A', 'B', args, params)     # => A, B, (('C', 'D'), {'k2': 'K2', 'k1': 'K1'}), {}
func('A', 'B', *args, **params)  # => A, B, ('C', 'D'), {'k1': 'K1', 'k2': 'K2'}

print("複数の値を返すことも出来ます")
def func():
    return 3, "ABC"

n, s = func()
print(n, s) # => 3 ABC


print("\n\n----------")
print("○グローバル変数")
print("グローバル変数を関数内で普通には参照も変更もできません")
print("global宣言すると変更できるようになります")
count = 0                   # グローバル変数
def func():
    global count            # これをしないと変更は出来ない
    print(count)            # 参照することはできる
    count += 1
    print(count)
func()

print("すべてのグローバル変数とローカル変数はglobals()とlocals()で取得できます")
def func():
    for k in globals().keys():
        print("GLOBAL: %s = %s" % (k, globals()[k]))
    for k in locals().keys():
        print("LOCAL: %s = %s" % (k, locals()[k]))
func()

print("\n\n----------")
print("○ラムダ式")
print("ラムダ式とは名前のない小さな関数です。")
print("コロンより手前が引数、後ろが戻り値です。")
myfunc = lambda x, y: x + y
print(myfunc(3, 5)) # => 8


print("\n\n----------")
print("○イテレータ")
print("イテレータはfor文で使える繰り返し機能を持つオブジェクトです")
print("__init__()には最初に1回だけやる処理を書きます")
print("__iter__()ではオブジェクトを返します")
print("__next__()で次の要素を返却します 最後に達するとStopIteration例外を返すようにします")
class Fib:
    def __init__(self, max):
        self.max = max
        self.a = 0
        self.b = 1
    def __iter__(self):
        return self
    def __next__(self):
        fib = self.a
        if fib > self.max:
            raise StopIteration
        self.a, self.b = self.b, self.a + self.b
        return fib
for n in Fib(3):
    print(n)                     # => 0, 1, 1, 2, 3

print("上記は以下を自動的にやってくれています")
it = Fib(3).__iter__()
while 1:
    try:
        n = it.__next__()
        print(n)                 # => 0, 1, 1, 2, 3
    except StopIteration:
        break

print("\n\n----------")
print("○ジェネレータ")
print("次の要素が使われるときに計算するので、配列を作って渡すよりもメモリや処理効率が改善されるみたい")
def funcB(list):
    for n in list:
        yield n * 2
for n in funcB([1, 2, 3, 4, 5]):
    print(n)                     #=> 2, 4, 6, 8, 10

def readfileB(f):
    for line in f:
        yield line.rstrip()
f = open("data.txt")
for line in readfileB(f):
    if (line == "__END__"):
        break
    print(line)
f.close()



print("\n\n----------")
print("○デコレータ")
print("関数実行前後に処理を追加出来ます")

def mydecolater(func):
    import functools
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print("Funcname:", func.__name__)
        print("Arguments:", args)
        print("Keywords:", kwargs)
        ret = func(*args, **kwargs)
        print("Return:", ret)
        return ret
    return wrapper

@mydecolater
def func(msg1, msg2, flag=1, mode=2):
    """A sample function"""
    print("----", msg1, msg2, "----")
    return 1234

n = func("Hello", "Hello2", flag=1)
print(n)

print(repr(func))
print(func.__doc__)


print("\n\n----------")
print("○クラス")

class MyClass(object):
    """A simple example class"""         # 三重クォートによるコメント

    PI=3.14                              # クラス変数

    def __init__(self):                  # コンストラクタ
        self.name = ""                   # nameはインスタンス変数

    def getName(self):                   # getName()メソッド
        return self.name

    def setName(self, name):             # setName()メソッド
        self.name = name

a = MyClass()                            # クラスのインスタンスを生成
a.setName("Tanaka")                      # setName()メソッドをコール
print(a.getName())                       # getName()メソッドをコール

print("Python では private や protected などのスコープを制御する機構は実装されておらず、クラス変数、インスタンス変数はすべてどこからでも参照可能(public)となります。")
print("クラス変数やインスタンス変数は直接書き換えられます")
MyClass.PI=3.141592
a.name="Tanaka2"

print("動的に追加も可能")
MyClass.myPI=3
a.age=18

print("インスタンス変数が存在しない場合、「インスタンス.変数名」はクラス変数を参照することに注意してください。")
print(a.PI) # PIというインスタンス変数は無いので、クラス変数が参照される。

print("「インスタンス.変数名」に値を代入した時点でインスタンス変数が生成され、以降はインスタンス変数が参照されます。")
a.PI=333 # クラス変数のPIとは別にインスタンス変数のPIができる。
print(a.PI) # => 333 インスタンス変数
print(MyClass.PI) # => 3.141592 クラス変数

print("dir()を使うといろいろ表示されます")
print("MyClass : "+str(dir(MyClass)))
print("MyClass : "+str(dir(a)))


print("\n\n----------")
print("○privateっぽい変数")
class MyClass2(object):
    _hidden_param=12
    __hidden_param2=34
print("クラス内の変数で、頭にアンダーバーが付いているものは外からはアクセスしないという慣習的なルールがあります。でもアクセスできます。")
print("2つついているとクラス内では普通にアクセス出来ますが、外からは普通にはアクセスしにくくなります。微妙に名前が変わって、「_クラス名__変数名」になります。")
print("MyClass2._hidden_param="+str(MyClass2._hidden_param))
#print("MyClass2._hidden_param="+str(MyClass2.__hidden_param2)) #←これはエラーになる
print("MyClass2._hidden_param="+str(MyClass2._MyClass2__hidden_param2)) #←これはOK


print("\n\n----------")
print("○コンストラクタとデストラクタと文字列化")
class MyClass3(object):
    def __init__(self, name):
        self.name = name
        print("welcome "+str(self.name))

    def __str__(self):
        return "name is "+self.name

    def __del__(self):
        print("byebye "+str(self.name))

a = MyClass3("Tanaka")
print(a) # __str__として定義されたメソッドが自動的に呼ばれる。
del(a)


print("\n\n----------")
print("○継承")
class MyClass:
    def hello(self):
        print("Hello")

class MyClass2(MyClass):
    def world(self):
        print("World")

a = MyClass2()
a.hello()                   #=> Hello
a.world()                   #=> World

print("メソッドのオーバーライト")
class MyClass:
    def hello(self):
        print("Hello")
class MyClass2(MyClass):
    def hello(self):        # 親クラスのhello()メソッドをオーバーライド
        print("HELLO")

a = MyClass2()
a.hello()                   #=> HELLO

print("super")
class MyClass1(object):
    def __init__(self):
        self.val1 = 123
    def pripri(self):
        print("print1")
class MyClass2(MyClass1):
    def __init__(self):
        super(MyClass2, self).__init__()
        self.val2 = 456
    def pripri(self):
        super(MyClass2, self).pripri()
        print("print2")

a = MyClass2()
print(a.val1)                #=> 123
print(a.val2)                #=> 456
a.pripri()

print("多重継承")
class MyClassA:
    def funcA(self):
        print("MyClassA:funcA")
class MyClassB:
    def funcB(self):
        print("MyClassB:funcB")

class MyClassC(MyClassA, MyClassB):
    def funcC(self):
        print("MyClassC:funcC")

a = MyClassC()
a.funcA()                    # MyClassA のメソッドも
a.funcB()                    # MyClassB のメソッドも使用できる
a.funcC()


print("\n\n----------")
print("○モジュール")
import mymodule
mymodule.myfunc()

print("パッケージについては省略。")

print("ファイル名"+str(__file__))
print("__name__でモジュール名の表示が出来ます。スクリプトで起動された場合は__main__になります。str(__name__)="+str(__name__))


print("\n\n----------")
print("○pprint")
print("配列等の情報を見やすく表示するにはpprintを使います")
from pprint import pprint
aaa = [0, 1, 2]
ppp = {'taro':{'age': '21', 'name': 'tanaka'}, 'jiro':{'age': '18', 'name': 'tanaka2'},}
pprint(aaa) #=> [0, 1, 2]
pprint(ppp) #=> {'jiro': {'age': '18', 'name': 'tanaka2'},
            #    'taro': {'age': '21', 'name': 'tanaka'}}

import os
print("現在のパスは"+os.getcwd())


print("\n\n----------")
print("○デバッグ用print")
print("デバッグ時のみ表示したいようなものは以下のようにすればよい(良いやり方か不明)。")

def null_function(x):
    return

myprint=null_function
#myprint=print

myprint("hoge")


print("\n\n----------")
print("○文字列の一部変更")
print("C言語のようにtext[2]='x'等とすることは出来ません。")
print("strがimmutableのためです")
print("一度リストに変換してから変更したり、スライスで操作します。")
print("参考 : http://minus9d.hatenablog.com/entry/20130528/1369745960")

text="test string"
#text[2]='S'#これはNG

temp=list(text)
temp[2]='S'
text="".join(temp)
print(text) #=> "teSt string"


print("\n\n----------")
print("○引数の値渡しと参照渡し")
print("関数の引数は値渡しの場合と参照渡しの場合があります。")
print("C言語に似ていて、int,float等は値渡し、list,dict等は参照渡しになります。")
print("でもstrは値渡しです。")
print("参考 : http://amacbee.hatenablog.com/entry/2016/12/07/004510")
def func1(x):
    x[1]=999
y=[0,1,2]
print(y) #=> [0, 1, 2]
func1(y)
print(y) #=> [0, 999, 2]

print("\n\n----------")
print("○スクリプトファイルを途中で止め入力可能にする")
import code; code.InteractiveConsole(locals=dict(globals(),**locals())).interact()
```


```python:mymodule.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-

#モジュール

def myfunc():
    print("Hello!")
```