python学習ノート24:基礎文法の関数
11383 ワード
目次1.関連概念 1.1形式パラメータ/実際のパラメータ 1.2位置パラメータ/キーワードパラメータ 1.3パラメータ数は不確定であってもよい 1.3.1アスタリスク* を使用 1.3.2双星号** を使用 1.3.3. ***との役割 1.4.命名キーワードパラメータ 1.5.パラメータ組合せ 1.6.戻り値 1.7. DocStrings 1.8.関数別名 1.9.関数式プログラミング 2.高次関数 2.1.変数は関数 を指すことができる. 2.2.関数名も変数 2.3.入力関数 2.4.戻り関数 3.匿名関数lambda 4.装飾器 5.バイアス関数 1.関連概念
次のようなプログラムを例にとると
1.1形式パラメータ/実際のパラメータ
形式パラメータ:関数定義時に書かれ、メモリ領域は割り当てられていませんが、定義で使用できるパラメータです.例:def(a,b=0).実際のパラメータ:関数呼び出し時に関数に渡される変数.これは、システムがメモリ空間を実質的に割り当てた変数です.
1)パラメータはデフォルト値def func(a,b=5,c=10)を定義することができるが、パラメータテーブルの末尾にあるパラメータのみがデフォルトパラメータ値を持つことができ、例えばdef func(a,b=5)が有効であり、def func(a=5,b)が無効である.2)パラメータリストの後にデフォルト値を持つパラメータを表示し、デフォルト値のないパラメータの前に表示されるとエラーが発生します.
1.2位置パラメータ/キーワードパラメータ
位置パラメータ:入力された値は、関数のパラメータに位置順に順次割り当てられます.例えばpower(x,n)、キーワードパラメータ:パラメータに割り当てられたパラメータとして名前を付けることで、位置を考慮する必要はありません.例えばfunc(25,c=24);
キーワードパラメータを使用するメリット:1)パラメータの順序を心配する必要はありません.2)他のパラメータにデフォルト値がある場合は、希望するパラメータにのみ値を割り当てることができます.
1.3パラメータの数は不確定であることができる
1.3.1アスタリスクの使用*
関数を定義するときに、パラメータの前に*番号を付けると、パラメータはtupleを受信します.
アスタリスクは通常の文では使用できません
注意:*numbersという書き方は、関数パラメータのリスト、関数を呼び出すときのパラメータ伝達の2つの文にしか現れません.通常の文(関数内部の文を含む)でアスタリスクを使用すると、エラーが発生します. は、関数パラメータリストで使用されます.この場所には実際に複数のパラメータがあるが、関数内部で1つのtupleにマージされて使用されていることを示します. は、関数パラメータがList/Topleではなくその要素であるため、関数パラメータを呼び出すときに使用されます. *numbersは通常の文に書かれており、構文エラー:can't use starred(星番号付き)expression hereが報告されます.
1.3.2双星を使用**
*kwを使用して、0つ以上のパラメータ名を含むパラメータを入力します.これらのキーワードパラメータは、関数内部でdictとして組み立てられます.キーワードパラメータを使用して関数の機能を拡張します.
1.3.3. ***との役割
一般に*と**は、関数にパラメータを渡す場合にのみ使用されますが、関数パラメータの外ではあまり使用されません(エラーが発生する可能性もあります).
例えば、foo(1,2,3)はfoo(*[1,2,3])bar(a=1,b=2,c=3)はbar(*{‘a’:1,‘b’:2,‘c’:3})に相当する
*L 0はリスト(メタグループ)L 0を解体した結果と考えられる.
*の役割:リストを要素に分割します.L 0=[0,1,2,3]#L 0はlistであり、全体であり、L 0を関数に渡し、関数は1つのパラメータを得る.*L 0#L 0は4つの要素で、L 0を関数に渡し、関数は4つのパラメータを得ます.
**の役割は、dictを一連のキー値ペアに分解します.D 0={‘a’:0,‘b’:1}#D 0はdictであり,直接関数に伝達され,関数は1つのパラメータを得る.D 0#は2つのキー値のペアで、D 0を関数に渡し、関数は2つのパラメータを得ます.
1.4.キーワードパラメータの命名
*kwを使用:任意の名前のキーワードをパラメータとして渡すことができます.*,city,jobを使用すると、キーワードパラメータとしてcityとjobのみを受信するなど、キーワードパラメータの名前を制限できます.に対応するパラメータがパラメータ名に入力されなければならない(「city」=「Chengdu」という方法でパラメータ名が入力されている)が、パラメータ名がない場合は位置パラメータとみなされ、Errorを招く可能性がある. 関数を定義するときにデフォルト値を与えると、呼び出し時にこのパラメータを渡さなくてもよい.
1.5.パラメータの組み合わせ
Python関数の5つのパラメータは任意に組み合わせて使用できます.パラメータ定義の順序は以下のとおりでなければなりません.必須パラメータ デフォルトパラメータ 可変パラメータ 名前付きキーワードパラメータ キーワードパラメータ 例:
任意の関数は、パラメータがどのように定義されているかにかかわらずfunc(*args,*kw)のような形式(メタグループと辞書)で呼び出すことができます.
1.6.戻り値 returnを使用して関数から戻り(ジャンプ)、値を返すこともできます. pythonプログラムデフォルトはNone を返します. returnは複数の値(実際には1つのメタグループを返し、括弧を省略し、複数の変数に直接付与) を返すことができる.
1.7. DocStringsは、関数に説明文を埋め込むことができる. 三重引用符を使用すると、行にまたがって説明を書くことができます. 使用_doc__メソッドで、説明文を呼び出すことができます.
1.8.関数の別名
関数名は実際には関数の参照を指すので、関数名を変数に割り当てることができ、その後、この変数から関数を呼び出すことができます.
1.9.関数式プログラミング
Pythonは関数式プログラミングに一部のサポートを提供する.Pythonは変数の使用を許可するため、Pythonは純粋な関数式プログラミング言語ではない.
2.高次関数
2.1.変数は関数を指すことができる
2.2.関数名も変数
関数名は、実は関数を指す変数です.例えばabs()という関数はabsが絶対値を計算する関数を指す変数である.
2.3.入力関数
1つの関数Aは、パラメータとして別の関数Bを受信することができ、この関数Aを高次関数と呼ぶ.
map()もreduce()も、いずれも高次関数
2.4.戻り関数
高次関数は関数をパラメータとして受け入れるほか、関数を結果値として返すこともできる.
3.匿名関数lambda lambdaは匿名関数 を定義した. lambdaは、プログラムの実行効率の向上をもたらすものではなく、コードをより簡潔にするだけです. lambdaには1つの式しかありません.returnを書く必要はありません.戻り値は式の値です. for...in...ifを使って完成できれば、lambdaは絶対に使いません. lambdaを使用する場合、lambdaにはループが含まれないでください.ある場合は、関数を定義して完了し、コードの再利用性とより良い読み取り性を得ることができます.
上記filterは、[x for x in foo if x%x==0]上記mapは、[x*2+10 for x in foo]に書き換えることができる
4.アクセサリー
役割:関数の機能を強化しますが、関数定義自体を変更しません.
例1:
現在の呼び出し関数の名前を印刷し、パラメータとして関数を受け入れ、関数を返す装飾器を定義します.
装飾器(log)を他の関数(now)に作用させると、now=log(now):now()を呼び出し、now自体を実行する前に1行のlogを印刷します
例2、装飾器を定義し、関数呼び出しの回数と関数実行時間を印刷する
テスト:
5.バイアス関数構文:functools.partial(関数オブジェクト、*args、**kwargs) パラメータ:関数オブジェクト、位置パラメータ、命名パラメータ Pythonのfunctoolsモジュールは多くの機能を提供しており、そのうちの1つはバイアス関数(Partial Function)である.functools.partial機能:バイアス関数を作成しますが、バイアス関数を自分で定義する必要はありません.
たとえば、2進数文字列を10進数整数に変換すると、関数int 2を定義できます.
これにより、デフォルトでは2進文字列が処理する.
しかし、関数int 2を自分で定義する必要はありません.バイアス関数を使用して目的を達成することができます.
functools.partialの役割:関数のいくつかのパラメータを固定(すなわちデフォルト値を設定)し、新しい関数を返します.ただし、int 2を呼び出すと、baseパラメータを他の値として指定できます.
例1:
例2:
次のようなプログラムを例にとると
def add(a,b=0): # a b , b=0
c = a+b # c
global d, e # d e
d = a*b
e = a+b
x=8
y=9
add(x, y) # x y
1.1形式パラメータ/実際のパラメータ
形式パラメータ:関数定義時に書かれ、メモリ領域は割り当てられていませんが、定義で使用できるパラメータです.例:def(a,b=0).実際のパラメータ:関数呼び出し時に関数に渡される変数.これは、システムがメモリ空間を実質的に割り当てた変数です.
1)パラメータはデフォルト値def func(a,b=5,c=10)を定義することができるが、パラメータテーブルの末尾にあるパラメータのみがデフォルトパラメータ値を持つことができ、例えばdef func(a,b=5)が有効であり、def func(a=5,b)が無効である.2)パラメータリストの後にデフォルト値を持つパラメータを表示し、デフォルト値のないパラメータの前に表示されるとエラーが発生します.
1.2位置パラメータ/キーワードパラメータ
位置パラメータ:入力された値は、関数のパラメータに位置順に順次割り当てられます.例えばpower(x,n)、キーワードパラメータ:パラメータに割り当てられたパラメータとして名前を付けることで、位置を考慮する必要はありません.例えばfunc(25,c=24);
キーワードパラメータを使用するメリット:1)パラメータの順序を心配する必要はありません.2)他のパラメータにデフォルト値がある場合は、希望するパラメータにのみ値を割り当てることができます.
1.3パラメータの数は不確定であることができる
1.3.1アスタリスクの使用*
関数を定義するときに、パラメータの前に*番号を付けると、パラメータはtupleを受信します.
>>> def calc(*numbers):
... s = 0
... for n in numbers: # numbers tuple, ,
... s += n**2
... return s
...
>>> L0 = [0,1,2,3]
>>>
>>> # : list/tuple * , list/tuple
>>> calc(*L0)
14
>>> # List, , List ,
>>> # list int 。
>>> calc(L0)
Traceback (most recent call last):
File "", line 1, in
File "", line 4, in calc
TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'int'
アスタリスクは通常の文では使用できません
>>> *L0
File "", line 1
SyntaxError: can't use starred expression here
>>> a,b,c,d = *L0
File "", line 1
SyntaxError: can't use starred expression here
>>> a,b,c,d = (*L0)
File "", line 1
SyntaxError: can't use starred expression here
>>> (a,b,c,d) = (*L0)
File "", line 1
SyntaxError: can't use starred expression here
>>>
注意:
1.3.2双星を使用**
*kwを使用して、0つ以上のパラメータ名を含むパラメータを入力します.これらのキーワードパラメータは、関数内部でdictとして組み立てられます.キーワードパラメータを使用して関数の機能を拡張します.
>>> def person(name, age, **kw):
... print(‘name:’, name, ‘, age’, age, ‘, others:’ kw)
...
>>> person(‘Michael’, 30) #
name:Michael, age:30, others:{}
>>>
>>> person(‘Adam’, 45, gender=’M’, job=’Engineer’) # dict。
name:Adam, age:45, others:{‘gender’:’M’, ‘job’:’Engineer’}
>>>
>>> extra = {‘gender’:’M’, ‘job’:’Engineer’}
>>> person(‘Adam’, 45, **extra) # dict **, dict ;
name:Adam, age:45, others:{‘gender’:’M’, ‘job’:’Engineer’}
1.3.3. ***との役割
一般に*と**は、関数にパラメータを渡す場合にのみ使用されますが、関数パラメータの外ではあまり使用されません(エラーが発生する可能性もあります).
例えば、foo(1,2,3)はfoo(*[1,2,3])bar(a=1,b=2,c=3)はbar(*{‘a’:1,‘b’:2,‘c’:3})に相当する
*L 0はリスト(メタグループ)L 0を解体した結果と考えられる.
*の役割:リストを要素に分割します.L 0=[0,1,2,3]#L 0はlistであり、全体であり、L 0を関数に渡し、関数は1つのパラメータを得る.*L 0#L 0は4つの要素で、L 0を関数に渡し、関数は4つのパラメータを得ます.
**の役割は、dictを一連のキー値ペアに分解します.D 0={‘a’:0,‘b’:1}#D 0はdictであり,直接関数に伝達され,関数は1つのパラメータを得る.D 0#は2つのキー値のペアで、D 0を関数に渡し、関数は2つのパラメータを得ます.
1.4.キーワードパラメータの命名
*kwを使用:任意の名前のキーワードをパラメータとして渡すことができます.*,city,jobを使用すると、キーワードパラメータとしてcityとjobのみを受信するなど、キーワードパラメータの名前を制限できます.
>> def person(name, age, *, city, job):
.. print(name, age, city, job)
..
>> person(‘Jon’, 30, city=’Chengdu’, job=’Engineer’) # , ;
on 30 Chendu, Engineer
>>
>> extra = {‘city’:’Shenzhen’, ‘job’:’Art’}
>> person(‘Bill’, 9, **extra) # dict , ;
ill 9 Shenzhen Art
>>>
>>> extra ={‘job’:’Art’}
>>> person(‘Bill’, 9, **extra) # dict , : city ;
TypeError: person() missing 1 required keyword-only arg: ‘city’
>>>
>>> extra = {‘length’:6, ‘job’:’Art’}
>>> person(‘Bill’, 9, **extra) # dict , : length ;
TypeError: person() got a unexpected keyword arg: ‘length’
1.5.パラメータの組み合わせ
Python関数の5つのパラメータは任意に組み合わせて使用できます.パラメータ定義の順序は以下のとおりでなければなりません.
def f1(a, b, c=0, *args, **kw):
pass
def f2(a, b, c=0, *, d, **kw):
pass
任意の関数は、パラメータがどのように定義されているかにかかわらずfunc(*args,*kw)のような形式(メタグループと辞書)で呼び出すことができます.
1.6.戻り値
def move(x0, y0, s=0, angle=0):
x1=x0+s*math.cos(angle)
y1=y0+s*math.sin(angle)
return x1,y1
x,y = move(100,100, 50, math.pi*(1/3))
1.7. DocStrings
>>> def max(x,y):
... '''''Return the max of two number.
... The two number must be integer.'''
... if a>b:
... return a
... else:
... return b
...
>>> print max(1,2)
>>> print max.__doc__
1.8.関数の別名
関数名は実際には関数の参照を指すので、関数名を変数に割り当てることができ、その後、この変数から関数を呼び出すことができます.
>>> a = abs # a abs
>>> print(a(-1))
1
>>> print(a)
1.9.関数式プログラミング
Pythonは関数式プログラミングに一部のサポートを提供する.Pythonは変数の使用を許可するため、Pythonは純粋な関数式プログラミング言語ではない.
2.高次関数
2.1.変数は関数を指すことができる
>>> x = abs(-10) # , ;
>>> f = abs #
>>> print(f) #
>>> f(-10) # f abs,f(-10) abs(-10)
2.2.関数名も変数
関数名は、実は関数を指す変数です.例えばabs()という関数はabsが絶対値を計算する関数を指す変数である.
>>> import builtins
>>> builtins.abs
>>> builtins.abs = 10 # abs
2.3.入力関数
1つの関数Aは、パラメータとして別の関数Bを受信することができ、この関数Aを高次関数と呼ぶ.
>>> def func_add(f, x, y):
... return f(x)+f(y)
...
>>> abs_add(abs, 5, -6)
11
map()もreduce()も、いずれも高次関数
2.4.戻り関数
高次関数は関数をパラメータとして受け入れるほか、関数を結果値として返すこともできる.
3.匿名関数lambda
>>> foo = [2,18,9,22]
>>> list(filter(lambda x:x%3==0, foo)) # 3 ;
[18, 9]
>>> list(map(lambda x:x*2+10, foo)) # *2+10;
[14, 46, 28, 54]
>>> list(map(lambda x:[x,x*2], foo)) # list;
[[2, 4], [18, 36], [9, 18], [22, 44]]
>>> functools.reduce(lambda x,y:x+y, foo) # , ;
51
上記filterは、[x for x in foo if x%x==0]上記mapは、[x*2+10 for x in foo]に書き換えることができる
4.アクセサリー
役割:関数の機能を強化しますが、関数定義自体を変更しません.
例1:
現在の呼び出し関数の名前を印刷し、パラメータとして関数を受け入れ、関数を返す装飾器を定義します.
>>> def log(func):
... def wrapper(*args, **kwargs):
... print(‘call func: {name}: ’.format(name=func.__name__))
... return func(*args, **kwargs)
... return wrapper
装飾器(log)を他の関数(now)に作用させると、now=log(now):now()を呼び出し、now自体を実行する前に1行のlogを印刷します
>>> @log
... def now():
... print(datetime.datetime.now())
...
>>> import datetime # now import
>>> now()
call func: now
2018-07-27 11:29:18.239895
例2、装飾器を定義し、関数呼び出しの回数と関数実行時間を印刷する
import time
def timer(func):
lst = [0, 0] # list , ,lst ;
def wrapper(*args, **kwargs):
start = time.time()
r = func(*args, **kwargs) # ,
end = time.time()
delta = end –start
lst[0] += 1 # lst[0]
lst[1] += delta # lst[1]
print(f‘cnt: {lst[0]}, time: {lst[1]}, {delta}’)
return r # , , ;
return wrapper #
テスト:
>>> @timer
>>> def my_sum(n): #
... r = 0
... for i in range(n):
... r += i
... return r
...
>>> for i in range(10):
... r = my_sum(10000000)
...
cnt 1, time 0.937***, 0.937***
cnt 2, time 1.852***, 0.914***
cnt 3, time 2.747***, 0.895***
cnt 4, time 3.681***, 0.934***
cnt 5, time 4.601***, 0.919***
cnt 6, time 5.563***, 0.962***
cnt 7, time 6.494***, 0.930***
cnt 8, time 7.403***, 0.909***
cnt 9, time 8.374***, 0.970***
cnt 10, time 9.280***, 0.906***
5.バイアス関数
たとえば、2進数文字列を10進数整数に変換すると、関数int 2を定義できます.
def int2(x, base=2):
return int(x, base=base)
これにより、デフォルトでは2進文字列が処理する.
しかし、関数int 2を自分で定義する必要はありません.バイアス関数を使用して目的を達成することができます.
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2(‘00010000’)
16
functools.partialの役割:関数のいくつかのパラメータを固定(すなわちデフォルト値を設定)し、新しい関数を返します.ただし、int 2を呼び出すと、baseパラメータを他の値として指定できます.
>>> int2(‘00010000’,base=10)
10000
例1:
>>> int2 = functools.partial(int, base=2)
>>> int2(‘00010000’)
>>>
>>> # :
>>> kwargs = {‘base’:2} # ’base’:2 kwargs
>>> int(‘00010000’, **kwargs)
例2:
>>> max_with_10 = functools.partial(max, 10)
>>> max_with_10(5, 6, 7)
>>>
>>> # :
>>> args=(10, 5, 6, 7) # 10 *args
>>> max(*args)