ホームページ >バックエンド開発 >Python チュートリアル >Python を学ぶ第 3 章__関数プログラミング、再帰、組み込み関数
1. 関数プログラミング
関数の作成
関数式は、キーワードdef、関数名、括弧とコロン、括弧内のパラメータで構成されます。関数を実行したいときは、関数を記述するだけです。 name と括弧。Can
形式: def function (parameter) 関数を作成しましょう
例を見てみましょう。次のコードでは、まず変数 a = "haha" を入れ、次に関数に a = "heihei" を入れます。最後にこの関数を実行して変数 a の結果を出力します
a が "heihei" と等しくない理由はわかりました。先ほど割り当てた「笑」の現象を早速公開していきます
#!/usr/bin/env python # -*- coding:utf-8 -*- #创建函数 def print_str(): print("Hello World") #调用函数 print_str()
変数スコープの例1
グローバル変数とローカル変数
変数のスコープが以下であることは明らかです。変数が有効になるスコープ この問題が発生した場合、スコープは使用できません
グローバル変数: 通常、グローバル変数はスクリプトの終了後も存続し、すべての関数がそれにアクセスできます
ローカル変数: 関数内でのみ呼び出すことができますローカル変数が配置されている場所、およびローカル変数がグローバル変数として宣言されていない限り、他の関数を呼び出すことができず、ローカル変数
関数の実行が完了すると存在しなくなります
#!/usr/bin/env python # -*- coding:utf-8 -*- a = "haha" #创建函数 def print_str(): a = "heihei" print("Hello World") #调用函数 print_str() print("我是变量a:",a)
グローバル変数とローカル変数
global
グローバルとはローカル変数を置けるという意味です 宣言されたローカル変数名がグローバル変数名と同じであれば、その変数はグローバル変数になります。グローバル変数を上書きするときは、グローバルを使用して変数を宣言する必要があります。そうでない場合、Python は以前の宣言が必要であることを通知します
エラー メッセージ: SyntaxWarning: name 'a' is assign to before global.宣言 global a
#!/usr/bin/env python # -*- coding:utf-8 -*- a = "haha" #创建函数 def print_str(): a = "heihei" print("我是局部变量a:",a) #调用函数 print_str() print("我是全局变量a:",a)
gloable
2. 戻り値を渡す
パラメータを渡す
関数は比較的簡単に使えて理解しやすいですが、パラメータがさらに変化します。パラメータは関数括弧内にあり、文字列、数値、辞書、リストを受け取ることができます
#!/usr/bin/env python # -*- coding:utf-8 -*- a = "haha" #创建函数 def print_str(): global a a = "heihei" print("我是局部变量a:",a) #调用函数 print_str() print("我是全局变量a:",a)
パラメータを渡す
#!/usr/bin/env python # -*- coding:utf-8 -*- #创建函数 def print_str(Name,Age,Aender): print(''' Name:%s Age:%s Aender:%s '''%(Name,Age,Aender)) #用户输入 in_name = input("请输入你的名字:") in_age = input("请输入你的年龄:") in_aender = input("请输入你的性别:") #固定位置传参 print_str(in_name,in_age,in_aender) print("----------------------------------") #不固定位置传参 print_str(in_name,Aender=in_aender,Age=in_age)
辞書またはリストを渡します
#!/usr/bin/env python # -*- coding:utf-8 -*- def print_str(lists): if type(lists) == list: print(''' Name:%s Age:%s Aender:%s '''%(lists[0],lists[1],lists[2])) else: print(''' Name:%s Age:%s Aender:%s '''%(lists["name"],lists["age"],lists["aenber"])) #传入列表 userlist = ["Ben","22","Man"] print_str(userlist) print("----------------------------------") #传入字典 userdict = {"name":"Ben","age":"022","aender":"Man"} print_str(userlist)
デフォルトパラメータ
非固定パラメータ
非固定パラメータは 1 つの * と 2 つの * に分けられます。*args は入力パラメータをプリミティブに変換し、**kwargs は入力パラメータを辞書に変換します。もちろん、*ages は他の名前にすることもできます。仕様 *args と **kwargs を使用するのが最善です
仮パラメータは * と ** を取ることができるため、実際のパラメータも * と ** を取ることができます、 then * これはリストで使用され、** は辞書で使用されます。
#!/usr/bin/env python # -*- coding:utf-8 -*- def print_str(lists,Country="China"): if type(lists) == list: print(''' Name:%s Age:%s Aender:%s country:%s '''%(lists[0],lists[1],lists[2],Country)) else: print(''' Name:%s Age:%s Aender:%s country:%s '''%(lists["name"],lists["age"],lists["aenber"],Country)) #传入列表 userlist = ["Ben","22","Man"] print_str(userlist) print("----------------------------------") #传入字典 userdict = {"name":"Ben","age":"022","aender":"Man"} print_str(userlist,"America")
* が付いた実際のパラメータはリストを「Ben」、「22」、「Man」に分解し、個々の要素を 1 つずつ関数に渡しますが、** will 辞書は name="Ben"、age="022"、gender="Man" に分解されます
この種のキーと値のペアが関数に渡されます。
仮パラメータ
注!当普通参数和默认参数和非固定参数结合使用的时候,要遵循一个顺序,普通参数在默认参数前面,默认参数在非固定参数前面
返回值
在正常使用函数的时候,函数是可以把函数内部处理的结果返回给函数调用者的,在没有返回值得函数中会保留None传给函数调用者,返回值可以返回序列等
在函数执行的时候遇到return函数会停止执行,并返回结果
#!/usr/bin/env python # -*- coding:utf-8 -*- #创建函数 def print_str(Age): if int(Age) <= 30: return "你才%s啊!真年轻"%(Age) else: return "你都%s啦!老家伙"%(Age) in_age = input("请输入你的年龄:") word = print_str(in_age) print(word)
return
嵌套函数
在函数内部也可以写函数,这样就是外层函数套着内侧函数,这种形式称之为嵌套函数,同理因为作用域的关系嵌套函数只能内部调用
return unction_2(stra)+"我是第二层\n" 就等于先 c = unction_2(stra) 然后 return c+"我是第二层\n"
def unction(stra): def unction_2(stra_2): return stra_2+"我是第三层\n" return unction_2(stra)+"我是第二层\n" r_str = unction("") print(r_str+"我是第一层")
嵌套函数
前面已经介绍了函数相关的知识,在函数中,函数可以调用其他的函数,并且函数还可以调用自身,利用这种特性我们可以完成一些特定的
操作,这种函数调用自身的形式就是递归
def recursion() :
return recursion()
在递归中不能像上面两行一样一直调用自身,这样一会程序就会崩溃,因为它永远的在调用就跟while死循环一样出不去,所以递归也需要进
判断给它出口
例子:阶乘
什么是阶乘,阶乘就是给一个自然数N,然后计算N的阶乘那么 N = 1x2x3x4....N ,这个就是阶乘,我们可以把它到过来看,
N = N x (n-1) x (n-2) x (n-3) ...... 1 一直乘到括号中的值等于1,既然知道了阶乘是什么,那么我们来写一个程序实现它
def factorial(n): for i in range(1,n): n *= i return n c = factorial(4) print(c)
阶乘非递归版本
剖析:上面的例子首先把n=4传入进去,然后通过 for i in range(1,4)让i分别等于1,2,3,然后进行 n*=i,我们可以看出这个for循环是循环3次的
第一次(n = n*i) n = 4*1 ,此时n还是等于4
第二次(n = 4*i) n = 4*2 此时n = 8
第三次(n = 8*i) n = 8*3 此时n等于24
此时for循环了3次所以结束了,通过return把n的结果返回,所以最终结果算出 4的阶乘等于24
递归版本
下面看递归版本的阶乘
def factorial(n) : if n == 1: return 1 else: return n * factorial(n-1) c = factorial(4) print(c)
阶乘递归版本
剖析:
首先c = factorial(4)开始执行函数,然后进行第一次判断 n == 1,显然第一层n不等于1,然后碰到return n * factorial(n-1),碰到return本来是要返回的,但是 factorial(n-1)
有调用了factiorial这个函数,因此进入了第二层
第二层因为上一层传入的参数是n-1,所以第二层的n是等于3的,然后判断,这一层的n也不等于1,然后又进入第三层
第三层n等于3,然后判断这一层的n还不等于1,然后又进入第四层
到第四层的时候这时的 n就等于1,所以触发了 return 1 不再调用函数了,所以就开始返回
返回第三层 return n * factorial(n-1) , 此时factorial(n-1) 就等于第四层return上去的1,所以第三层返回时就等于return n * 1(return 2 * 1),并且第三层n是等于2的
返回第二层factorial(n-1)就等于第三层return上去的2,并且第二层n是等于3的,return 3 * 2
返回第一层factorial(n-1)就等于第二层return上去的6,并且第一层n是等于4的,return 4 * 6
到此为止递归执行完毕,c就等于 4 * 6 c=24
匿名函数也叫lambda函数,函数没有具体的名称。语法:function name= lambda args(多个参数用逗号隔开): Expression(表达式,表达式的结果就是返回值)
先来看一个最简单例子:
#普通函数 def func(arg1,arg2): return arg1-arg2 #lambda函数 func_2 = lambda arg1,arg2: arg1-arg2 #传参执行 print(func(5,4)) print(func_2(5,4))
匿名函数
有认识,这个匿名函数和普通函数没有什么区别么,其实匿名函数就像三元运算一样,并且能够用lambda函数有几大优势
1、在一些不会再别的地方调用的函数,我们可以使用匿名函数,并且这样简化了代码,看起来更加整洁。
2、lambda函数将会搭配一些内置函数来使用(下面会涉及到)
在上面的示例中知道了函数可以调用函数本身,这种形式称之为递归,那么还可以将函数作为参数返回,这种形式就称之为闭包
闭包最大的好处就是即用即调,闭包对于安装计算,隐藏状态,以及在函数对象和作用域中随意地切换是很有用的!
#!/usr/bin/env python # -*- coding:utf-8 -*- def func(rate): count = [0] def add_func(arg): count[0] +=1 print("第%s次调用"%count[0]) arg = arg - arg*rate return arg return add_func closure = func(0.03) print(closure(1000)) print(closure(1100)) print(closure(1200))
闭包示例
例子中做了一个减去手续费后返回余额的功能,首先执行了func函数,将利率封装了进去,然后,func函数把它内部的函数进行了进行了返回
要知道当函数不加括号的时候是不执行的!,所以此时closoure就是 add_func 函数的内存地址,当想要使用这个功能的时候,直接把closoure加括号
并传入值即可执行。并且可以看到的是在全局作用域中执行,随时可以切换到局部作用域。
函数可以用来当做返回值,可以用调用自己本身,高阶函数就是函数的参数把另一个函数作为参数,这种函数就称之为高阶函数。
def func_1(num): return num+1 def func_2(num): return num-1 def func_main(num,func): # 可以简写成return func(num) results = func(num) return results results = func_main(10,func_1) print(results) print(func_main(10,func_2))
高阶函数
编写高阶函数,就是让函数的参数能够接收别的函数。
内置函数就是python中内置的一些方法
内置函数使用方法示例,详细介绍请参考
# !/usr/bin/env python # -*- coding:utf-8 -*- #返回数字的绝对值。 参数可以是整数或浮点数。 如果参数是复数,则返回其大小。 print(abs(-1.11)) #传入一个可被循环的元素,如果这个元素中有一个为False则都为假 # 0 空值 False 都为假 print(all([1,2,3])) #与all相反,只有一个为真,则为真; print(any([0,2,False])) #这个函数跟repr()函数一样,返回一个可打印的对象字符串方式表示。当遇到非ASCII码时 #就会输出\x,\u或\U等字符来表示。与Python 2版本里的repr()是等效的函数。 print(ascii("dsads"),ascii(66),ascii('b\23')) #将十进制转换为二进制; print(bin(10)) #返回布尔值,即True或False之一,如果参数为false或省略,则返回False; 否则返回True。 print(bool(1)) #根据传入的参数创建一个新的字节数组 #如果传入字符串必须给出编码 print(bytearray('你好','utf-8')) #当source参数是一个可迭代对象,那么这个对象中的元素必须符合大于0 小于256 print(bytearray([256,1,2])) #返回一个的“bytes”对象,返回bytes类型 bytes('中文','utf-8') #检查对象是否可以被调用 def func(): pass print(callable(func)) #返回整数所对应的Unicode字符,chr(97)返回字符串'a',而chr(8364)返回字符串'€'。 print(chr(126)) #是用来指定一个类的方法为类方法,类方法可以不实例化直接调用 class A: @classmethod def B(cls,arg1,): print(arg1) A.B(1) A().B(1) #将源编译为代码或者AST对象。代码对象能够通过exec语句来执行或者eval()进行求值。 #源可以是正常字符串,字节字符串或AST对象。 expr = "5+5-1" obj = compile(expr,"","eval") print(eval(obj)) #返回值为real + imag * j的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数。 print(complex(1, 2)) print(complex(1)) print(complex("1+2j")) # 参数是一个对象和一个字符串。 该字符串必须是对象属性之一的名称。 class A: def a1(self): print("a1") def a2(self): print("a2") obj = A print(dir(obj)) delattr(obj, "a1") print(dir(obj)) #dir 返回对象中的方法 strs="aaa" print(dir(strs)) #返回两个数值的商和余数 print(divmod(7,3)) #用于遍历序列中的元素以及它们的下标 print(enumerate([1,2,3]))#返回的是可迭代的对象 for i,j in enumerate(('A','B','C')): print(i,j) #将字符串str当成有效的表达式来求值并返回计算结果。 print(eval("1+2+3")) print(eval("False or True")) #字符串str当成动态语句块执行并返回结果 exec('a=1+2+3') print(a) #使用指定方法(方法,函数),过滤可迭代对象的元素 def add(arg): return arg > 3 for i in filter(add,[1,2,3,4,5]): print(i) #浮点型 print(float(11)) #格式化显示 更多方法请参考官方说明 print('{:,.2f}'.format(111111)) #根据传入的参数创建一个新的不可变集合 a = frozenset([1,2,3,4,5]) print(a) #获取对象的属性值 class A(): def __init__(self,): self.name = "123" b = A() print(getattr(b,'name')) #返回当前作用域内的全局变量和其值组成的字典 print(globals()) #检查对象是否含有属性 class A(): def __init__(self,): self.name = "123" b = A() print(hasattr(b,'name')) #哈希值计算 #在当前环境中是唯一的 print(hash('Hello')) #help帮助 def funcs(args): """ Function description :param args: args = list :return: """ pass print(help(funcs)) #转换16进制 print(hex(44)) #显示对象的标识符 print(id("123")) #input标准输入 s = input("user name:") print(s) #int返回整数 print(int(1.2)) print(int("2")) #判断对象是否是类或者类型元组中任意类元素的实例 print(isinstance("1",int)) print(isinstance(1.1,(int,float))) #判断类是否是另外一个类或者类型元组中任意类元素的子类 print(dir(str)) print(issubclass(bytearray,str)) print(issubclass(bool,int)) #根据传入的参数创建一个新的可迭代对象 a = iter('12345') print(next(a)) print(next(a)) #返回对象的长度len a = [1,2,3,4] #转换列表 print(list("abcd")) #返回当前作用域内的局部变量和其值组成的字典 def A(): print(locals()) s = 1 print(locals()) A() #使用指定方法去作用传入的每个可迭代对象的元素,生成新的可迭代对象 def add(x): return x+100 lists = [1,2,3,4] for i in map(add,lists): print(i) #max:返回最大值 print(max(1,2,3)) print(max([1,2,3,4])) #在进行切片并赋值数据时,不需要重新copy原列表数据,可以直接映射原数据内存; s = memoryview(b'abcd') print(s[1]) #返回最小值 print(min(1,2,3)) print(min([2,3])) #返回可迭代对象中的下一个元素值 a = iter('1234') print(next(a)) #创建一个新的object对象(新式类) class B(object): pass #转化成8进制数字符串 print(oct(10)) #open文件操作 file = open('test.txt',encoding="utf-8") #ord:返回Unicode字符对应的整数 print(ord("A")) #幂运算 print(pow(2,3)) #标准输出 print() #property:标示属性的装饰器 #类中使用具体方法请百度,或者等待后续更新 property #range:根据传入的参数创建一个新的range对象 range(10) range(1,10) """repr()函数得到的字符串通常可以用来重新获得该对象,repr()的输入对python比较友好。 通常情况下obj==eval(repr(obj))这个等式是成立的。""" obj='Python' print(eval(repr(obj))) #翻转序列 a = reversed([1,2,3,4,5]) print(list(a)) #round:对浮点数进行四舍五入求值 print(round(1.5)) #set 转换成集合 print(set([1,2,3])) #setattr:设置对象的属性值 class A(): def __init__(self,age): self.age = age s = A(11) print(s.age) setattr(s,'age',22) print(s.age) #根据传入的参数创建一个新的切片对象 c1 = slice(3) c2 = slice(2,4) c3 = slice(0,5,2) s = [1,2,3,4,5,6] print(s[c1]) print(s[c2]) print(s[c3]) #排序,返回一个新的列表默认按字符ascii码排序 a = [4,3,2,1,7] print(sorted(a)) #标示方法为静态方法的装饰器 class B(object): def __init__(self,age): self.age = age @staticmethod def hello(args): print(args) B.hello("Hello World") #字符串类型 print(str(123)) #求和 print(sum([1,2,3,4])) #根据传入的参数创建一个新的子类和父类关系的代理对象 class A(object): def __init__(self): print("我是 A Clase") class B(A): def __init__(self): print("我是 B Class") super().__init__() b = B() #元祖 tuple([1,2,3,4]) #type 返回对象的类型 print(type([1])) print(type("1")) #返回当前作用域内的局部变量和其值组成的字典,或者返回对象的属性列表 def func(): print(vars()) s = 1 print(vars()) func() #聚合传入的每个迭代器中相同位置的元素,返回一个新的元组类型迭代器 list1 = [1,2,3] list2 = ["A","B","C","D"] print(zip(list1,list2)) for i in zip(list1,list2): print(i) #__import__:动态导入模块 __import__
更多简学Python第三章__函数式编程、递归、内置函数 相关文章请关注PHP中文网!