Python関数と変数の役割ドメイン

39806 ワード

関数と変数の役割ドメイン
一、関数
1.1関数定義
def    ([  1][,  2][,  3]...):
  [    ]#     return        
  [return [   ]]#return         

1.2関数呼び出し
Pythonでは、すべての文がリアルタイムで実行され、C/C++のコンパイルプロセスは存在せず、defも実行可能な文であり、関数を定義します.関数の呼び出しは定義後にしなければなりません

>>> def add(a,b):
...   return a+b
...
>>> add
<function add at 0x0000000005DAB730>
>>> add(1,2)
3
>>> x=add
>>> x(1,2)
3
>>> def nullFun(a,b):
...   return
...
>>> nullFun(1,2)
>>> 

1.3関数パラメータ
関数を呼び出すと、パラメータテーブルに提供されるパラメータが実際のパラメータとなり、実参と略称されます.Pythonでは、変数はC/C++のポインタに似たオブジェクトの参照を保存します.実パラメータをパラメータに渡すことは、オブジェクト参照をパラメータに割り当てることです.
関数の多態性
マルチステートはオブジェクト向けの特徴であり、同じ動作が異なるオブジェクトに対して異なる結果を得る可能性があることを意味します.Pythonのオブジェクトにはタイプ属性がなく、変数は様々なタイプのオブジェクトを飲むことができます.同じ関数では,伝達される実際のパラメータタイプが異なり,異なる結果が得られ,多態性を体現する.例:
>>> def add(a,b):
...   return a+b
...
>>> add(1,3)
4
>>> add(1,1.5)
2.5
>>> add('abc', 'def')
'abcdef'
>>> add([1,3],[2,4])
[1, 3, 2, 4]

パラメータ代入伝達
Pythonでは、実パラメータをパラメータに渡すことを指定して、パラメータに値を割り当てることができます.例:

>>> def add(a,b):return a+b
...
>>> add(a='ab',b='cd')
'abcd'
>>> add(b='ab',a='cd')
'cdab'

この方式を用いると,パラメータ順序はパラメータ付与値に準じて無視できることが分かる.
パラメータ転送と共有リファレンス

>>> def f(x): x=100
...
>>> a=10
>>> f(a)
>>> a
10

Pythonでの付与時にオブジェクトへの変数の参照が確立されるため、関数にaを再付与しても、関数外のaには影響しないことがわかります.値を再割り当てすると、パラメータが新しいオブジェクトを参照し、元の参照が無効になったことを意味します.
可変パラメータの使用に注意

>>> def f(a):
...   a[0]='abc'
...
>>> x=[1,2]
>>> f(x)
>>> x
['abc', 2]

可変パラメータを使用する場合、リスト、辞書など、関数でパラメータを変更すると、共有参照であるため、変更後のオブジェクトも実パラメータで取得されます.以上のように.
関数内の変更が関数外の変数に影響を及ぼすことを望まない場合は、表示の回避も可能です.
たとえば、リストは、リストのコピーを実パラメータとして使用できます.次のようになります.

>>> def f(a):
...   a[0]='abc'
...
>>> x=[1,2]
>>> f(x[:])
>>> x
[1, 2]

関数内でリストをコピーすることもできますが、実パラメータは変数を使用します.たとえば

>>> def f(a):
...   a=a[:]
...
>>> def f(a):
...   a=a[:]
...   a[0]='abc'
...
>>> x=[1,2]
>>> f(x)
>>> x
[1, 2]

デフォルトのパラメータ
例えばc++
任意の数のパラメータを渡す
パラメータを定義する場合、パラメータ名には「*」が使用され、0個を含む任意のパラメータを受け入れることができ、これらのパラメータはメタグループに保存されます.
>>> def add(a,*b,c):
...   print(c)
...   s=a
...   for x in  b:
...     s+=x
...   return s
...
>>> add(1,2)
3
>>> add(1,2,3)
6
>>> add(1)
1

「*」パラメータの後にパラメータが残っている場合は、付与値で渡す必要があります.以上のように.
関数ネスト定義
内部定義の関数役割ドメインは関数内

>>> def add(a,b):
...   def getsum(x):
...     s=0
...     for n in x:
...       s+=ord(n)
...     return s
...   return getsum(a)+getsum(b)
...
>>> add('12', '34')
202

Lambda関数
Lambda関数も式関数となり、変数呼び出しによって変数に値を割り当てる匿名関数を定義します.Lambda関数定義の基本フォーマットは以下の通りです.
LambdaパラメータLambdaぱらめーた:式しき
次のようになります.

