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フレームワーク
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 新機能
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):
...