06 函數式編程

1 函數式編程簡介

函數:function

函數式:functional 一種編程范式

?

特點:

把計算視為函數而非指令

純函數式編程:不需要變量,沒有副作用,測試簡單

支持高階函數,代碼簡潔

?

Python支持的函數式編程:

不是純函數式編程:允許有變量

支持高階函數:函數也可以作為變量傳入

支持閉包:有了閉包就能返回函數

有限度的支持匿名函數

?

變量可以指向函數:

>>> f=abs

>>> f(-20)

?

函數名其實就是指向函數的變量。

>>> abs=len

>>> abs([1,2,3])

?

2 高階函數

能接受函數作為參數的函數

變量可以指向函數

函數的參數可以接受變量

一個函數可以接受另一個函數作為參數

能接受函數作為參數的函數就是高階函數

def add(x, y, f)

?? return f(x) + f(y)

add(x, y, abs)

?

3 map()函數

Python內置的高階函數,接受一個函數f和一個list,并且通過把函數f依次作用在list的每個元素上,得到一個新的list并返回。

def f(x)

??? return x*x

map(f, range(1,10))

?

4 reduce()函數

參數為一個函數f,一個list。函數f接收兩個參數,reduce()對list的每個元素反復調用函數f,并返回最后結果。

def f(x, y)

??? return x + y

reduce(f, [1,3,5,7,9])??? #25

?

5 filter()函數

參數為一個函數f,一個list。函數f的作用是對每個元素進行判斷,并返回布爾值。filter()根據判斷結果對False的元素進行過濾。

def if_odd(x):

??? return x%2==1

filter(is_odd, [1,2,3,4,5])??? #[1,3,5]

?

刪除None或者空字符串

def is_not_empty(s):

??? return s and len(s.strip())>0

filter(is_not_empty, ['test', None, ' ', 'End'])

?

strip()的作用:刪除字符串首尾的空白字符。

?

6 sorted()函數

參數為一個list,一個函數f。函數f接受兩個參數x和y,如果x應該排在前面,則返回-1;如果y應該排在前面,則返回1;如果相等則返回0。

>>> sorted([36, 5, 12, 9, 21])??? #[5, 9, 12, 21, 36]

?

def reversed_cmp(x, y)

??? if x == y

??????? return 0

??? else

??????? return -cmp(x, y)

>>> sorted([36, 5, 12, 9, 21], reversed_cmp)??? #[36, 21, 12, 9, 5]

?

7 返回函數

def f():

??? print 'call f()...'

??? def g():

??????? print 'call g()...'

??? return g

>>> x=f()??? #調用f()

call f()...

>>> x??? #變量x是f()返回的函數

<function g at 0x1037bf320>

>>> x()??? #x指向函數,因此可以調用

call g()...?

注意區分返回函數和返回值

?

延遲計算

def calc_sum(lst):

??? def lazy_sum():

??????? return sum(lst)

??? return lazy_sum

>>> f=calc_sum([1,2,3,4])??? #調用calc_sum()并沒有計算出結果,而是返回函數。

>>> f

<function lazy_sum at 0x1037bfaa0>

>>> f()??? #對返回的函數進行調用時,才計算出結果

10

?

8 閉包

在函數內部定義的函數和外部定義的函數是一樣的,只是他們無法被外部訪問。

內層函數引用外層函數的變量,然后返回內層函數的情況,稱為閉包(Closure)。

閉包的特點:

返回的函數還引用了外層函數的局部變量,所以要正確使用閉包,就要確保引用的局部變量在函數返回后不能變。

def count():

??? fs=[]

??? for i in range(1, 4)

??????? def f():

??????????? return i*i;

??????? fs.append(f)

??? return fs

f1, f2, f3 = count()??? #此時調用f1、f2、f3的值都返回9

?

?

def count():

??? fs=[]

??? for i in range(1, 4)

??????? def f(j):

??????????? def g():

??????????????? return j*j;

??????????? return g;

??????? fs.append(f(i))

??? return fs

