流暢的python讀書筆記-第五章 一等函數

高階函數

接受函數爲參數,或者把函數做爲結果返回的函數是高階函數
def reverse(word):
        return word[::-1]
    
    
    fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
    
    print(reverse('testing'))
    
    print(sorted(fruits, key=reverse))

all 和 any 也是內置的歸約函數。

all(iterable)

若是 iterable 的每一個元素都是真值,返回 True;all([]) 返回True。html

any(iterable)

只要 iterable 中有元素是真值,就返回 True;any([]) 返回False。python

匿名函數

fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']

print(sorted(fruits, key=lambda word: word[::-1]))

可調用對象

若是類定義了 call 方法,那麼它的 實例 能夠做爲函數調用。程序員

所以判斷對象可否調用,最安全的方法是使用內置的 callable() 函數編程

實現 call 方法的類是建立函數類對象的簡便方式,安全

函數內省

用戶定義的函數的屬性 page 252app

案例 生成html標籤的函數

def tag(name, *content, cls=None, **attrs):
    """生成一個或多個HTML標籤"""

    if cls is not None:
        attrs['class'] = cls

    if attrs:
        attr_str = ''.join(' %s="%s"' % (attr, value)
                           for attr, value
                           in sorted(attrs.items()))
    else:
        attr_str = ''

    if content:
        return '\n'.join('<%s%s>%s</%s>' % (name, attr_str, c, name) for c in content)
    else:
        return '<%s%s />' % (name, attr_str)


print(tag('br'))

print(tag('p', 'hello'))

print(tag('p', 'hello', 'world'))

print(tag('p', 'hello', 'world', cls='sidebar'))

獲取關於參數的信息

import bobo
@bobo.query('/')
def hello(person):
return 'Hello %s!' % person

bobo.query 裝飾器把一個普通的函數(如 hello)與框架的請求處理
機制集成起來了。框架

Bobo 會內省 hello 函數,發現它須要一個名爲 person
的參數,而後從請求中獲取那個名稱對應的參數,將其傳給 hello 函
數,所以程序員根本不用觸碰請求對象。ide

提取關於函數參數的信息

使用 inspect 模塊函數式編程

from clip import clip
from inspect import signature
sig = signature(clip)

print(sig)


print(str(sig))

for name, param in sig.parameters.items():
    print(param.kind, ':', name, '=', param.default)

inspect.signature 函數返回一個inspect.Signature 對象函數

  • 它有一個 parameters 屬性,這是一個有序映射,
  • 把參數名和 inspect.Parameter 對象對應起來。
  • 各個Parameter 屬性也有本身的屬性,
  • 例如 name、default 和 kind。特殊的 inspect._empty 值表示沒有默認值

kind 屬性的值是 _ParameterKind 類中的 5 個值之一,列舉以下。

  • POSITIONAL_OR_KEYWORD

    能夠經過定位參數和關鍵字參數傳入的形參(多數 Python 函數的參數屬於此類)。
  • VAR_POSITIONAL

    定位參數元組。
  • VAR_KEYWORD

    關鍵字參數字典。
  • KEYWORD_ONLY

    僅限關鍵字參數(Python 3 新增)。
  • POSITIONAL_ONLY

    僅限定位參數;

inspect.Signature 對象有個 bind 方法,

它能夠把任意個參數綁定到簽名中的形參上,所用的規則與實參到形參的匹配方式同樣。
框架可使用這個方法在真正調用函數前驗證參數,

示例 5-18 把tag 函數(見示例 5-10)的簽名綁定到一個參數字典

>>> import inspect
>>> sig = inspect.signature(tag) ➊
>>> my_tag = {'name': 'img', 'title': 'Sunset Boulevard',
... 'src': 'sunset.jpg', 'cls': 'framed'}
>>> bound_args = sig.bind(**my_tag) ➋
>>> bound_args
<inspect.BoundArguments object at 0x...> ➌
>>> for name, value in bound_args.arguments.items(): ➍
... print(name, '=', value)
...
name = img
cls = framed
attrs = {'title': 'Sunset Boulevard', 'src': 'sunset.jpg'}
>>> del my_tag['name'] ➎
>>> bound_args = sig.bind(**my_tag) ➏
Traceback (most recent call last):
...
TypeError: 'name' parameter lacking default value

