python関数|伝参、戻り値、作用域

38037 ワード

一、関数初見
関数の生成:関数は機能を実装するコードセグメントです.
li = ['spring', 'summer', 'autumn', 'winter']
def function():
    count = 0
    for j in li:
        count += 1
    print(count)
function()        # 4
  • defキーワードは、関数
  • を定義します.
  • function関数名の表記規則は変数と同じです.
  • 括弧は参照用です.
  • 関数体は、関数内の論理コード
  • です.
    コードが上から下にかけて実行され、def function()に実行されると、functionという変数名を一時メモリにロードしますが、実行しません.
    関数の実行:関数名+() 
     
    __を使うname_メソッドを使用して関数名を取得します.doc_uうメソッド取得関数の説明  
    def func1():
        """
                   ,     ...  。
        return:           (True,False)
        """
        print(666)
    
    func1()
    print(func1.__name__)         #     
    print(func1.__doc__)         #          
        :
    666
    func1
               ,     ...  。
    return:           (True,False)
    これは何に使いますか?例えばログ機能は、誰がいつ、どの関数を呼び出して、関数が何をするかをプリントアウトする必要があります.何度も時間がかかります.この時、関数の有益な情報を得る必要があります.
     
    1. 関数の戻り値
    関数を書きます.関数にprintを書かないでください. 関数は機能をガイドにしています.テストの時以外はprint()を書くことができます.
  • は、関数において、return終了関数
  • に遭遇する.
    def fun():
        print(111)
        return
        print(444)
    fun() 
        :111
  • は、関数の使用者
  • に値を返す.
    def fun():
        a = 134
        return a
    print(fun()) 
        :123
    1)リセットなし
    def fun():
        pass
    print(fun()) 
    None
    2)return 1つの値.この値は何ですか?直接関数の引数、関数名()に戻ります.
    def fun():
        return [1,2,3]
    print(fun()) 
        :[1, 2, 3]
    3)return複数の値は複数の値を一つのタプルに入れ、関数の引数の引数に返します.
    def fun():
        return 1,2,[33,44],'abc'
    print(fun()) 
        :
    (1, 2, [33, 44], 'abc')
    2. 関数の参照
    (1)実参:関数実行者の中のパラメータを実参といいます.
    ①位置パラメータ:順番に、一々対応する
    def func(a,b,c):
        print(a)
        print(b)
        print(c)
    
    func('fdsafdas',3,4) 
        :
    fdsafdas
    3
    4
    もしパラメータが一つ足りないなら?
    def func(a,b,c):
        print(a)
        print(b)
        print(c)
    
    func(3,4) 
        :TypeError: func() missing 1 required positional argument: 'c'
    いちいち対応しなければなりません.
    def compare(x,y):
        ret = x if x > y else y   #    ,     if else    
        return ret
    
    print(compare(123,122334))        # 122334
    ②キーワードパラメータ:順番でなくてもいいですが、いちいち対応しなければなりません.
    def compare(x,y):
        ret = x if x > y else y
        return ret
    print(compare(y=13,x=1))
        :13
    ③混合パラメータ:キーワードパラメータは位置パラメータの後ろに必ずあります.
    def func1(a,b,c,d,e):
        print(a)
        print(b)
        print(c)
        print(d)
        print(e)
    
    func1(1,4,d=2,c=3,e=5) 
        :
    1
    4
    3
    2
    5
    (2) イメージ:
    ①位置パラメータ:順番と実務に対応し、位置パラメータは値を伝えなければなりません.
    def func(a,b,c):
        print(a)
        print(b)
    print(c)
    
    func('fdsafdas',3,4) 
        :
    fdsafdas
    3
    4
    ②デフォルトのパラメータ:パラメータが上書きされ、パスしないとデフォルトで、デフォルトのパラメータは常に位置パラメータの後ろにあります.
    例1.
    def func(a,b=666):
        print(a,b)
    func(1,2) 
        :1 2
    例2.
    def func(a,b=666):
        print(a,b)
    func(1) 
    
        :1 666
    一つの場面を挙げます.担任が社員情報表に記入します.二つの問題があります.第一、男性が多いです.第二に、関数機能を完成しました.
    def  Infor(username,sex=' '):
        with open('name_list',encoding='utf-8',mode='a') as f1:
            f1.write('{}\t{}
    '.format(username,sex)) while True: username = input(' ( 1 ):').strip() if '1' in username: username = username[1:] # 1 Infor(username) else: Infor(username,' ')
    ③ダイナミックパラメータ:関数の参照数が一定でない場合、ダイナミックパラメータが使用できます.&argsと**kwargsで受信し、argsは母集団タイプで、キーパッドペア以外のパラメータ(受信位置パラメータ)を受信し、kwargsは辞書タイプで、キーパッドペア(キーワードパラメータ)を受信し、辞書に保存します.
    def func(*args,**kwargs):
        print(args,type(args))
        print(kwargs,type(kwargs))
    
    func(1,2,3,4,'alex',name = 'alex')
         :
    (1, 2, 3, 4, 'alex') 
    {'name': 'alex'} 
    「*」の魔性作用
    (1)関数定義時:*位置パラメータと*キーワードパラメータは、集約を表します.
    すべての実参照の位置パラメータを一つの元のグループにまとめ、このタプルをargsに割り当てます.重要なパラメータの前に「*」を加えると、実際に参加したキーワードパラメータを辞書に集めて、この辞書をkwargsに割り当てます.
    2つのリストのすべての要素をargsに割り当てます.
    def func(*args):
        print(args)
    
    l1 = [1,2,30]
    l2 = [1,2,33,21,45,66]
    func(*l1)
    func(*l1,*l2) 
        :
    (1, 2, 30)
    (1, 2, 30, 1, 2, 33, 21, 45, 66)
    二つの辞書を**kwargsに伝えます.
    def func(**kwargs):
        print(kwargs)
    
    dic1 = {'name':'jack','age':22}
    dic2 = {'name1':'rose','age1':21}
    func(**dic1,**dic2) 
        :
    {'name': 'jack', 'age': 22, 'name1': 'rose', 'age1': 21}
    def func(*args,**kwargs):
        print(args)
        print(kwargs)
    
    func(*[1,2,3], *[4,5,6], **{'name':'alex'}, **{'age':18})    #   func([1,2,3,4,5,6], {'name':'alex','age':18})
     
     

    (2)在函数的调用执行时,打散

       *可迭代对象,代表打散(list,tuple,str,dict(键))将元素一一添加到args。

       **字典,代表打散,将所有键值对放到一个kwargs字典里。

    def func(*args,**kwargs):
        print(args,kwargs)
    
    dic1 = {'name':'jack','age':22}
    dic2 = {'name1':'rose','age1':21}
    
    func(*[1,2,3,4],*'asdk',**dic1,**dic2) 
        :(1, 2, 3, 4, 'a', 's', 'd', 'k') {'age1': 21, 'name': 'jack', 'age': 22, 'name1': 'rose'}
    イメージの順序:位置パラメータ-->args-->キーワードパラメータ---->デフォルトパラメータ ------->**kwargs
    *argsパラメータは、デフォルトでは空()、****kwargsダイナミックなパラメータではなく、すべてのキーワードパラメータ(未定義)を辞書に入れます.
    def func(a,b,c,d,*args,e=' ',**kwargs):
        print(a,b,c,d,args,e,kwargs)
    
    func(1,2,3,4,5,6,7,v=3,m=7,h=9,e=' ') 
    1 2 3 4 (5, 6, 7)   {'v': 3, 'h': 9, 'm': 7}
    def func(a,b,c,**kwargs):
        print(kwargs)
    func(1,2,r=4,b1=5,c1=6,c=7) 
    
        :{'r': 4, 'c1': 6, 'b1': 5}
    エラーが発生していないのは、関数がパラメータを受信した後、左から右に探して、最後にc=7パラメータを見つけました.a、b、cの中で定義されていますので、出力の辞書には現れていません.kwargsは未定義のキーワードパラメータを返します.
    関数に複数の未知のパラメータが含まれている場合、通常は以下のフォーマットを使います.
    def func1(*args,**kwargs):
        pass
    func1() 
    二、名前空間とスコープ
    関数を実行する時、彼はメモリの中で一時的な名前空間を開拓して、関数の体内のすべての変数と値の関係を保存して、関数の実行が終わると、臨時の空間は自動的に閉じます.
     
    関数内の変数は、関数の外で直接参照できますか?
    def func1():
        m = 1
        print(m)
    
    print(m)                          # NameError: name 'm' is not defined
    上記はなぜエラーを報告しましたか?python内部の原理を分析してみます.
    まず、Pythonコードが実行されているときの関数との出会いを思い出します.Pythonインタプリタから実行を開始した後、メモリの中に一つの空間を開きます.変数が発生するたびに、変数名と値との間の対応関係を記録しますが、関数定義があるときには、関数名をメモリに読み込むだけです.この関数が存在していることを示します.関数内部の変数や論理については、解釈器はまったく関心がありません.関数が呼び出されると、Python解釈器はメモリをもう一つ開けてこの関数の内容を保存します.この時、関数の中にどの変数があるかに注目します.関数内の変数は新しく開発されたメモリに保存されます.関数内の変数です.関数の内部でのみ使用できます.関数の実行が終わると、このメモリの内容は全部空になります.
    1. 名前空間とスコープ
    名前空間:保存”名前と値の関係の空間”
    ①グローバル名前空間:コードが実行中に作成された記憶”変数名と値の関係”のメモリ空間
    ②ローカル名前空間:関数呼び出し時に一時的に開いた空間は、関数の実行が完了するとクリアされます.
    ③名前空間の内蔵:python解釈器が提供してくれた名前:input、print、str、list、tuple…これらは私たちが熟知しているので、持ってきても使える方法です.
     
    作用域:作用範囲です.
    ①グローバルスコープ:グローバル名前空間、名前空間を内蔵します.ファイル全体の任意の位置で参照され、グローバル効果があります.
    ②ローカルスコープ:ローカル名前空間は、ローカル範囲内でのみ有効となります.
     
    読み込み順序:
    名前空間を内蔵(プログラム実行前にロード)-->  グローバル名前空間(プログラム実行中に上から下にロード)->ローカル名前空間(プログラム実行中:呼び出し時にロードする)
     
    値を取る順序:
    ローカル呼び出し:ローカル名前空間->グローバル名前空間->名前空間を内蔵する
    グローバル呼び出し:グローバル名前空間->名前空間を内蔵する
     
    以上のように、変数を探すときは、小さな範囲から大きな範囲までを一階ずつ探していきます.
     
    ローカル変数の例
    name = 'summer'
    def func1():
        name = 'spring'
        print(name)
    func1()
        :spring

    name = 'summer'
    def func1():
        print(name)
    func1() 
     実行出力:summer
    コードは上から下まで順次実行されます.関数は上から下まで順次実行されます.
    print(111)
    def func1():
        print(333)
        func2()
        print(666)
    def func2():
        print(444)
    def func3():
        print(555)
        func2()
    
    func1()
    print(222) 
        :
    111
    333
    444
    666
    222
    def f1():
        def f2():
            def f3():
                print("in f3")
            print("in f2")
            f3()
        print("in f1")
        f2()
    f1() 
        :
    in f1
    in f2
    in f3
    2. globalsとlocasの方法
    print(globals())         #
    print(locals())        #          ,   (  
    globals()とlocars()は一般的にはあまり使われていません.関数論理が複雑な場合に使用されるかもしれません.
    li = ['spring', 'summer', 'autumn', 'winter']
    
    def func():
        a = 1
        b = 2
        print('func', globals())
        print('func', locals())
    
        def func1():
            c = 3
            d = 4
            print('func1', globals())
            print('func1', locals())
    
        func1()
    
    func()
    出力結果
    func {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.sourcefileloader object="" at="">, '__spec__': None, '__annotations__': {}, '__builtins__': 'builtins' (built-in)>, '__file__': 'C:/Users/Administrator/houseinfo/test.py', '__cached__': None, 'li': ['spring', 'summer', 'autumn', 'winter'], 'func': }
    func {'b': 2, 'a': 1}
    func1 {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.sourcefileloader object="" at="">, '__spec__': None, '__annotations__': {}, '__builtins__': 'builtins' (built-in)>, '__file__': 'C:/Users/Administrator/houseinfo/test.py', '__cached__': None, 'li': ['spring', 'summer', 'autumn', 'winter'], 'func': }
    func1 {'d': 4, 'c': 3}
     (1)global:
    ①ローカル名前空間でグローバル変数を宣言する
    def func2():
        global name
        name = 'summer'
    
    func2()
    print(name)
        :summer
    ②グローバル変数は、ローカル名前空間で変更されます.
    count = 1
    def func1():
        global count
        count = count + 1
        print(count)
    func1()
    print(count)

    2
    2
    大域変数countは関数体のglobal countによって 上書きしました
    (2)nonlocal
    ①親関数の変数をサブ関数で変更します.この変数はグローバル変数ではありません.
    a = 4
    def func1():
        nonlocal a
        a = 5             #      
        #print(name)
    func1()
    print(a) 
        :SyntaxError: no binding for nonlocal 'a' found
    ②ローカルスコープでは、親レベルのスコープの変数を参照して修正し、どのレイヤーを参照するかは、その層および以下の変数からすべて変わります.
    例1
    def func1():
        b = 6
        def func2():
            b = 666
            print(b)
        func2()
        print(b)                 #      
    func1() 
        :
    666
    6
    例2
    def func1():
        b = 6
        def func2():
            nonlocal b          #        ,   func1()
            b = 666             #    
            print(b)
        func2()    
       print(b)                 #    ,   b  ,  666
    func1() 
        :
    666
    666
    例3*********
    def aa():                     #  ccl  
        b = 42
        def bb():
            b = 10                 #      ,b  10
            print(b)
            def cc():
                nonlocal b             #      ,   bb()
                b = b + 20             #b=10+20    30
                print(b)
            cc()
            print(b)
        bb()
        print(b)
    aa()
        :
    10
    30
    30
    42
    注意
    a = 5
    def func1():
        a += 1
        print(a)
    func1() 
    エラーを実行します.この関数はグローバル変数を変更しました.操作は許可されていません.関数の内部はグローバル変数を参照することができます.変更はできません.globalが必要です.
    a = 5
    def func1():
        global a
        a += 1
        print(a)
    
    func1()     #  6