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.関連概念
    次のようなプログラムを例にとると
    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
    >>>
    

    注意:
  • *numbersという書き方は、関数パラメータのリスト、関数を呼び出すときのパラメータ伝達の2つの文にしか現れません.通常の文(関数内部の文を含む)でアスタリスクを使用すると、エラーが発生します.
  • は、関数パラメータリストで使用されます.この場所には実際に複数のパラメータがあるが、関数内部で1つのtupleにマージされて使用されていることを示します.
  • は、関数パラメータがList/Topleではなくその要素であるため、関数パラメータを呼び出すときに使用されます.
  • *numbersは通常の文に書かれており、構文エラー: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のみを受信するなど、キーワードパラメータの名前を制限できます.
  • に対応するパラメータがパラメータ名に入力されなければならない(「city」=「Chengdu」という方法でパラメータ名が入力されている)が、パラメータ名がない場合は位置パラメータとみなされ、Errorを招く可能性がある.
  • 関数を定義するときにデフォルト値を与えると、呼び出し時にこのパラメータを渡さなくてもよい.
  • >> 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.戻り値
  • returnを使用して関数から戻り(ジャンプ)、値を返すこともできます.
  • pythonプログラムデフォルトはNone
  • を返します.
  • returnは複数の値(実際には1つのメタグループを返し、括弧を省略し、複数の変数に直接付与)
  • を返すことができる.
    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
  • は、関数に説明文を埋め込むことができる.
  • 三重引用符を使用すると、行にまたがって説明を書くことができます.
  • 使用_doc__メソッドで、説明文を呼び出すことができます.
  • >>> 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
  • lambdaは匿名関数
  • を定義した.
  • lambdaは、プログラムの実行効率の向上をもたらすものではなく、コードをより簡潔にするだけです.
  • lambdaには1つの式しかありません.returnを書く必要はありません.戻り値は式の値です.
  • for...in...ifを使って完成できれば、lambdaは絶対に使いません.
  • lambdaを使用する場合、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.バイアス関数
  • 構文:functools.partial(関数オブジェクト、*args、**kwargs)
  • パラメータ:関数オブジェクト、位置パラメータ、命名パラメータ
  • Pythonのfunctoolsモジュールは多くの機能を提供しており、そのうちの1つはバイアス関数(Partial Function)である.functools.partial機能:バイアス関数を作成しますが、バイアス関数を自分で定義する必要はありません.
    たとえば、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)