もた日記

くだらないことを真面目にやる

Pythonメモ : あまり知られていない(かもしれない)テクニック集 その1

github.com

上記リポジトリにあまり知られていない(かもしれない)Pythonのテクニックが49個まとめられていたので簡単なものから見ていく(その2、その3は下記リンク)。

wonderwall.hatenablog.com

wonderwall.hatenablog.com


valueswapping.py : 変数の値を交換

変数の値を入れ替える。一時的な変数は不要。

コード

#! /usr/bin/env python3
"""pythonic way of value swapping"""
a, b = 5, 10
print(a, b)
a, b = b, a
print(a, b)

実行結果

5 10
10 5


controlwhitespaces.py : 空白の操作

空白の操作。幅を20として左寄せ、右寄せ、中央寄せする方法や、左右の空白を削除する方法。

コード

#! /usr/bin/env python3
"""control the whitespaces in string"""

s = 'The Little Price'

# justify string to be at least width wide
# by adding whitespaces
width = 20
s1 = s.ljust(width)
s2 = s.rjust(width)
s3 = s.center(width)
print(s1)   # 'The Little Price    '
print(s2)   # '    The Little Price'
print(s3)   # '  The Little Price  '

# strip whitespaces in two sides of string
print(s3.lstrip())  # 'The Little Price  '
print(s3.rstrip())  # '  The Little Price'
print(s3.strip())   # 'The Little Price'

実行結果

The Little Price
    The Little Price
  The Little Price
The Little Price
  The Little Price
The Little Price


concatenatestrings.py : 長い文字列を複数行に分けて書く

長い文字列を複数行に分けて書く方法。実行結果はprint(my_long_text)とした場合。

コード

#! /usr/bin/env python3
"""Concatenate long strings elegantly
across line breaks in code"""

my_long_text = ("We are no longer the knights who say Ni! "
                "We are now the knights who say ekki-ekki-"
                "ekki-p'tang-zoom-boing-z'nourrwringmm!")

実行結果

We are no longer the knights who say Ni! We are now the knights who say ekki-ekki-ekki-p'tang-zoom-boing-z'nourrwringmm!


forelse.py : forループのelse文

forループでbreakが呼び出されなければelse文が実行される。forループがbreak呼び出しで途中終了しておらず、最後まで実行されたことを確かめたいときに役立つ。

コード

#! /usr/bin/env python3
"""else gets called when for loop does not reach break statement"""
a = [1, 2, 3, 4, 5]
for el in a:
    if el == 0:
        break
else:
    print('did not break out of for loop')

実行結果

did not break out of for loop


whileelse.py : whileループのelse文

whileにも同様にelse文がある。

コード

""" You can have an else clause with a while. Works like for-else.
    When break is encountered, it exits the loop without executing else. """

i = 5

while i > 1:
    print("Whil-ing away!")
    i -= 1
    if i == 3:
        break
else:
    print("Finished up!")

実行結果

Whil-ing away!
Whil-ing away!

実行結果(i = 3とした場合)

Whil-ing away!
Whil-ing away!
Finished up!


tryelse.py : tryのelse文

tryにも同様にelse文がある。例外が発生しない場合にelse文が実行される。

コード

""" You can have an 'else' clause with try/except.
    It gets excecuted if no exception is raised.
    This allows you to put less happy-path code in the 'try' block so you can be
    more sure of where a caught exception came from."""
    
try:
    1 + 1
except TypeError:
    print("Oh no! An exception was raised.")
else:
    print("Oh good, no exceptions were raised.")

実行結果

Oh good, no exceptions were raised.


boolasint.py : ブール型を数値として扱う

True, Falseはそれぞれ1, 0として扱える。["is odd", "is even"][a % 2 == 0][a % 2 == 0]がFalse、つまり0なので["is odd", "is even"]の0番目にアクセスしてis oddになる。

コード

#! /usr/bin/env python3
"""True and False can be used as integer values
True -> 1
False -> 0
"""
a = 5
print(isinstance(a, int) + (a <= 10))
print(["is odd", "is even"][a % 2 == 0])

実行結果

2
is odd


rawinputintegers.py : 文字列内の複数の数値を変換

mapを使って文字列内の複数の数値を変換する方法。

コード

#! /usr/bin/env python3

"""
Convert raw string integer inputs to integers
"""