f1, f2, f3 = count()??? #此時調用f1、f2、f3的值返回1,4,9

?

?

9 匿名函數

?

關鍵字lambda表示匿名函數,冒號前面的x表示函數參數。

匿名函數的限制:只能有一個表達式,該表達式就是返回值。

>>> map(lambda x : x*x, range(1, 10))

>>> sorted([1,5,3,6], lambda x,y : -cmp(x, y))

>>> myabs=lambda x : -x if x < 0 else x??? #返回匿名函數

>>> filter(lambda s :s and len(s.strip()>0), ['test', None, ' ', 'END'])

?

?

?

10 decorator裝飾器

?

問題:定義了一個函數,想在運行時動態增加功能,有不想改動函數本身的代碼。

示例:希望對下列函數調用增加log功能,打印出函數調用:

def f1(x):

??? return x*2

def f2(x):

??? return x*x

def f3():

??? return x*x*x

?

高階函數:可以接受函數作為參數;可以返回函數;接受一個函數,對其包裝,然后返回一個新的函數。

def new_fn(f):

??? def fn(x):

??????? print 'call' + f._name_ + '()'

??? return fn

>>> g1=new_fn(f1)

>>> print g1(5)

>>> f1=new_fn(f1)

>>> print f1(5)

?

裝飾器

Python內置的@語法法就是為了簡化裝飾器的調用

@new_fn

def f1(x):

??? return x*2

?

裝飾器的作用

極大簡化代碼,避免為每個函數編寫重復性代碼

打印日志:@log

檢測性能:@performance

數據庫事務:@transaction

URL路由:@post('/register')

?

?

編寫無參數的decorator

Python的decorator本質上就是一個高階函數,它接受一個函數作為參數,然后返回一個新函數。

使用decorator用@語法,可以避免手動編寫f=decorate(f)這樣的代碼。

要讓decorator自適應任何參數定義的函數,可以利用Python的*args和**kw,保證任意個數的參數總是能正常調用。

*args是非關鍵字參數,用于元組;**kw是關鍵字參數,用于字典。

def log(f):

??? def fn(*args, **kw):

??????? print 'call' + f._name_ + '()...'

??????? return f(*args, **kw)

??? return fn

?

例子:編寫一個@performance,可以打印出函數調用的時間。

import time

def performance(f):

??? def fn(*args, **kw):

??????? t1 = time.time()

??????? r = f(*args, **kw)

??????? t2 = time.time()

??????? print 'call %s() in %fs' %(f._name_, t2-t1)

??????? return r

??? return fn

?

@performance

def factorial(n):

