LoginSignup
13
14

More than 5 years have passed since last update.

python小ネタ集

Last updated at Posted at 2016-06-04

はじめに

pythonを勉強していて,小ネタが増えてきたので軽くまとめてみます.
深くまで調べられていない部分もありますが,ご容赦ください.

小ネタ一覧

  • 同一性と同値性
  • listのコピー
  • 関数を引数にとる関数
  • 関数を返す関数
  • 関数へのプロパティの付与
  • アクセス制限
  • intの除算
  • numpy小ネタ
    • 1次元配列の変形
    • スライスを使った反転
    • vectorize

小ネタ

一覧の上から順に説明していきます.

同一性と同値性

同一性とはオブジェクトが同一であることを,同値性は値が同一であることを指します.
同一性は is で評価し,同値性は == で評価します.
では,それぞれの型について結果を確認します.

int

-5 ~ 256の範囲の整数はメモリ節約のため同一のオブジェクトを使います.
それ以外の整数は,同値であっても同一ではありません.

a = 256
b = 256
a is b # True

c = 257
d = 257
c is d # False

e = -5
f = -5
e is f # True

g = -6
h = -6
g is h # False

float, long, complex

こちらは整数と異なる挙動をします.
同値であっても,格納されているメモリが異なるため同一ではありません.

a = 1.0
b = 1.0
a == b # True
a is b # False

a = 1L
a = 1L
a == b # True
a is b # False

a = 1 + 2j
b = 1 + 2j
a == b # True
a is b # False

bool

True / Falseは一つしか存在しません.

a = True
b = True
a is b # True

a = False
b = False
a is b # True

ちなみに,bool は int のサブクラスであり,False0True1 として扱うことができます.

isinstance(False, bool) # True
isinstance(False, int) # True

False == 0 # True
False is 0 # False

True == 1 # True
True is 1 # False

True + True # 2

result = -1
'OK' if result == 0 else 'NG' # 'NG'
('NG', 'OK')[result == 0] # 'NG'
result = 0
('NG', 'OK')[result == 0] # 'OK'

string

特殊文字を含まない文字列は,名前リストにインターンされるため同一です.
スペースや演算子等の特殊文字を含む場合,同値であっても同一ではありません.
ただし,特殊文字一文字だけの場合,同一となります.

a = 'foo'
b = 'foo'
a == b # True
a is b # True

a = 'f o o'
b = 'f o o'
a == b # True
a is b # False

a = 'x+y'
b = 'x+y'
a == b # True
a is b # False

a = '/'
b = '/'
a == b # True
a is b # True

また,以下のような場合には同一になりません.

a = 'f'
a += 'oo'
b = 'foo'
a == b # True
a is b # False

list, tuple, dictionary

list, tuple, dictionaryも文字列同様,同値であっても同一ではありません.

a = [1, 2, 3]
b = [1, 2, 3]
a == b # True
a is b # False

a = (1, 2, 3)
b = (1, 2, 3)
a == b # True
a is b # False

a = {'x': 1, 'y': 2}
b = {'x': 1, 'y': 2}
a == b # True
a is b # False

set

setはユニークな値を持つ集合です.順序の保証がないという特徴があります.
setも同値であっても同一ではありません.

a = set([1, 3, 2])
b = set([1, 3, 2])
c = set([1, 2, 3, 2])

a == b # True
a is b # False

a == c # True -> 順序の情報を保持せず,ユニークな値しか保たないので True
a is c # False

listのコピー

listの注意点として = を使ってコピーした場合,一方の要素を変更すると,もう一方の要素も変更されます.

a = [1, 2, 3]
b = a
a[0] = [0, 0] # a: [[0, 0], 2, 3], b: [[0, 0], 2, 3] -> a[0]を変更すると,b[0]も変更されます

スライスを使ってコピーした場合,深いコピーとなり,上の問題を防ぐことができます.

a = [1, 2, 3]
b = a[:]
a[0] = 0 # a: [0, 2, 3], b: [1, 2, 3] -> a[0]のみ変更
b[1] = 0 # a: [0, 2, 3], b: [1, 0, 3] -> b[1]のみ変更

ちなみにstring, tupleは要素の変更ができません.

b = 'foo'
b[0] = 'h' # TypeError: 'str' object does not support item assignment

a = (1, 2, 3)
a[0] = 0 # TypeError: 'tuple' object does not support item assignment

関数を引数にとる関数

pythonでは,「関数を引数に取る関数」を定義できます.

def higher(func, x, y):
    return func(x, y)

def add(a, b):
    return a + b

def sub(a, b):
    return a - b

print higher(add, 4, 3) # 7
print higher(sub, 4, 3) # 1

ちなみに lambda を使うと addsub のような関数を定義する手間を省けます.

def higher(func, x, y):
    return fun(x, y)

print higher(lambda a, b: a + b, 4, 3) # 7
print higher(lambda a, b: a - b, 4, 3) # 1

関数を返す関数

