Python函數有哪些?

PHP中文网
發布: 2017-06-20 10:17:09
原創
1442 人瀏覽過

  我們可以用一段程式碼來實現我們需要的功能,但是當我們需要重複使用這段程式碼時,複製貼上並不是一個酷的方法,我們可以用到函數來實現這一需求

一、函數定義

函數是邏輯結構化和過程化的一種程式設計方法,透過一個函數名稱封裝好一串用來完成某一特定功能的程式碼

函數的定義:

def 函數名稱(參數1,參數2....):

  ''註解''

  函數體

#
def func1():  #定义函数print('this is a function')  #函数体
func1()  #调用函数
登入後複製
(%)
登入後複製
(%(func1()) 
登入後複製

-->  egon is a good man

    None

函數的優點:1.程式碼重用

      2.保持一致性,易於維護

      3.可擴展性好

變數類似,在定義前使用會報錯

   2.函數在定義階段只偵測語法錯誤,不會執行程式碼,所以即使在函數體內有未定義的變數名,在函數未呼叫前也不會報錯

   3.函數的回傳值可以是任意型,如果是回傳多個值,一定是元組形式

   4.return 的作用是終止函數的執行,return只終止函數的執行,return只終止執行一次,後面的內容不執行

二、函數參數

函數的參數分為形式參數和實際參數,在函數定義的時候,函數名稱後面括號裡的就是形式參數,在函數呼叫的時候,傳遞的參數是實際參數。形式參數只在函數內部有效,外部無法引用。

1.形參

1)位置參數:依照從左到右的順序依序定義的參數def foo(x,y,z)

  位置形參必須被傳值,且多一個少一個都不行

2)預設參數:在函數定義階段就已經為形參賦值,呼叫階段不賦值也會有預設值def foo(x,y= 10)

  值經常變化的情況,通常定義成位置參數,但是值在多數情況下不變的情況下,可以定義成預設參數

注意:

a.預設參數必須放在位置參數後面

b.預設參數通常定義成不可變型別

c.預設參數只在定義時被賦值一次

# 3)命名關鍵字參數:def register(*,name,age) *後面定義的形參,必須被傳值,且必須以關鍵字的形式傳值

2.實參

1)位置實參:與位置形參一一對應

2)關鍵字參數:實參在定義時,依key-values的形式定義

  def foo( x,y)

  foo(x=1,y=2)

  關鍵字參數可以不用向位置參數一樣與形參一一對應,可以打破順序限制

注意:a.位置參數和關鍵字參數混合使用的時候,位置參數必須在關鍵字參數前面

   b.既可以是位置實參形式,也可以是關鍵字實參形式,但是一個形參只能傳值一次

3)可變長參數:

  按位置定義的可變長參數用*表示

  按關鍵字定義的可變類型的參數用**表示

def func(x,y,*args):print(x,y,args)
func(1,2,3,4,5)  --->1 2 (3 4 5)
登入後複製

#遇到*就是位置參數,把*後面的全部拆開,再一一匹配,多餘的就以元組的形式存放到一起

def func(x,y,**kwargs):print(x,y,kwargs)
func(1,y=2,z=3,a=1,b=2)---->1 2 {'z': 3, 'a': 1, 'b': 2}
登入後複製

#遇到**就是關鍵字參數,把**後面的全部拆成關鍵字,再一一匹配,多餘的以字典形式存放到一起

def wrapper(*args,**kwargs):可以接受任意形式,任意長度的參數

參數的定義順序:x,y=1,*args,z,* *kwargs,分別是位置參數,預設參數,可變長位置參數,命名關鍵字參數,可變類型參數

但需要注意的是,這些參數並不會同時全部出現

三、名稱空間和作用域

名稱空間存放名字和值的綁定關係,以key-value 的形式

在Windows指令提示列中輸入指令:import this ,在最後一行會看到這樣一句話:

  Namespaces are one honking great idea -- let's do more of those!

名稱空間分為三種:

#1 )內建名稱空間:Python自帶的,如print,int,len....當Python解釋器啟動的時候,就會產生內建名稱空間

2)全域名稱空間:檔案層級定義的名字會存放到全域名稱空間,執行Python程式的時候產生,簡單點說就是沒有縮排的變數名稱