??? return reduce(lambda x,y:x+y, range(1,n+1)

print factorial(10)

?

?

編寫帶參數的decorator

如果有的函數非常重要,希望打印出'[INFO]call xxx()...';有的函數不太重要,希望打印出'[DEBUG] call xxx()...'。

這時,log函數本身就需要傳入'INFO'或'DEBUG'這樣的參數,類似這樣:

@log('DEBUG')

def my_func():

??? pass

?

上面定義翻譯成高階函數調用,就是:

my_func=log('DEBUG')(my_func)

?

再展開一下就是:

log_decorator=log('DEBUG')

my_func=log_decorator(my_func)

?

亦即:

log_decorator=log('DEBUG')

@log_decorator

def my_func():

??? pass

?

def log(prefix):

??? def log_decorator(f):

??????? def wrapper(*args, **kw)

??????????? print '[%s]%s()...' %(prefix, f._name_)

??????????? return f(*args, **kw)

??????? return warpper

??? return log_decorator

?

完善decorator

由decorator返回的函數的信息與被裝飾的函數的信息不同,可以利用Python內置的functools來將原函數的所有必要屬性一一賦值到新函數上,如__name__,__doc__等。

import functools

def log(f)

??? @functools.wrap(f)

??? def wrapper(*args, **kw)

??????? print 'call ...'

??????? return f(*args, **kw)

??? return wrapper

?

需要指出的是,無法獲得原函數的原始參數信息。

?

?

?

11 偏函數

?

當一個函數有很多參數時,調用者就需要提供多個參數;如果減少參數個數,就可以簡化調用者的負擔。

>>> int('12345')

>>> int('12345', base=8)

>>> int('12345', 16)

?

假設要轉換大量的二進制字符串,每次都傳入int(x,base==2)非常麻煩,可以定義一個int2()函數,默認把base=2傳進去。

def int2(x, base=2)

??? return int(x,base)

>>> int2('101010110')

?

functools.partial就是幫助我們創建一個偏函數的。

>>> import functools

>>> int2 = functools.partial(int, base=2)

>>> int2('101010110')

?

例子:忽略大小寫排序。

>>> import functools

>>> sorted_ignore_case = functools.partial(sorted, cmp=lambda s1,s2:cmp(s1.upper(), s2.upper()))

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/387113.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/387113.shtml
英文地址,請注明出處:http://en.pswp.cn/news/387113.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android SDK開發

目前我們的應用內使用了 ArcFace 的人臉檢測功能&#xff0c;其他的我們并不了解&#xff0c;所以這里就和大家分享一下我們的集成過程和一些使用心得 集成 ArcFace FD 的集成過程非常簡單 在 ArcFace FD 的文檔上有說明支持的系統為 5.0 及以上系統&#xff0c;但其實在 4.4 系…

jQuery WeUI 上傳

jQuery WeUI 是專為微信公眾賬號開發而設計的一個框架&#xff0c;jQuery WeUI的官網&#xff1a;http://jqweui.com/ 需求&#xff1a;需要在微信公眾號網頁添加上傳圖片功能 技術選型&#xff1a;實現上傳圖片功能可選百度的WebUploader、餓了么的Element和微信的jQuery WeUI…

07 模塊

模塊和包的概念 等同于java中的Package 模塊名文件名&#xff08;無后綴&#xff09; 在文件系統中&#xff0c;包就是文件夾&#xff0c;模塊就是xxx.py文件 每層包下面都有__init__.py文件 導入模塊 >>> import math >>> math.pow(2, 0.5) >>…

1.rabbitmq 集群版安裝及使用nginx進行四層負載均衡設置

1.安裝erlang 需要注意erlang的版本是否滿足rabbitmq的需求 這里用到的版本是&#xff1a;Erlang 19.0.4 RabbitMQ 3.6.15 wget http://www.rabbitmq.com/releases/erlang/erlang-19.0.4-1.el7.centos.x86_64.rpmrpm -ivh erlang-19.0.4-1.el7.centos.x86_64.rpm yum -y inst…

使用WEUI uploader上傳圖片

使用WEUI uploader上傳圖片&#xff0c;博主費了很大的勁總算找到完整的了&#xff0c;并且帶后臺接收代碼&#xff0c;有需要的朋友拿去吧&#xff0c;親測可用&#xff01; 一、html代碼<link rel"stylesheet" href"https://res.wx.qq.com/open/libs/weui/…

08 面向對象編程

1 介紹 面向對象編程是一種程序設計范式 把程序看做不同對象的相互調用&#xff0c;對現實世界建立對象模型。 面向對象編程的基本思想&#xff1a; 類和實例&#xff1a; 類用于定義抽象類型 實例根據類的定義被創建出來 2 定義類并創建實例 類通過class關鍵字定義&…

H5+jqweui實現手機端圖片壓縮上傳 Base64

H5jqweui實現手機端圖片壓縮上傳主要功能&#xff0c;使用H5的formData上傳base64格式的圖片&#xff0c;canvas壓縮圖片&#xff0c;前端樣式使用weui&#xff0c;為方便起見&#xff0c;使用了jquery封裝過的weui&#xff0c;jqweui。話不多少&#xff0c;開始上代碼。前端代…

09 類的繼承

繼承一個類 class Person(object): def __init__(self, name, gender): self.name name self.gender gender class Student(Person): def __init__(self, name, gender, score): super(Student, self).__init__(name, gender) self.score score 判斷類型 isinstance()可以…

vue 中v-if 與v-show 的區別

相同點或者說功能&#xff0c;都可以動態操作dom元素的顯示隱藏 不同點&#xff1a; 1.手段&#xff1a;v-if是動態的向DOM樹內添加或者刪除DOM元素&#xff1b;v-show是通過設置DOM元素的display樣式屬性控制顯隱&#xff1b;2.編譯過程&#xff1a;v-if切換有一個局部編譯/卸…

vue打包后放在 nginx部署時候的配置文件

部署了三套程序,默認的&#xff0c;admin和design#user nobody; worker_processes 1;#error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info;#pid logs/nginx.pid;events {worker_connections 1024; }http {include …

淘淘商城之技術選型、開發工具和環境、人員配置

一、技術選型 1&#xff09;Spring、SpringMVC、Mybatis 2&#xff09;JSP、JSTL、jQuery、jQuery plugin、EasyUI、KindEditor&#xff08;富文本編輯器&#xff09;、CSSDIV 3&#xff09;Redis&#xff08;緩存服務器&#xff09; 4&#xff09;Solr&#xff08;搜索&#x…

啟動代碼格式:nginx安裝目錄地址 -c nginx配置文件地址

啟動啟動代碼格式&#xff1a;nginx安裝目錄地址 -c nginx配置文件地址 例如&#xff1a;[rootLinuxServer sbin]# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf停止nginx的停止有三種方式&#xff1a; 從容停止1、查看進程號[rootLinuxServer ~]# ps -ef…

Lecture 3 Divide and Conquer

1.Divide the problem(instance) into one or more sub-problem; 2.Conquer each sub-problem recursively; 3.Combine solutions.

Maven報錯找不到jre

富人之所以越來越富&#xff0c;窮人之所以越來越窮&#xff0c;中產階級之所以總是在債務泥潭中掙扎&#xff0c;其主要原因之一在于他們對金錢的觀念不是來自學校&#xff0c;而是來自家庭。 ---《窮爸爸富爸爸》 一、報錯提示 常規配置maven環境變量&#xff0c;報錯&#x…

vue按照url地址訪問出錯404

問題描述&#xff1a; 最近在開發cms的時候使用Vue.js框架&#xff0c;利用vue-route結合webpack編寫了一個單頁路由項目&#xff0c;自己在服務器端配置nginx。部署完成后&#xff0c;訪問沒問題&#xff0c;從頁面中點擊跳轉也沒問題&#xff0c;但是只要點擊刷新或通過瀏覽器…

Lecture 4 Quick Sort and Randomized Quick Sort

Quick Sort --Divide and Conquer --Sorts “in place” --Very practical with tuning Divide and Conquer: 1.Divide: Partition array into 2 sub-arrays around pivot x such that elements in lower sub-array < x < elements in upper sub-array; 2.Conquer: …

HDU 3966 樹鏈剖分后線段樹維護

題意: 一棵樹, 操作1.$path(a,b)$之間的點權$k$ 操作2.單點查詢 題解: 樹鏈剖分即可,注意代碼細節,雙向映射 主要是記錄一下板子 #include <string.h> #include <stdio.h> #include <algorithm> #define endl \n #define ll long long #define ull unsigned …

VUE config/index.js文件配置

&#xfeff;&#xfeff; 當我們需要和后臺分離部署的時候&#xff0c;必須配置config/index.js: 用vue-cli 自動構建的目錄里面 &#xff08;環境變量及其基本變量的配置&#xff09;123456789101112131415var path require(path)module.exports {build: {index: path.res…

數據規則列表加導入導出

1.進入bos&#xff0c;打開數據規則&#xff0c;進入列表菜單 2.點擊事件-新增操作 3.點擊新增 4.點擊操作類型&#xff0c;輸入%引入 5.點擊確定&#xff0c;保存后生效&#xff0c;導出 、引入模板設置同理轉載于:https://www.cnblogs.com/RogerLu/p/10643521.html