❷ 把一個字典參數傳給 .bind() 方法。
❸ 獲得一個 inspect.BoundArguments 對象。
❹ 迭代 bound_args.arguments(一個 OrderedDict 對象)中的元
素,顯示參數的名稱和值。
❺ 把必須指定的參數 name 從 my_tag 中刪除。
❻ 調用 sig.bind(**my_tag),拋出 TypeError,抱怨缺乏 name 參
數。

函數註解

def clip(text: str, max_len: 'int > 0' = 80) -> str:
    print(text, max_len)


clip("sdf", 18)

print(clip.__annotations__)
  • 若是想註解返回值,在 ) 和函數聲明末尾的 : 之間添加 -> 和一個表達式。
  • 各個參數能夠在 : 以後增長註解表達式。若是參數有默認值,註解放在參數名和 = 號之間。
註解不會作任何處理,只是存儲在函數的 annotations 屬性(一
個字典)中:

operator模塊

reduce計算階乘

from functools import reduce


# 階乘
def fact(n):
    print(reduce(lambda a, b: a * b, range(1, n + 1)))


# operator.mul 函數計算階乘
from functools import reduce
from operator import mul


def fact2(n):
    return reduce(mul, range(1, n + 1))

print(fact2(3))

itemgetter

展現了 itemgetter 的常見用途:根據元組的某個字段給元
組列表排序。在這個示例中,按照國家代碼(第 2 個字段)的順序打印
各個城市的信息。

metro_data = [
    ('Tokyo', 'JP', 36.933, (35.689722, 139.691667)),
    ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
    ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
    ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
    ('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
]

### 演示使用 itemgetter 排序一個元組列表

from operator import itemgetter

for city in sorted(metro_data, key=itemgetter(1)):
    print(city)

若是把多個參數傳給 itemgetter,它構建的函數會返回提取的值構成
的元組:

cc_name = itemgetter(1, 0)
for city in metro_data:
    print(cc_name(city))

attrgetter

此外,若是參數名中包含 .(點號),attrgetter 會深
入嵌套對象,獲取指定的屬性。

from collections import namedtuple

metro_data = [
    ('Tokyo', 'JP', 36.933, (35.689722, 139.691667)),
    ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
    ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
    ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
    ('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
]

## 就像數據格式化同樣 數據帶上標籤
LatLong = namedtuple('LatLong', 'lat long')

Metropolis = namedtuple('Metropolis', 'name cc pop coord')

metro_areas = [Metropolis(name, cc, pop, LatLong(lat, long))
               for name, cc, pop, (lat, long) in metro_data]

print(metro_areas[0])
print(metro_areas[0].coord.lat)

#
from operator import attrgetter

name_lat = attrgetter('name', 'coord.lat')

for city in sorted(metro_areas, key=attrgetter('coord.lat')):
    print(name_lat(city))

methodcaller 自行建立函數

它會自行建立函數。methodcaller 建立的函數會在對象上調用參數指定的方法
本身建立函數

from operator import methodcaller
s = 'The time has come'
upcase = methodcaller('upper')

print(upcase)

hiphenate = methodcaller('replace', ' ', '-')
print(hiphenate(s))

functools.partial凍結參數

functools.partial 這個高階函數用於部分應用一個函數。部分應用
是指,基於一個函數建立一個新的可調用對象,把原函數的某些參數固定。
from operator import mul
from functools import partial

print(mul(3, 7))
# 第一個函數, 第二個固定的參數
triple = partial(mul, 3)
print(list(map(triple, range(1, 10))))

小總結

高階函數

  • 接受函數爲參數,或者把函數做爲結果返回的函數是高階函數.
  • Python 中經常使用的高階函數有內置函數
  • sorted、min、max 和 functools. partial

實例 直接函數化運行

  • 從 lambda 表達式建立的簡單函數到實現__call__ 方法的類實例。
  • 這些可調用對象都能經過內置的callable() 函數檢測。

函數註解

  • 在 inspect 模塊的幫助下,能夠讀取它們。
  • 例如,Signature.bind 方法使用靈活的規則把實參綁定到形參上,這與 Python 使用的規則同樣。

operator 模塊

  • 介紹了 operator 模塊中的一些函數,
  • 以及functools.partial 函數,
  • 有了這些函數,函數式編程就不太須要功能有限的 lambda 表達式了

其餘

  • all 和 any 也是內置的歸約函數.
  • 用來判斷是否全部都爲真,或者有一個爲真
相關文章
相關標籤/搜索