Python

★インストール(Macの場合)

brew doctor

brew install pyenv

export PATH="$HOME/.pyenv/shims:$PATH"

pyenv install --list

pyenv install 3.6.3

pyenv global 3.6.3

python -V

pyenv versions

Tips

a, b = b, a # 交換

def binary():

return 0, 1

zero, one = binary()

zero, _ = binary()

pip用法

pip install <package-name>

pip install <package-name>==<version>

pip check 依存関係の確認

pip list

pip list -o アップデート必要なパッケージのリスト

pip freeze パッケージ名==バージョンで表示

pip freeze > requirements.txt

pip install -r requirements.txt

pip install -U <package-name> アップデート

pip install -U pip

pip install <package-name> -t ./

pip uninstall <package-name>

pip show <package-name>

error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": https://visualstudio.microsoft.com/downloads/

対応方法(Windowsの場合):vs_buildtools__776263548.1558503326.exeをインストール

★Flaskフレームワーク

http://flask.pocoo.org/

pip install Flask

FLASK_APP=hello.py FLASK_DEBUG=1 flask run

Try

def divide(a, b):

try:

return a / b

except ZeroDivisionError as e:

raise ValueError('Invalid inputs') from e

try:

result = divide(x, y)

except ValueError:

...

else:

...

Lambda

def test(v):

r = []

if v > 0:

for i in range(v):

r += [v - i]

return r

test = lambda v: [v - i for i in range(v)] if v > 0 else []

★Pretty print

from pprint import pprint

pprint(my_dict)

コマンドの場合

cat file.json | python -m json.tools

★Generator

リストの代わりにジェネレータを返す

def index_words(text):

result = []

if text:

result.append(0)

for index, letter in enumerate(text):

if letter == ' ':

result.append(index + 1)

return result

rlt = index_words(str)

def index_words(text):

if text:

yield 0

for index, letter in enumerate(text):

if letter == ' ':

yield index + 1

rlt = list(index_words(str))

★組込みException

BaseException

+-- SystemExit

+-- KeyboardInterrupt

+-- GeneratorExit

+-- Exception

+-- StopIteration

+-- ArithmeticError

| +-- FloatingPointError

| +-- OverflowError

| +-- ZeroDivisionError

+-- AssertionError

+-- AttributeError

+-- BufferError

+-- EnvironmentError

| +-- IOError

| +-- OSError

| +-- WindowsError (Windows)

| +-- VMSError (VMS)

+-- EOFError

+-- ImportError

+-- LookupError

| +-- IndexError

| +-- KeyError

+-- MemoryError

+-- NameError

| +-- UnboundLocalError

+-- ReferenceError

+-- RuntimeError

| +-- NotImplementedError

+-- SyntaxError

| +-- IndentationError

| +-- TabError

+-- SystemError

+-- TypeError

+-- ValueError

| +-- UnicodeError

| +-- UnicodeDecodeError

| +-- UnicodeEncodeError

| +-- UnicodeTranslateError

+-- Warning

+-- DeprecationWarning

+-- PendingDeprecationWarning

+-- RuntimeWarning

+-- SyntaxWarning

+-- UserWarning

+-- FutureWarning

+-- ImportWarning

+-- UnicodeWarning

+-- BytesWarning

+-- ResourceWarning

★落とし穴

def test():

return [lambda x: i*x for i in range(4)]

for func in test():

print(func(2))

# 想定:0 2 4 6

# 実際:6 6 6 6

対策1

def test():

return [lambda x,i=i: i*x for i in range(4)]

対策2

from functools import partial

from operator import mul

def test():

return [partial(mul,i) for i in range(4)]

対策3

def test():

return (lambda x: i*x for i in range(4))

対策4

def test():

for i in range(4):

yield lambda x: i*x

def foo(x=[]):

x.append(1)

print x

foo() # [1]

foo() # [1, 1]

正 ↓

def foo(x=None):

if x is None:

x = []

x.append(1)

print x

foo() # [1]

foo() # [1]

★特殊メソッド

http://diveintopython3-ja.rdy.jp/special-method-names.html

class Department:

def __init__(self, *employees):

self.employees = employees

for employee in department.employees:

...

class Department:

def __init__(self, *employees):

self._employees = employees

def __iter__(self):