3)局部名稱空間:定義在函數(或模組、類別)內部的名字,只有在函數(模組、類別)呼叫的時候才生效,呼叫結束後就會釋放

載入順序是:內建名稱空間-->全域名稱空間-->局部名稱空間

取值順序是:局部名稱空間-->全域名稱空間-->內建名稱空間

四、函數巢狀與作用域

1.函數嵌套包含函數的巢狀呼叫和函數的巢狀定義

函數巢狀呼叫可以用求最大值的例子來說明:

def max2(x,y):if x > y:return xelse:return ydef max4(a,b,c,d):
    res1=max2(a,b) #23res2=max2(res1,c) #23res3=max2(res2,d) #31return res3print(max4(11,23,-7,31))
登入後複製

函数嵌套定义:

def f1():def f2():def f3():print('from f3')print('from f2')
        f3()print('from f1')
    f2()# print(f1)f1()
登入後複製

2.作用域

1)全局作用域:内置名称空间与全局名称空间的名字属于全局范围,在整个文件的任意位置都能引用

2)局部作用域:属于局部范围,只在函数内部可以被引用,局部有效

一定要注意局部变量和全局变量的作用范围,在局部修改全局变量会出错,在全局范围引用局部变量也会出错

作用域在函数定义时就已经固定了,不会因调用位置而改变

但是如果一定要在局部修改全局变量,也是用办法的,就是在要修改的变量前加一个global

x=1def foo():
    x=10print(x)        

foo()       #10print(x)    #1
登入後複製
x=1def foo():global x
    x=10print(x)

foo()       #10print(x)    #10
登入後複製
def foo():
    x=1def f2():
        x+=xreturn xreturn f2()print(foo())        #会报错UnboundLocalError: local variable 'x' referenced before assignmentdef foo():
    x=1def f2():
        nonlocal x  #告诉Python解释器,这里的x不是局部变量,只会找函数内部的,不会修改全局变量
        x+=xreturn xreturn f2()print(foo())    #会打印出修改后的x的值,2
登入後複製

五、闭包函数

定义在函数内部的函数,该内部函数包含对外部作用域,而非全局作用域的名字的引用,那么该内部函数称为闭包函数

name===func()
登入後複製

闭包函数的特点:a.自带作用域,b.延迟计算(f只是拿到了函数的内存地址,什么时候用,加括号就可以运行)

闭包函数最基本的形式:

def 外部函数名():

  内部函数需要的变量

  def 内部函数名():

    引用外部变量

  return 内部函数名

六、装饰器

1.开放封闭原则:对扩展是开放的,对修改是封闭的

2.装饰器本质是任意可调用的对象,被装饰对象也是任意可调用的对象

3.装饰器的功能是:在不修改被装饰对象源代码及调用方式的前提下,为其添加新的功能

4.装饰器语法:在被装饰对象的正上方的单独一行,写上@装饰器名字

5.有多个装饰器的时候,每行一个,执行时从上往下运行

6.被装饰函数有参数的情况:写成(*args,**kwargs)的形式

装饰器示例一:

#实现缓存网页内容的功能,下载的页面存放于文件中,如果文件内有值(文件大小不为0),# 就优先从文件中读取网页内容,否则,就去下载,然后存到文件中from urllib.request import urlopenimport os

cache_path=r'C:\untitled\0615Python第8天\cache_file.txt'def make_cache(func):def wrapper (*args,**kwargs):if os.path.getsize(cache_path):#有缓存print('\033[45m========>有缓存\033[0m')
            with open(cache_path,'rb') as f:
                res=f.read()else:
            res=func(*args,**kwargs)#下载with open(cache_path,'wb') as f:#制作缓存                f.write(res)return resreturn wrapper


@make_cachedef get(url):return urlopen(url).read()print(get(''))
登入後複製

装饰器示例二:

#为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码db_dic={'egon':'123','alex':'alex3714','yuanhao':'smallb'}


db_path=r'C:\untitled\0615Python第8天\db_dic.txt'with open(db_path,'w',encoding='utf-8') as f:
    f.write(str(db_dic))