>>> add=lambda a,b:a+b
>>> add(1,2)
3
>>> add('ab','cd')
'abcd'

さいきかんすう
例えばC/C++
関数リスト
Pythonでは、関数をリストオブジェクトとして使用し、リストインデックスで関数を呼び出すことができます.次のようになります.
>>> add=lambda a,b:a+b #  lambda  
>>> add(1,2)
3
>>> add('ab','cd')
'abcd'
>>>
>>>
>>> d=[lambda a,b:a+b,lambda a,b:a*b]
>>> d[0](1,3)
4
>>> d[1](1,3)
3
>>>
>>>#  def  
>>> def add(a,b):
...   return a+b
...
>>> def fac(n):
...   if n==0:
...     return 1
...   else:
...     return n*fac(n-1)
...
>>> d=[add,fac]#             
>>> d[0](1,2)
3
>>> d[1](5)
120
>>> d=(add,fac)#             
>>> d[0](2,3)
5
>>> d[1](5)
120

ヒント:関数リストの本質は、メタグループ、リスト、辞書などのシーケンスで履歴書関数オブジェクトの参照であり、インデックスによって関数を呼び出します.
二、変数作用域
2.1役割ドメインタイプ
変数の役割ドメインは、変数のアクセス可能な範囲であり、ネーミングスペースとも呼ばれます.初めて変数に値を割り当てるとき、Pythonは変数を作成し、初めて変数に値を与える位置が変数の役割ドメインを決定します.
役割ドメインは大きいものから小さいものに分けられます:内蔵役割ドメイン>ファイル役割ドメイン>関数ネスト役割ドメイン>ローカル役割ドメイン
ローカル役割ドメイン:他の関数定義を含まない関数の内部がローカル役割になります.関数内で値を割り当てて作成された変数は、関数パラメータがローカルの役割ドメインに属します.
関数ネストの役割ドメイン:他の関数定義を含む関数の内部が関数ネストの役割ドメインになります.
ファイルの役割ドメイン:プログラムファイル(モジュールファイルとも呼ばれる)の内部がファイルの役割ドメイン
組み込み役割ドメイン:pythonの様々な事前定義変数と関数を含む最上位レベルの役割ドメインが組み込み役割ドメインとなります.
組み込み役割ドメインとファイル役割ドメインは、グローバル役割ドメイン(変数をグローバル変数と呼ぶ)となる場合があり、関数ネスト役割ドメインの利点もローカル役割ドメイン(変数をローカル変数とする)となります.
役割ドメイン外の変数は、役割ドメイン内の変数名と同時に「ローカル」優先原則に従い、外部の役割ドメインが遮断される--役割分離原則となる.C/C++と似ています.しかしC/C++とは異なり,より小さな役割ドメイン全体において,この繰返し変数を定義する前の範囲では,プログラムはその大きな役割ドメインの変数を検出できない.

>>> a=10
>>> def show():
...   print('a=',a)
...   a=100
...   print('a=',a)
...
>>> show()
Traceback (most recent call last):
  File "", line 1, in <module>
  File "", line 2, in show
UnboundLocalError: local variable 'a' referenced before assignment

2.2 global文
global文を使用して、関数内でグローバル変数を宣言します.グローバル変数はコードメンテナンスデバッグの難易度を増大させ、推奨しません.
>>> a=10
>>> def show():
...   global a#   ?           a ?
...   a+=1
...   print('a=',a)
...
>>> show()
a= 11
>>> show()
a= 12
>>> show()
a= 13

2.3 nonlocal文
役割ドメイン分離の原則は、関数内部のネスト関数にも適用されます.ネストされた関数内で上位関数のローカル変数と同じ名前の変数を使用する場合、その変数に値が割り当てられていない場合、その変数は上位関数のローカル変数です.次のようになります.

>>> def test():
...   a=10
...   def show():
...     print('in show(),a=',a)
...   show()
...   print('in test(),a=',a)
...
>>> test()
in show(),a= 10
in test(),a= 10

少し修正
>>> def test():
...   a=10
...   def show():
...     a=100
...     print('in show(),a=',a)
...   show()
...   print('in test(),a=',a)
...
>>> test()
in show(),a= 100
in test(),a= 100

このaを前のレイヤaと同じにするには、変数が外部のローカル変数であることを宣言するnonlocal aを追加する必要があります.
>>> def test():
...   a=10
...   def show():
...     nonlocal a
...     a=100
...     print('in show(),a=',a)
...   show()
...   print('in test(),a=',a)
...
>>> test()
in show(),a= 100
in test(),a= 100