return iter(self._employees)

for employee in department:

...

class Book:

def __eq__(self, other):

if not isinstance(other, self.__class__):

return NotImplemented

return (self.author == other.author and

self.title == other.title)

def __hash__(self):

return hash(self.author) ^ hash(self.other)

def __lt__(self, other):

return (self.author, self.title) < (other.author, other.title)

class Config:

def __init__(self, **entries):

self.entries = entries

def __add__(self, other):

entries = (self.entries.items() +

other.entries.items())

return Config(**entries)

default_config = Config(color=False, port=8080)

config = default_config + Config(color=True)

class Sample(object):

__slots__ = ["name","age"]

def __init__(self, name, age):

self.name = name

self.age = age

※__dict__を利用しない一方、メモリ節約

★Unpack

def foo(x, y):

pass

foo(*a_list)

foo(**a_dict)

def f(a, b, c, d):

pass

f(**{'a': 1, 'd': 4}, **{'c': 3}, **{'b': 2})

def handle(*args):

for count, thing in enumerate(args):

pass

handle('apple', 'cabbage')

def handle(**kwargs):

for name, value in kwargs.items():

pass

handle(apple = 'fruit', cabbage = 'vegetable')

all(x >= 0 for x in [1, 2, -3]) # False

any(x >= 0 for x in [1, 2, -3]) # True

if a>0: print(a)

c = a if a<b else b

f = lambda a,b:a if a<b else b

name = "Tom"

age = 30

anniversary = datetime.date(1990, 4, 17)

print(f"{name} {age-23}歳: Anniv. {anniversary: %A, %B, %d, %Y}")

print("{} {}歳: Anniv. {:%A, %B, %d, %Y}".format(name, age-23, anniversary))

'{msg1} {msg2}'.format_map({"msg1":"Hello", "msg2":"World"})

t = a % 3

if t == 0:

a = a * 2

elif t == 1:

a = 0

elif t == 2:

a = t * 2

t = a % 3

a = [a * 2, 0, t * 2][t]

c = 4 if a < b else 2

c = 2 + 2 * (a < b)

★メモリ使用量

mylist = range(0, 10000)

print(sys.getsizeof(mylist)) # 48 Good

mylist = [x for x in range(0, 10000)]

print(sys.getsizeof(myreallist)) # 87632

★文字列・数値をゼロ埋め

s = '1234'

s.zfill(8) # 00001234

s.rjust(8, '0') # 00001234

s.ljust(8, '0') # 12340000

s.center(8, '0') # 00123400

format(s, '0>8') # 00001234

'{:0>8}'.format(s) # 00001234

n = 1234

format(n, '08') # 00001234

'{:08}'.format(n) # 00001234

f'{n:08}' # 00001234

★Clone

import copy

a = [1, 2, 3, 4, ['a', 'b']]

b = a

c = copy.copy(a)

d = copy.deepcopy(a)

a.append(5)

a[4].append('c')

# a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]

# b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]

# c = [1, 2, 3, 4, ['a', 'b', 'c']]

# d = [1, 2, 3, 4, ['a', 'b']]

リストのコピー

y = x[:]

y = list(x)

★フォルダ遍歴

import os

def tree(top):

for path, names, fnames in os.walk(top):

for fname in fnames:

yield os.path.join(path, fname)

for name in tree('/home/xxx'):

print name

List

for i in bag:

bag[i] = bag[i] * 2

# enumerate(bag, 1)の場合:index + 1

for index, element in enumerate(bag):

print(index, element)

bag = [elem * 2 for elem in bag] # better

teams = [...]

to_str = ", ".join(teams)

bag = []

for _ in range(10):

bag.append(0)

bag = [0] * 10 // better

# list[start:stop:step]

# list[::-1] 逆順

for color in reversed(colors):

bag = [...]

for elem in bag[:5]: # 最初から

for elem in bag[-5:]: # 最後から

for elem in bag[::2]: # 2毎

sorted(fruits)

sorted(fruits, reverse=True)

sorted(fruits, key=len)

※fruitsは変更されない

fruits.sort()

※fruitsは変更される

from bisect import bisect

def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):

i = bisect(breakpoints, score)

return grades[i]

[grade(score) for score in [33, 77, 100]]

# ['F', 'C', 'A']

重複除く

