関数(5)--可変パラメータ
4779 ワード
第18条:可変数の位置パラメータで視覚雑音を減少する
まず、このような関数を見てみましょう.
この関数は文字列とリストを受け入れ、印刷に使用します.ただし、リストに値がない場合は、2番目のパスのように空のリストを送信します.これは,
使用する場合は、もちろん2番目のパラメータが空の値であれば、リストを空にする必要がなく、関数も正常に動作することが望ましい.Pythonでは,後の位置パラメータに*を付けると実現できる.
変長パラメータを持つ関数を使用する場合は、常にメタグループに変換されます.したがって、変長パラメータに対応するパラメータの個数は十分に少ないはずです.そうしないと、メモリが大量に消費されます.特に、入力された可変パラメータが
第19条:オプションの動作をキーワードパラメータで表現する
Python関数は、パラメータを指定してパラメータを渡すときにキーワードを使用します.
直接値を渡すことも、キーワードを指定して値を伝えることもできます.ただし、キーワードパラメータの前に位置パラメータを置くことはできません.
各パラメータは1回しか指定できませんが、
第20条:動的デフォルトパラメータ
関数のパラメータにダイナミックなデフォルト値が必要な場合は、パラメータにデフォルト値を指定するのは当然だと思います.
運行結果は私たちが考えているものと違い、時間は一秒も違わず、全く同じであることがわかります!
ここではPythonコードの実行に関し、Pythonでは、パラメータのデフォルト値は各モジュールのロード時に求められ、モジュールはまたプログラムの起動時にロードされるので、パラメータのデフォルト値はモジュールのロード時に固定されている.
以上のようにPythonではパラメータの動的デフォルト値を実現するには関数でしか実現できない.パラメータをデフォルトでNoneに設定し、関数でパラメータの値に基づいてNoneかどうかを判断して評価します.パラメータがリスト、辞書などの可変タイプの場合は、Noneを使用して入力する必要があります.そうしないと、同じ可変タイプのオブジェクトが使用されます.
第21条:キーワード形式でしか指定できないパラメータを使用して、コードが明確であることを確保する
Python 3では、キーワード形式でしか指定できないパラメータを定義することができ、これらのパラメータはキーワードで提供されなければならず、位置で提供されない.
上記の例では、パラメータリストに
指定したキーパラメータを使用して正常に動作します.
Python 2では、この方法はありませんが、指定したキーワードパラメータしか使用できないことを別の方法で実現することができます.
まず、このような関数を見てみましょう.
def log(message, values):
if not values:
print(message)
else:
values_str = ''.join(str(x) for x in values)
print('%s: %s' % (message, values_str))
log('My number are', [1, 2])
log('No number', [])
>>>
My number are: 12
No number
この関数は文字列とリストを受け入れ、印刷に使用します.ただし、リストに値がない場合は、2番目のパスのように空のリストを送信します.これは,
log
関数のパラメータが固定されており,固定されたパラメータに従ってしか値を伝達できないためである.使用する場合は、もちろん2番目のパラメータが空の値であれば、リストを空にする必要がなく、関数も正常に動作することが望ましい.Pythonでは,後の位置パラメータに*を付けると実現できる.
def log(message, *values): # *
if not values:
print(message)
else:
values_str = ''.join(str(x) for x in values)
print('%s: %s' % (message, values_str))
log('My number are', [1, 2])
log('No number') #
>>>
My number are: 12
No number
変長パラメータを持つ関数を使用する場合は、常にメタグループに変換されます.したがって、変長パラメータに対応するパラメータの個数は十分に少ないはずです.そうしないと、メモリが大量に消費されます.特に、入力された可変パラメータが
*
番のジェネレータである場合です.もう1つの問題は、可変パラメータの前に新しいパラメータを追加する場合、関数を変更する必要があります.そうしないと、混乱します.第19条:オプションの動作をキーワードパラメータで表現する
Python関数は、パラメータを指定してパラメータを渡すときにキーワードを使用します.
def remainer(number, divisor):
return number % divisor
assert remainer(20, 7) == 6
remainer(20, divisor=7)
remainer(number=20, divisor=7)
remainer(divisor=7, number=20)
直接値を渡すことも、キーワードを指定して値を伝えることもできます.ただし、キーワードパラメータの前に位置パラメータを置くことはできません.
remainer(number=20, 7)
>>>
SyntaxError: positional argument follows keyword argument
各パラメータは1回しか指定できませんが、
remainer(20, number=7)
>>>
TypeError: remainer() got multiple values for argument 'number'
第20条:動的デフォルトパラメータ
関数のパラメータにダイナミックなデフォルト値が必要な場合は、パラメータにデフォルト値を指定するのは当然だと思います.
def log(message, when=datetime.now()):
print('%s: %s' % (message, when))
log('first time')
sleep(1)
log('second time')
>>>
first time: 2018-05-21 07:54:09.361192
second time: 2018-05-21 07:54:09.361192
運行結果は私たちが考えているものと違い、時間は一秒も違わず、全く同じであることがわかります!
ここではPythonコードの実行に関し、Pythonでは、パラメータのデフォルト値は各モジュールのロード時に求められ、モジュールはまたプログラムの起動時にロードされるので、パラメータのデフォルト値はモジュールのロード時に固定されている.
def log(message, when=None):
when=datetime.now() if when is None else when
print('%s: %s' % (message, when))
log('first time')
sleep(1)
log('second time')
>>>
first time: 2018-05-21 08:00:44.378427
second time: 2018-05-21 08:00:45.378766
以上のようにPythonではパラメータの動的デフォルト値を実現するには関数でしか実現できない.パラメータをデフォルトでNoneに設定し、関数でパラメータの値に基づいてNoneかどうかを判断して評価します.パラメータがリスト、辞書などの可変タイプの場合は、Noneを使用して入力する必要があります.そうしないと、同じ可変タイプのオブジェクトが使用されます.
第21条:キーワード形式でしか指定できないパラメータを使用して、コードが明確であることを確保する
Python 3では、キーワード形式でしか指定できないパラメータを定義することができ、これらのパラメータはキーワードで提供されなければならず、位置で提供されない.
def safe_division(number, divisor, *, ignore_overflow=False, ignore_zero_division=False):
try:
return number / divisor
except OverflowError:
if ignore_overflow:
return 0
else:
raise
except ZeroDivisionError:
if ignore_zero_division:
return 0
else:
raise
safe_division(5, 3, True, False)
>>>
TypeError: safe_division() takes 2 positional arguments but 4 were given
上記の例では、パラメータリストに
*
番を使用して位置パラメータが終了したことを示し、後続パラメータはキーワードでのみ指定できます.キーワードパラメータを指定しなかった場合、位置パラメータを使用するとエラーが表示されます.print(safe_division(1, 10*500, ignore_overflow=True, ignore_zero_division=False))
>>>
0.0
指定したキーパラメータを使用して正常に動作します.
Python 2では、この方法はありませんが、指定したキーワードパラメータしか使用できないことを別の方法で実現することができます.
def safe_division_d(number, divisor, **kwargs):
ignore_overflow = kwargs.pop('ignore_overflow', False)
ignore_zero_division = kwargs.pop('ignore_zero_division', False)
if kwargs:
raise TypeError('Unexcepted **kwargs')
try:
return number / divisor
except OverflowError:
if ignore_overflow:
return 0
else:
raise
except ZeroDivisionError:
if ignore_zero_division:
return 0
else:
raise
print(safe_division_d(1, 10**500000, True, False))
print(safe_division_d(1, 10**500000, ignore_overflow=True, ignore_zero_division=False))
print(safe_division_d(1, 10**500000, unexpected=True))
>>>
TypeError: safe_division_d() takes 2 positional arguments but 4 were given
0.0
TypeError: Unexcepted **kwargs
**kwargs
というパラメータを用いると,指定された方法でパラメータが正しいか否かを容易に判断できる.