必要な関数を実装するためにコードを使用できますが、このコードを再利用する必要がある場合、このニーズを達成するために関数を使用することはクールな方法ではありません
1. 関数の定義
A。関数は、関数名を通じて特定の関数を完成させるためのコード文字列をカプセル化する、論理的に構造化された手続き型プログラミング手法です。 「コメント」
関数本体
def func1(): #定义函数print('this is a function') #函数体 func1() #调用函数
(%)--> intgue曰く、メンテナンスが簡単だそうです この段階では構文エラーを検出するだけで、コードは実行されません, そのため、関数本体に未定義の変数名があっても、関数が呼び出される前にエラーは報告されません 3. 関数の戻り値は、複数の値を返す場合、任意の型にすることができます。タプルの形式 4. return の関数は関数の実行を終了する関数です。 return は 1 回だけ実行され、次の内容は実行されません
2. 関数のパラメータ
関数のパラメータは に分かれています。仮パラメータと実パラメータ 関数が定義されている場合、関数名の後の括弧内の仮パラメータは、関数が呼び出されるときに渡されるパラメータです。仮パラメータは関数内でのみ有効であり、外部から参照することはできません。
1) 位置パラメータ: 左から右の順に定義されたパラメータ def foo(x,y,z)
位置パラメータは値で渡す必要があり、1 つ以上は機能しません 2) デフォルトパラメータ: 関数定義フェーズ中に仮パラメータに値が割り当てられています。呼び出しフェーズ中に値が割り当てられていない場合、デフォルト値 def foo(x,y=10) も存在します。値が頻繁に変更される場合は、通常、位置パラメータとして定義されますが、値がほとんど変更されない場合は、デフォルト パラメータとして定義できます注: デフォルト パラメータは、a の後に配置する必要があります。位置パラメータb. デフォルトパラメータは、通常、不変型として定義されますc. デフォルトパラメータは、定義時に一度だけ割り当てられます3) 名前付きキーワードパラメータ: def register(*,name,age) *後から定義する仮パラメータは値で渡す必要があり、その値はキーワードの形式で渡す必要があります2 .実際のパラメータ1) 位置実パラメータ: 位置パラメータと1対1対応2) キーワードパラメータ: 実際のパラメータを定義するときは、key-value の形式で定義します def foo(x,y) foo(x=1,y=2) キーワードパラメータは必ずしも対応している必要はありません位置パラメータのような仮パラメータとの 1 つの組み合わせは、順序制限を破る可能性があります 注: a. 位置パラメータとキーワード パラメータを一緒に使用する場合、位置パラメータはキーワード パラメータの前になければなりません b.位置パラメータまたはキーワード パラメータですが、仮パラメータは値を 1 回しか渡すことができません 3) 可変長パラメータ: 位置による 定義された可変長パラメータは * で表されます キーワードで定義された変数型パラメータは次のとおりです**(%(func1())
#*に遭遇した場合、それは位置パラメータであり、*以降をすべて逆アセンブルし、それらを1つずつ照合し、余分なものをタプルの形式でまとめて保存します
def func(x,y,*args):print(x,y,args) func(1,2,3,4,5) --->1 2 (3 4 5)
# ** に遭遇した場合、それはキーワードパラメータです。 ** 以降をすべてキーワードに分割し、それらを 1 つずつ一致させて
def ラッパー (*args, **) の形式で保存します。 kwargs): 任意の形式と長さのパラメーターを受け入れることができます パラメーターの定義順序: x、y=1、*args、z、**kwargs はそれぞれ、位置パラメーター、デフォルト パラメーター、可変長の位置パラメーターであり、名前が付けられます。キーワードパラメータ、変数型パラメータただし、これらのパラメータはすべて同時に表示されるわけではないことに注意してください3. 名前空間とスコープ名前空間は、名前と値のバインディング関係をキーと値の形式で保存します Windows コマンド プロンプトにコマンドを入力します。 import this を実行すると、最後の行に次の文が表示されます: 名前空間は素晴らしいアイデアの 1 つです -- それらをもっと実行しましょう 名前空間には 3 つのタイプがあります:1) 組み込み名前空間: print、int、len などの Python 独自の名前空間。Python インタープリターが開始すると、組み込み名前空間が生成されます
3) ローカル名前空間:関数(またはモジュール)内で定義された名前です。クラス) は、関数 (モジュール、クラス) が呼び出されたときにのみ有効になり、呼び出しが完了すると解放されます
値の順序は、ローカル名前空間 --> グローバル名前空間 --> 組み込み名前空間です IV. 関数のネストとスコープ 1. 関数のネストには、関数のネストされた呼び出しと関数のネストが含まれます定義 ネストされた関数呼び出しは、最大値を見つける例で説明できます:
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 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)
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老师的例子有味道,但是我又忍不住不用这个
九、三元表达式
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 中国語 Web サイトの他の関連記事を参照してください。