摘要:可以通過(guò)定位參數(shù)和關(guān)鍵字參數(shù)傳入的形參多數(shù)函數(shù)的參數(shù)屬于此類。就像數(shù)據(jù)格式化一樣數(shù)據(jù)帶上標(biāo)簽自行創(chuàng)建函數(shù)它會(huì)自行創(chuàng)建函數(shù)。創(chuàng)建的函數(shù)會(huì)在對(duì)象上調(diào)用參數(shù)指定的方法自己創(chuàng)建函數(shù)凍結(jié)參數(shù)這個(gè)高階函數(shù)用于部分應(yīng)用一個(gè)函數(shù)。
高階函數(shù)
def reverse(word): return word[::-1] fruits = ["strawberry", "fig", "apple", "cherry", "raspberry", "banana"] print(reverse("testing")) print(sorted(fruits, key=reverse))all 和 any 也是內(nèi)置的歸約函數(shù)。
如果 iterable 的每個(gè)元素都是真值,返回 True;all([]) 返回True。
只要 iterable 中有元素是真值,就返回 True;any([]) 返回False。
匿名函數(shù)fruits = ["strawberry", "fig", "apple", "cherry", "raspberry", "banana"] print(sorted(fruits, key=lambda word: word[::-1]))可調(diào)用對(duì)象
如果類定義了 call 方法,那么它的 實(shí)例 可以作為函數(shù)調(diào)用。
因此判斷對(duì)象能否調(diào)用,最安全的方法是使用內(nèi)置的 callable() 函數(shù)
實(shí)現(xiàn) call 方法的類是創(chuàng)建函數(shù)類對(duì)象的簡(jiǎn)便方式,
函數(shù)內(nèi)省用戶定義的函數(shù)的屬性 page 252
案例 生成html標(biāo)簽的函數(shù)def tag(name, *content, cls=None, **attrs): """生成一個(gè)或多個(gè)HTML標(biāo)簽""" 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 " ".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"))獲取關(guān)于參數(shù)的信息
import bobo @bobo.query("/") def hello(person): return "Hello %s!" % person
bobo.query 裝飾器把一個(gè)普通的函數(shù)(如 hello)與框架的請(qǐng)求處理
機(jī)制集成起來(lái)了。
Bobo 會(huì)內(nèi)省 hello 函數(shù),發(fā)現(xiàn)它需要一個(gè)名為 person
的參數(shù),然后從請(qǐng)求中獲取那個(gè)名稱對(duì)應(yīng)的參數(shù),將其傳給 hello 函
數(shù),因此程序員根本不用觸碰請(qǐng)求對(duì)象。
使用 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 函數(shù)返回一個(gè)inspect.Signature 對(duì)象
它有一個(gè) parameters 屬性,這是一個(gè)有序映射,
把參數(shù)名和 inspect.Parameter 對(duì)象對(duì)應(yīng)起來(lái)。
各個(gè)Parameter 屬性也有自己的屬性,
例如 name、default 和 kind。特殊的 inspect._empty 值表示沒有默認(rèn)值
kind 屬性的值是 _ParameterKind 類中的 5 個(gè)值之一,列舉如下。
POSITIONAL_OR_KEYWORD
可以通過(guò)定位參數(shù)和關(guān)鍵字參數(shù)傳入的形參(多數(shù) Python 函數(shù)的參數(shù)屬于此類)。
VAR_POSITIONAL
定位參數(shù)元組。
VAR_KEYWORD
關(guān)鍵字參數(shù)字典。
KEYWORD_ONLY
僅限關(guān)鍵字參數(shù)(Python 3 新增)。
POSITIONAL_ONLY
僅限定位參數(shù);inspect.Signature 對(duì)象有個(gè) bind 方法,
它可以把任意個(gè)參數(shù)綁定到簽名中的形參上,所用的規(guī)則與實(shí)參到形參的匹配方式一樣。
框架可以使用這個(gè)方法在真正調(diào)用函數(shù)前驗(yàn)證參數(shù),
示例 5-18 把tag 函數(shù)(見示例 5-10)的簽名綁定到一個(gè)參數(shù)字典
上
>>> 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? >>> 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
? 把一個(gè)字典參數(shù)傳給 .bind() 方法。
? 得到一個(gè) inspect.BoundArguments 對(duì)象。
? 迭代 bound_args.arguments(一個(gè) OrderedDict 對(duì)象)中的元
素,顯示參數(shù)的名稱和值。
? 把必須指定的參數(shù) name 從 my_tag 中刪除。
? 調(diào)用 sig.bind(**my_tag),拋出 TypeError,抱怨缺少 name 參
數(shù)。
def clip(text: str, max_len: "int > 0" = 80) -> str: print(text, max_len) clip("sdf", 18) print(clip.__annotations__)
如果想注解返回值,在 ) 和函數(shù)聲明末尾的 : 之間添加 -> 和一個(gè)表達(dá)式。
各個(gè)參數(shù)可以在 : 之后增加注解表達(dá)式。如果參數(shù)有默認(rèn)值,注解放在參數(shù)名和 = 號(hào)之間。
注解不會(huì)做任何處理,只是存儲(chǔ)在函數(shù)的 annotations 屬性(一operator模塊 reduce計(jì)算階乘
個(gè)字典)中:
from functools import reduce # 階乘 def fact(n): print(reduce(lambda a, b: a * b, range(1, n + 1))) # operator.mul 函數(shù)計(jì)算階乘 from functools import reduce from operator import mul def fact2(n): return reduce(mul, range(1, n + 1)) print(fact2(3))itemgetter
展示了 itemgetter 的常見用途:根據(jù)元組的某個(gè)字段給元
組列表排序。在這個(gè)示例中,按照國(guó)家代碼(第 2 個(gè)字段)的順序打印
各個(gè)城市的信息。
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 排序一個(gè)元組列表 from operator import itemgetter for city in sorted(metro_data, key=itemgetter(1)): print(city)
如果把多個(gè)參數(shù)傳給 itemgetter,它構(gòu)建的函數(shù)會(huì)返回提取的值構(gòu)成
的元組:
cc_name = itemgetter(1, 0) for city in metro_data: print(cc_name(city))attrgetter
此外,如果參數(shù)名中包含 .(點(diǎn)號(hào)),attrgetter 會(huì)深
入嵌套對(duì)象,獲取指定的屬性。
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)), ] ## 就像數(shù)據(jù)格式化一樣 數(shù)據(jù)帶上標(biāo)簽 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 自行創(chuàng)建函數(shù)
它會(huì)自行創(chuàng)建函數(shù)。methodcaller 創(chuàng)建的函數(shù)會(huì)在對(duì)象上調(diào)用參數(shù)指定的方法
自己創(chuàng)建函數(shù)
from operator import methodcaller s = "The time has come" upcase = methodcaller("upper") print(upcase) hiphenate = methodcaller("replace", " ", "-") print(hiphenate(s))functools.partial凍結(jié)參數(shù)
functools.partial 這個(gè)高階函數(shù)用于部分應(yīng)用一個(gè)函數(shù)。部分應(yīng)用
是指,基于一個(gè)函數(shù)創(chuàng)建一個(gè)新的可調(diào)用對(duì)象,把原函數(shù)的某些參數(shù)固定。
from operator import mul from functools import partial print(mul(3, 7)) # 第一個(gè)函數(shù), 第二個(gè)固定的參數(shù) triple = partial(mul, 3) print(list(map(triple, range(1, 10))))小總結(jié) 高階函數(shù)
接受函數(shù)為參數(shù),或者把函數(shù)作為結(jié)果返回的函數(shù)是高階函數(shù).
Python 中常用的高階函數(shù)有內(nèi)置函數(shù)
sorted、min、max 和 functools. partial
實(shí)例 直接函數(shù)化運(yùn)行從 lambda 表達(dá)式創(chuàng)建的簡(jiǎn)單函數(shù)到實(shí)現(xiàn)__call__ 方法的類實(shí)例。
這些可調(diào)用對(duì)象都能通過(guò)內(nèi)置的callable() 函數(shù)檢測(cè)。
函數(shù)注解在 inspect 模塊的幫助下,可以讀取它們。
例如,Signature.bind 方法使用靈活的規(guī)則把實(shí)參綁定到形參上,這與 Python 使用的規(guī)則一樣。
operator 模塊介紹了 operator 模塊中的一些函數(shù),
以及functools.partial 函數(shù),
有了這些函數(shù),函數(shù)式編程就不太需要功能有限的 lambda 表達(dá)式了
其他all 和 any 也是內(nèi)置的歸約函數(shù).
用來(lái)判斷是否所有都為真,或者有一個(gè)為真
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/41640.html
摘要:在復(fù)雜的情況下,需要具體策略維護(hù)內(nèi)部狀態(tài)時(shí),可能需要把策略和享元模式結(jié)合起來(lái)。函數(shù)比用戶定義的類的實(shí)例輕量,而且無(wú)需使用享元模式,因?yàn)楦鱾€(gè)策略函數(shù)在編譯模塊時(shí)只會(huì)創(chuàng)建一次。 一等函數(shù)實(shí)現(xiàn)設(shè)計(jì)模式 經(jīng)典的策略模式定義 定義一系列算法,把它們一一封裝起來(lái),并且使它們可以相互替換。本模式使得算法可以獨(dú)立于使用它的客戶而變化。 案例 假如一個(gè)網(wǎng)店制定了下述折扣規(guī)則。 有 1000 或以上積分...
摘要:高程讀書筆記第五章類型創(chuàng)建實(shí)例的方式有兩種。第一種是使用操作符后跟構(gòu)造函數(shù),另一種方式是使用對(duì)象字面量表示法。 JS高程讀書筆記--第五章 Object類型 創(chuàng)建Object實(shí)例的方式有兩種。第一種是使用new操作符后跟Object構(gòu)造函數(shù),另一種方式是使用對(duì)象字面量表示法。 在通過(guò)對(duì)象字面量定義對(duì)象時(shí),實(shí)際上不會(huì)調(diào)用Object構(gòu)造函數(shù) 訪問(wèn)對(duì)象屬性時(shí)可以使用點(diǎn)表示法和方括號(hào)表示法。...
摘要:比如,你可以建立一個(gè),選出熱量超過(guò)卡路里的頭三道菜請(qǐng)注意也可以用在無(wú)序流上,比如源是一個(gè)。跳過(guò)元素流還支持方法,返回一個(gè)扔掉了前個(gè)元素的流。一般來(lái)說(shuō),應(yīng)該使用來(lái)對(duì)這種流加以限制,以避免打印無(wú)窮多個(gè)值。 一、篩選和切片 1.用謂詞篩選 Streams接口支持filter方法。該操作會(huì)接受一個(gè)謂詞(一個(gè)返回boolean的函數(shù))作為參數(shù),并返回一個(gè)包括所有符合謂詞的元素的流。例如篩選出所有...
摘要:跳過(guò)元素流還支持方法,返回一個(gè)扔掉了前個(gè)元素的流。歸約到目前為止,我們見到過(guò)的終端操作都是返回一個(gè)之類的或?qū)ο蟮?。這樣的查詢可以被歸類為歸約操作將流歸約成一個(gè)值。通過(guò)反復(fù)使用加法,你把一個(gè)數(shù)字列表歸約成了一個(gè)數(shù)字。 使用流 在上一篇的讀書筆記中,我們已經(jīng)看到了流讓你從外部迭代轉(zhuǎn)向內(nèi)部迭代。這樣,你就用不著寫下面這樣的代碼來(lái)顯式地管理數(shù)據(jù)集合的迭代(外部迭代)了: /** * 菜單 ...
摘要:第三個(gè)問(wèn)題查找所有來(lái)自于劍橋的交易員,并按姓名排序。第六個(gè)問(wèn)題打印生活在劍橋的交易員的所有交易額。第八個(gè)問(wèn)題找到交易額最小的交易。 付諸實(shí)戰(zhàn) 在本節(jié)中,我們會(huì)將迄今學(xué)到的關(guān)于流的知識(shí)付諸實(shí)踐。我們來(lái)看一個(gè)不同的領(lǐng)域:執(zhí)行交易的交易員。你的經(jīng)理讓你為八個(gè)查詢找到答案。 找出2011年發(fā)生的所有交易,并按交易額排序(從低到高)。 交易員都在哪些不同的城市工作過(guò)? 查找所有來(lái)自于劍橋的交易...
閱讀 5298·2021-09-22 15:59
閱讀 1879·2021-08-23 09:42
閱讀 2575·2019-08-29 18:42
閱讀 3459·2019-08-29 10:55
閱讀 2072·2019-08-27 10:57
閱讀 1771·2019-08-26 18:27
閱讀 2733·2019-08-23 18:26
閱讀 2933·2019-08-23 14:40