関数内で関数を定義し,それを返すように定義します.
外側の関数 f を実行すると f 内の _f がリターンされます.
リターンされた _f は関数であるため,さらに値を渡して実行することができます.
よって,f(1)(2) のような実行の仕方になります.

def f(x):
    def _f(y):
        return x + y
    return _f

print f(1) # <function _f at 0x10e45b140>
print f(1)(2) # 3

関数へのプロパティの付与

pythonにおける関数は,オブジェクトであるため,自由にプロパティを付与することができます.
どのように使うと便利なのかは分かりませんでした.どなたか教えてください.

def foo():
    return '!!!'

foo.x = 1
foo.y = 2
foo.f = lambda x: x + 1

print foo() # !!!
print foo.x # 1
print foo.y # 2.000000
print foo.f(9) # 10

アクセス制限

pythonには,C++やJavaに見られる privateprotected のようにアクセス制限をかける仕組みがありません.
そこで変数名 or メソッド名の先頭にアンダーバーをつけることで擬似的にアクセス制限をかけています.
アンダーバー1つの場合は,実際に呼び出すことができますが,プライベートメソッドとして実装しているという意図を示しています.
アンダーバー2つの場合は,定義したメソッド名で呼び出すことはできず,アクセス制限がかかった状態になります.
厳密に言うと,呼び出せないのではなく,メソッド名が _(クラス名)__(メソッド名) に変更されているだけです.
したがって,_(クラス名)__(メソッド名) の形式で呼び出すことができます.

class Foo(object):
    def __init__(self, x):
        self.x = x
    def f(self, y):
        return self.x + y
    def _f(self, y):
        return self.x + y + 1
    def __f(self, y):
        return self.x + y + 2

foo = Foo(1)
print foo.f(1) # 2
print foo._f(1) # 3
print foo.__f(1) # AttributeError: 'Foo' object has no attribute '__f'
print foo._Foo__f(1) # 4

intの除算

python 2.xにおける int $\div$ int の計算は,「小数点以下を切り捨てた整数」ではなく「除算の結果を超えない最大の整数」となります.
だからなんだって感じですね.

print 1 / 2 # 0
print -1 / 2 # -1

ちなみに,python 3.xでは,int $\div$ int の計算は小数になります.
また,python 3.xにおいてpython 2.xと同じ挙動にするには,// を使います.
// は,python 2.xでも使えます.

Python3.x
1 / 2 # 0.5
1 // 2 # 0
-1 / 2 # -0.5
-1 // 2 # -1

numpy小ネタ

みなさん大好きnumpyです.

1次元配列の変形

要素数 $n$ の1次元配列を shape で確認すると,(n, ) となります.
これを行ベクトル (1, n) や列ベクトル (n, 1) に変形するときは reshape を使います.

arr = numpy.arange(10) # array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
arr.shape # (10, )

arr.reshape((1, -1))
# array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])

arr.reshape((-1, 1))
# array([[0],
#        [1],
#        [2],
#        [3],
#        [4],
#        [5],
#        [6],
#        [7],
#        [8],
#        [9]])

スライスを使った反転

スライスを使って反転させることができます.
スライスは(開始インデックス):(終了インデックス):(間隔)で操作します.
負の値は後ろからのインデックスを指します.
[-1::-1] で末尾から先頭にスライスできます.
最初の -1 は省略できます.

X = numpy.arange(9).reshape((3, 3))
# array([[0, 1, 2],
#        [3, 4, 5],
#        [6, 7, 8]])

X[::-1, :]
# array([[6, 7, 8],
#        [3, 4, 5],
#        [0, 1, 2]])

X[:, ::-1]
# array([[2, 1, 0],
#        [5, 4, 3],
#        [8, 7, 6]])

vectorize

numpyのユニバーサル関数の中には,ndarray同士の四則演算や各要素の三角関数,対数をとる関数が定義されています.
自作の関数を各要素に適用する関数を定義するのに vectorize を使います.
例えば10で割ったときの余りを返す関数をvectorizeに渡して,その関数にndarrayを渡してみます.

X = numpy.arange(25).reshape((5, 5))
# array([[ 0,  1,  2,  3,  4],
#        [ 5,  6,  7,  8,  9],
#        [10, 11, 12, 13, 14],
#        [15, 16, 17, 18, 19],
#        [20, 21, 22, 23, 24]])

numpy.vectorize(lambda x: x % 10)(X)
# array([[0, 1, 2, 3, 4],
#        [5, 6, 7, 8, 9],
#        [0, 1, 2, 3, 4],
#        [5, 6, 7, 8, 9],
#        [0, 1, 2, 3, 4]])

おわりに

pythonの小ネタをまとめてみました.
他にもこんなのあるよっていうのあったら教えてください.
何か見つかったら随時追記してきます.

追記情報

@Tsutomu-KKE@github 様,@shiracamus 様,@kochory 様のコメントを参考に修正しました.(2016/06/04)

13
14
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
14