str_input = "1 2 3 4 5 6"

print("### Input ###")
print(str_input)

int_input = map(int, str_input.split())

print("### Output ###")
print(list(int_input))

実行結果

### Input ###
1 2 3 4 5 6
### Output ###
[1, 2, 3, 4, 5, 6]


chainedcomparison.py : 比較の連鎖

比較を連鎖させて書くことができる。10 == a < 2010 == a and a < 20と等価。

コード

#! /usr/bin/env python3
"""chained comparison with all kind of operators"""
a = 10
print(1 < a < 50)
print(10 == a < 20)

実行結果

True
True


conditionalassignment.py : 条件による代入

一つ目の例はよくあるif elseの書き方。二つ目の例はorの特徴を利用したもので、最初の値(この場合はNone)が偽値の場合は、次の値(この場合はFalse)が偽値であってもその値が代入される。

コード

#! /usr/bin/env python3
"""Python has two ways to do conditional assignments

The first is a fairly standard teranary style;
<value if true> if <conditional> else <value if false>

The second method takes advantage of the fact that python's or is lazy. When
an assignment is made if the first value is falsy (None is falsy), then it will
automatically return the second value, even if that value is falsy.

"""
b = True
print(True if b else False)

b = None or False
print(b)

実行結果

True
False


conditionalfunctioncall.py : 条件による関数呼び出し

1行のif else文で関数呼び出しができる。この場合はproduct(1, 1)が実行される。

コード

#! /usr/bin/env python3
"""calling different functions with same arguments based on condition"""
def product(a, b):
    return a * b

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

b = True
print((product if b else subtract)(1, 1))

実行結果

1


stepslice.py : リストの要素を何個置きに取得

3個置きに取得する場合。リストの範囲を指定する場合はa[0:4:3]などとする(結果は[1, 4])。

コード

#! /usr/bin/env python3
"""stepwise slicing of arrays"""
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(a[::3])

実行結果

[1, 4, 7, 10]


maxsplit.py : splitの分割回数

splitの分割回数を指定できる。ホワイトスペース区切りの場合はNoneとして回数を指定すればよい(回数を指定しないホワイトスペース区切りならsplit()でよい)。

コード

#! /usr/bin/env python3
"""split a string max times"""
string = "a_b_c"
print(string.split("_", 1))


"""use maxsplit with  arbitrary whitespace"""

s = "foo    bar   foobar foo"

print(s.split(None, 2))

実行結果

['a', 'b_c']
['foo', 'bar', 'foobar foo']


exec.py : execの引数に辞書

execの引数として辞書を渡すことができる。

コード

#! /usr/bin/env python3
"""exec can be used to execute Python code during runtime
variables can be handed over as a dict
"""
exec("print('Hello ' + s)", {'s': 'World'})

実行結果

Hello World


argumentunpacking.py : 引数リストのアンパック

ドキュメントによると引数リストのアンパックと呼ばれるもの。関数の引数として渡す場合、リストとタプルは*、辞書は**でアンパックできる。

コード

#! /usr/bin/env python3
"""simple tuple and dictionary unpacking"""
def product(a, b):
    return a * b

argument_tuple = (1, 1)
argument_dict = {'a': 1, 'b': 1}

print(product(*argument_tuple))
print(product(**argument_dict))

実行結果

1
1


extendediterableunpacking.py : Extended Iterable Unpacking

PEP 3132に書かれている。*を付けた変数に残りの値が代入されるようだ。

コード

#! /usr/bin/env python3
"""allows collecting not explicitly assigned values into
a placeholder variable"""

a, *b, c = range(10)
print(a, b, c)

"""advanced example"""

[(c, *d, [*e]), f, *g] = [[1, 2, 3, 4, [5, 5, 5]], 6, 7, 8]
print(c, d, e, f, g)

実行結果

0 [1, 2, 3, 4, 5, 6, 7, 8] 9
1 [2, 3, 4] [5, 5, 5] 6 [7, 8]


setglobalvariables.py : グローバル変数の更新

グローバル変数を辞書で更新する方法。globals()はグローバル名前空間の内容を示す辞書。

コード

#! /usr/bin/env python3
"""set global variables from dict"""

d = {'a': 1, 'b': 'var2', 'c': [1, 2, 3]}
globals().update(d)
print(a, b, c)

実行結果

1 var2 [1, 2, 3]