orgList = [...]

formatList = list(set(orgList))

formatList.sort(key=orgList.index) // 順番保証

頻繁数字を探す

test = [1,2,3,4,...1,4,4,4]

max(set(test), key=test.count) # 4

注意点

board = [['_'] * 3 for i in range(3)]

board[1][2] = 'X'

# [['_', '_', '_'], ['_', '_', 'X'], ['_', '_', '_']]

下記と同じ

board = []

for i in range(s):

row = ['_'] * 3

board.apped(row)

注意点

board = [['_'] * 3] * 3

board[1][2] = 'X'

# [['_', '_', 'X'], ['_', '_', 'X'], ['_', '_', 'X']]

下記と同じ

row = ['_'] * 3

board = []

for i in range(s):

board.apped(row)

a=[1,2,3]

b=[4,5,6]

a.append(b)

# a: [1, 2, 3, [4, 5, 6]]

a.extend(b)

# a: [1, 2, 3, 4, 5, 6]

Flattening

a = [[1, 2], [3, 4], [5, 6]]

-> [1, 2, 3, 4, 5, 6]

方法1

list(itertools.chain.from_iterable(a))

方法2

sum(a, [])

方法3

[x for l in a for x in l]

★ZIP

a = [1, 2, 3]

b = ['a', 'b', 'c']

z = zip(a, b)

# [(1, 'a'), (2, 'b'), (3, 'c')]

zip(*z)

# [(1, 2, 3), ('a', 'b', 'c')]

nfc = ["A", "B"]

afc = ["C", "D"]

※二つのリストの長さは必ず同じ

for teama, teamb in zip(nfc, afc):

print teama + " vs. " + teamb

# A vs. C

# B vs. D

list(zip(range(3), 'ABC'))

# [(0, 'A'),(1, 'B'),(2, 'C')]

list(zip(range(3), 'ABC', [0, 1, 2, 3]))

# # [(0, 'A', 0),(1, 'B', 1),(2, 'C', 2)]

from itertools import zip_longest

list(zip_longest(range(3), 'ABC', [0, 1, 2, 3], fillvalue=-1))

# # [(0, 'A', 0),(1, 'B', 1),(2, 'C', 2),(-1, -1, 3)]

map filter reduce

first, second, *rest, last = range(10)

print(*[1,2], 3, *[4])

*range(4), 4 # (0, 1, 2, 3, 4)

[*range(4), 4] # [0, 1, 2, 3, 4]

{*range(4), 4} # {0, 1, 2, 3, 4}

{**{'x': 3}, 'y': 4} # {'x': 3, 'y': 4}

x = dict(a=1, b=2)

y = dict(b=3, d=4)

z = {**x, **y} # {'a': 1, 'b': 3, 'd': 4}

★operatorとfunctoolsモジュール

data = [

('Tokyo', 'JP', (35.23, 139.35)),

...

]

from operator import itemgetter

for city in sorted(data, key=itemgetter(1)):

...

cc_name = itemgetter(1,0)

for city in data:

print(cc_name(city))

somelist = [(1, 5, 8), (6, 2, 4), (9, 7, 5)]

somelist.sort(key=itemgetter(1))

# [(6, 2, 4), (1, 5, 8), (9, 7, 5)]

from operator import mul

from functools import partial

triple = partial(mul, 3)

list(map(triple, range(1, 10)))

★collectionsモジュール

from collections import namedtuple

LatLong = namedtuple('LatLong', 'lat long')

City = namedtuple('City', 'name, cc, coord')

areas = [City(name, cc, LatLong(lat, long)) for name, cc, (lat, long) in data]

from operator import attrgetter

name_lat = attrgetter('name', 'coord.lat')

for city in sorted(areas, key=attrgetter('coord.lat')):

print(name_lat(city))

from collections import deque

dq = deque([1,2])

dq.append('a') # [1,2,'a']

dq.appendleft('b') # ['b',1,2,'a']

dq.insert(2,3) # ['b',1,3,2,'a']

print(dq.pop())

print(dq.popleft())

from collections import OrderedDict

od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])

※挿入の順番

from collections import Counter

c = Counter(a=4, b=2, c=0, d=-2)

list(c.elements())

['a', 'a', 'a', 'a', 'b', 'b']

c = Counter('abracadabra')