login_dic={'user':None,'status':False,
}def auth(func):def wrapper(*args,**kwargs):#加一个验证状态的字典,如果已经登录成功,下次使用就不用重新验证if login_dic['user'] and login_dic['status']:
            res=func(*args,**kwargs)return reselse:
            name=input('name:')
            password=input('password:')
            with open(db_path, 'r', encoding='utf-8') as f:
                auth_dic = eval(f.read())if name in auth_dic and password==auth_dic[name]:print('login ok')
                login_dic['user']=name
                login_dic['status']=True
                res=func(*args,**kwargs)return reselse:print('error')return wrapper

@authdef index():print('welcom to the page')

@authdef home(name):print('welcom  to %s\'s home page'%name)


index()
home('egon')
登入後複製

七、迭代器

1.对于字符串、列表、元组的数据类型,我们可以依据索引来实现迭代的效果,但是字典、集合这种没有索引的数据类型,就需要其他方式

2.Python为了提供一种不依赖索引的迭代方式,为一些对象内置了__iter__方法,obj.__iter__()得到的结果就是迭代器

得到的迭代器既有.__iter__方法,又有.__next__方法

3.迭代器的优点:

  a.提供了一种不依赖索引的取值方式

  b.惰性计算,节省内存

4.迭代器的缺点:

  a.取值不如按照索引取值方便

  b.一次 性的,取值只能往后走,不能往前退

  c.无法获取迭代器的长度

5.for循环实际上会默认调用.__iter__方法

6.判断是否是可迭代对象和迭代器,可以用命令

print(isinstance(str1,Iterable)) --->判断是否为可迭代对象

print(isinstance(str1,Iterator)) --->判断是否为迭代器

八、生成器函数(语句形式和表达式形式)

1.生成器函数:函数体内包含有yield关键字,该函数的执行结果就是生成器

2.生成器实际就是迭代器的一种

3.yield的功能:

  a.与return类似,都可以返回值,但不一样的地方在于yield返回多次值,而return只能返回一次值
  b.为函数封装好了__iter__和__next__方法,把函数的执行结果做成了迭代器
  c.遵循迭代器的取值方式obj.__next__(),触发的函数的执行,函数暂停与再继续的状态都是由yield保存的
4.生成器语句形式应用实例

 1 #模拟linux中tail -f a.txt|grep 'error' |grep '404'的功能 2 import time 3 def tail(filepath,encoding='utf-8'): 4     with open(filepath,encoding='utf-8') as f: 5         f.seek(0,2)  #以末尾为开始位,第0个 6         while True: 7             line=f.readline() 8             if line: 9                 yield line10             else:11                 time.sleep(0.5)12 13 def grep(lines,pattern):14     for line in lines:15         if pattern in line:16             # print(line)17             yield line18 19 g1=tail('a.txt')20 g2=grep(g1,'error')21 g3=grep(g2,'404')22 23 for i in g3:24     print(i)
登入後複製
View Code

5.生成器的表达式形式

def foo():print('starting')while True:
        x=yield #默认就是yield Noneprint('value :',x)

g=foo() 
next(g)  #初始化,等同于g.send(None)
g.send(2)  
登入後複製

将yield赋值给一个变量如x=yield,然后用send()传值,但注意要先做一个类似初始化的操作

g.send(2)的操作实际是先把2传值给yield,再由yield传值给x,send()既有传值的效果,又有next()的效果

生成器表达式形式应用示例

 1 def init(func): 2     def wrapper(*args,**kwargs): 3         g=func(*args,**kwargs) 4         next(g) 5         return g 6     return wrapper 7 @init 8 def eater(name): 9     print('%s ready to eat' %name)10     food_list=[]11     while True:12         food=yield food_list#return None13         food_list.append(food)14         print('%s start to eat %s' %(name,food))15 16 17 e=eater('alex')18 print(e.send('狗屎'))19 print(e.send('猫屎'))20 print(e.send('alex屎'))21 22 23 def make_shit(people,n):24     for i in range(n):25         people.send('shit%s' %i)26 27 e=eater('alex')28 make_shit(e,5)29 #from egon30 #egon老师的例子有味道,但是我又忍不住不用这个
登入後複製
View Code

九、三元表达式

res= x if x>y else y----->判断条件x>y是否为真,为真则把x赋给res,否则把y赋给res

十、列表解析

s='hello'res=[i.upper() for i in s]print(res)          #['H', 'E', 'L', 'L', 'O']
登入後複製

以上是Python函數有哪些?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!