LoginSignup
105
100

More than 1 year has passed since last update.

あまり知られていないPythonの言語仕様(Python3.4以降対応)

Last updated at Posted at 2015-01-20

はじめに

Pythonの言語仕様であまり知られていない(と勝手に思っている)ものをまとめてみる。

初級・中級・上級の分類は適当。

他にもあれば追記していく。

初級編

複素数リテラル

複素数の演算が標準でできるようになっている。
添字はiではなくjを使う。

>>> c1 = 1 + 1j
>>> c2 = 1 - 2j
>>> c1 + c2
(2-1j)
>>> c1 * c2
(3-1j)
>>> c1 / c2
(-0.2+0.6j)

複数のfor..inを含む内包表記

内包表記の中にfor..inを複数書ける。

>>> a = range(3)
>>> b = range(4)
>>> [x + y for x in a for y in b]
[0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5]

n個おきのスライス

次のように書くことでリストなどの要素をn個おきに取り出せる。

>>> a = list(range(20))
>>> a[::2]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

スライスによるリストのコピー

スライス構文にインデックスを渡さなければリストのコピーを作れる。

>>> a = range(10)
>>> b = a
>>> b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b is a # bとaは同一のオブジェクト
True
>>> c = a[:]
>>> c
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> c is a # bとaは別個のオブジェクト
False

中級編

Ellipsis

... が「省略」を表すオブジェクトとして扱われる。
詳しくはこちらを参照。

>>> ...
Ellipsis
>>> bool(...)
True

キーワード限定引数

関数定義中で *, を書くと、以降の引数を必ずキーワード引数として呼び出さなければならないようにできる。

>>> def f(a, *, b):
...     pass
...
>>> f(1)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: f() missing 1 required keyword-only argument: 'b'
>>> f(1,2)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: f() takes 1 positional argument but 2 were given
>>> f(1,b=2)
>>>

関数アノテーション

関数の引数と返り値にアノテーションをつけられる。
ドキュメントなどに使うためのアノテーションなので、違う型のオブジェクトが与えられてもエラーにはならない。

>>> def f(x : int, y : int) -> int:
...     return x + y
...
>>> f(2, 3)
5
>>> f('hoge', 'fuga') # エラーにはならない
'hogefuga'

global

global によって、どのスコープからでもグローバル変数を実行時に定義できる。

>>> def f():
...     global a
...     a = 1
...
>>> a # ここではaは未定義
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'a' is not defined
>>> f() # fの呼び出しによりグローバル変数aが定義される
>>> a
1

nonlocal

nonlocal によって、ひとつ外側のスコープに属する変数への代入が可能となる。
クロージャが簡単に作れる。

>>> def make_counter():
...     count = 0
...
...     def counter():
...         nonlocal count
...         count += 1
...         return count
...
...     return counter
...
>>> c = make_counter()
>>> c(), c(), c()
(1, 2, 3)

上級編

引数付きデコレータ

「『関数を受け取って関数を返す関数』を返す関数」を書くことで引数付きデコレータが作れる。
Flaskの @route('/') などはこれを用いて実装されていると思われる。

>>> def greet(before, after):
...      def decorator(func):
...          def wrapper(*args, **kwargs):
...              print(before)
...              func(*args, **kwargs)
...              print(after)
...          return wrapper
...      return decorator
...
>>> @greet('Hi.', 'Bye.')
... def introduce(name):
...     print('I am ' + name + '.')
...
>>> introduce('yubessy')
Hi.
I am yubessy.
Bye.

クラスデコレータ

クラスをラッピングするデコレータを書くことができる。
以下は簡易シングルトンの実装例。

>>> def singleton(cls):
...   instances = {}
...   def getinstance(*args, **kwargs):
...     if cls not in instances:
...         instances[cls] = cls(*args, **kwargs)
...     return instances[cls]
...   return getinstance
...
>>> @singleton
... class C(object):
...   pass
...
>>> c1 = C()
>>> c2 = C()
>>> c1 is c2
True

yield from

他のイテレータから値を返すジェネレータを作れる。

>>> def g():
...     yield from range(5)
...     yield from range(5, 10)
...
>>> [i for i in g()]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

raise from

例外を連鎖する際に、送出元の例外を保持する。

>>> try:
...     raise Exception('e1') from Exception('e2')
... except Exception as e:
...     print(e.__cause__)
...
e2

参考

105
100
7

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
105
100