c.most_common()

[('a', 5), ('r', 2), ('b', 2), ('c', 1), ('d', 1)]

c.most_common(3)

[('a', 5), ('r', 2), ('b', 2)]

c.most_common()[:-n:-1] # 最小のn数

★プロパティ

class Sample(object):

def __init__(self, x):

self._x = x

@property

def x(self):

return self._x

@x.setter

def x(self, x):

if not isinstance(x, float):

raise ValueError("hoge")

self._x = x

@x.deleter

def x(self):

del self._x

★Enum

from enum import Enum

class AnimalEnum(Enum):

HORSE = 1

COW = 2

CHICKEN = 3

DOG = 4

AnimalEnum.CHICKEN.name # 'CHICKEN'

AnimalEnum.CHICKEN.value # 3

for animal in AnimalEnum:

# Name: AnimalEnum.HORSE Value: 1

print('Name: {} Value: {}'.format(animal, animal.value))

或いは

AnimalEnum = Enum('Animal', 'HORSE COW CHICKEN DOG')

AnimalEnum.CHICKEN

AnimalEnum(2)

AnimalEnum['CHICKEN']

from enum import auto, Enum

class Shapes(Enum):

CIRCLE = auto() # 1

SQUARE = auto()

OVAL = auto()

★Python 3.7 新機能

dataclasses

from dataclasses import dataclass

@dataclass

class InventoryItem:

'''Document'''

name: str

unit_price: float

quantity_on_hand: int = 0

def total_cost(self) -> float:

return self.unit_price * self.quantity_on_hand

下記と同様

def __init__(self, name: str, unit_price: float, quantity_on_hand: int=0):

self.name = name

self.unit_price = unit_price

self.quantity_on_hand = quantity_on_hand

★日付関連

import datetime as dt

x = dt.datetime(2018, 12, 15)

x = dt.timedelta(hours=1, minutes=30)

y = x + dt.timedelta(1) # 1日後

x = dt.datetime.strptime(str, "%Y-%m-%d %H-%M-%S")

★メモリの解放

・要素を削除

import gc

del gc_test

gc.collect()

・yieldを使う

def file_generator(file):

with open(file, encoding="utf-8") as f:

for line in f:

yield line

gen = file_generator('sample.csv')

for line in gen:

print(line)

・pandasでchunksizeを指定(一度にメモリ上に読み込む行数)

import pandas as pd

reader = pd.read_csv('sample.csv', encoding='utf-8', chunksize=10, header=None)

for i in reader:

print(i)

・dask(柔軟な並列計算を行うライブラリ)を使用

import dask.dataframe as dd

reader = dd.read_csv('sample.csv', encoding='utf-8', header=None)

print(reader.compute())

list(map(my_func, filter(lambda n: n % 2, range(6))))

[my_func(n) for n in range(6) if n % 2]

from functools import reduce

from operator import add

reduce(add, range(100))

sum(range(100))

nums = [str(n) for n in range(20)]

nums = map(str, range(20))

★PIPE風

functionにより

from functools import reduce

def even_filter(nums):

return filter(lambda x: x%2==0, nums)

def multiply_by_three(nums):

return map(lambda x: x*3, nums)

def convert_to_string(nums):

return map(lambda x: 'The Number: %s' % x, nums)

def pipeline_func(data, fns):

return reduce(lambda a, x: x(a),

fns,

data)

nums = [1, 2, 3, 4, 5]

pipeline = pipeline_func(nums, [even_filter,

multiply_by_three,

convert_to_string])

for num in pipeline:

print (num)

decoratorにより

class Pipe(object):

def __init__(self, func):

self.func = func

def __ror__(self, other):

def generator():

for obj in other:

if obj is not None:

yield self.func(obj)

return generator()

@Pipe

def even_filter(num):

return num if num % 2 == 0 else None

@Pipe

def multiply_by_three(num):

return num*3

@Pipe

def convert_to_string(num):

return f'The Number: {num}'

@Pipe

def echo(item):

print (item)

return item

def force(sqs):

for item in sqs: pass

nums = [1, 2, 3, 4, 5]

force(nums | even_filter | multiply_by_three | convert_to_string | echo)

Dict

a = dict(one=1, two=2, three=3)

a = {'one':1, 'two':2, 'three':3}

a = dict(zip(['one', 'two', 'three'], [1,2,3]))

a = dict([('two', 2), ('one', 1), ('three', 3)])

dict1 = { 'a': 1, 'b': 2 }

dict2 = { 'b': 3, 'c': 4 }

merged = { **dict1, **dict2 }

for key,value in dict.items():

for key,value in dict.iteritems(): # メモリ節約

for key in dict:

for key in dict.keys():

for value in dict.values():

for value in set(dict.values()): # 重複なし

count = {}

bag = [...]

for i in bag:

if i in count:

count[i] += 1

else:

count[i] = 1

for i in bag:

count[i] = count.get(i, 0) + 1 # better

あるいは

count = dict([(num, bag.count(num)) for num in bag]) # 遅い

あるいは

count = {num: bag.count(num) for num in bag} # 遅い

あるいは

from collections import Counter

count = Counter(bag)

my_dict = {i: i * 2 for i in xrange(100)}

my_set = {i * 2 for i in xrange(100)}

teams = [...]

print {key: value for value, key in enumerate(teams)}

data = {...}

is_admin = data.get('admin', False)

defaultについて

my_dict = {}

my_dict.setdefault(key, []).append(value)

下記と同じ

if key not in my_dict:

my_dict[key] = []

my_dict[key].append(value)

from collections import defaultdict

my_dict = defaultdict(list)

my_dict[key].append(value)

d = {}

for color in colors:

d[color] = d.get(color, 0) + 1

d = defaultdict(int)

for color in colors:

d[color] += 1

d = {}

for name in names:

key = len(name)

d.setdefault(key, []).append(name)

d = defaultdict(list)

for name in names:

key = len(name)

d[key].append(name)

Tuple

namedtupleについて

from collections import namedtuple

Card = namedtuple('Card', ['rank', 'suit'])

class FrenchDeck:

ranks = [str(n) for n in range(2, 11)] + list('JQKA')

suits = 'spades diamonds clubs hearts'.split()

def __init__(self):

self._cards = [Card(rank, suit) for suit in self.suits

for rank in self.ranks]

def __len__(self):

return len(self._cards)

def __getitem__(self, position):

return self._cards[position]

c = Card('7', 'diamonds')

City = namedtuple('City', 'name country coordinates')

tokyo = City('Tokyo', 'JP', (35.23, 139.35))

City._fields # name country coordinates

LatLong = namedtuple('LatLong', 'lat long')

data = ('Tokyo', 'JP', LatLong(35.23, 139.35))

tokyo = City._make(data) 或いは City(*data)

for key, value in tokyo._asdict().items():

...

クラス

class Vector:

def __init__(self, x=0, y=0):

self.x = x

self.y = y

def __repr__(self):

return 'Vector(%r, %r)' % (self.x, self.y)

def __add__(self, other):

x = self.x + other.x

y = self.y + other.y

return Vector(x, y)

def __mul__(self, scalar):

return Vector(self.x * scalar, self.y * scalar)

★__init__ vs __new__

class A(object):

def __init__(self, *args, **kwargs):

print("init ", self.__class__)

def __new__(cls, *args,**kwargs):

print("new ", cls)

return object.__new__(cls, *args, **kwargs)

a = A()

# new <class '__main__.A'>

# init <class '__main__.A'>

class A():

def __init__(self, dicts):

# self.name=dicts["name"]

self.__dict__.update(dicts)

if __name__ == '__main__':

dicts={"name":"lisa","age":23}

a=A(dicts)

★classmethod vs staticmethod

class Sample:

class_var = "hoge"

@classmethod

def class_method(cls):

print "%s, %s" %(cls, cls.class_var)

@staticmethod

def static_method():

print "%s, %s" %(Sample, Sample.class_var)

class SubSample(Sample):

class_var = "foo"

Sample.class_method() # _main_.Sample, hoge

Sample.static_method() # _main_.Sample, hoge

SubSample.class_method() # _main_.Sample, foo

SubSample.static_method() # _main_.Sample, hoge

★抽象クラス

import abc

class MyClass(abc.ABC): # from 3.4

class MyClass(metaclass=abc.ABCMeta):

@abc.abstractmethod

def method(self):

"""..."""

class MySubClass(MyClass):

def method(self):

...