Python学习 day5-2021.3.3(函数)


Python入门课程系列:

  • Python学习 day1:认识Python
  • Python学习 day2:判断语句与循环控制
  • Python学习 day3:高级数据类型
  • Python学习 day4:函数基础

A. 函数的基本类型

⚠️B. 局部变量

在函数内部定义的变量就是局部变量,作用域仅仅局限在函数的内部
不同的函数可以定义相同的局部变量,但各自用各自的,不会互相产生影响
局部变量的作用:为了临时保存数据,需要在函数中定义来进行存储

def TestMethod():
    name='ling' #在函数TestMethod里定义变量name,这个变量在TestMethod中,别的函数不可使用
    print(name)
    pass
TestMethod()
#ling

⚠️C. 全局变量

全局变量与局部变量的区别在于作用域的不同
当全局变量和局部变量的变量名称一致(即出现重复定义的时候),程序会优先使用函数内部的变量(局部变量)
如果想在函数内部对全局变量进行修改,必须使用global关键字

#定义全局变量pro
pro="计算机信息管理"
def TestMethod():
    name='ling'
    print('{}.{}'.format(name,pro))
    pass
TestMethod()
#ling.计算机信息管理

#修改全局变量
def  changeGlobal():
    '''
    修改全局变量
    :return:
    '''
    pro='市场营销'
    pass
changeGlobal()
print(pro)
#计算机信息管理    (并没有修改)
def  changeGlobal():
    '''
    修改全局变量
    :return:
    '''
    global pro
    pro='市场营销'
    pass
changeGlobal()
print(pro)
#市场营销

D. 引用

在python中,值是靠引用来传递的,可以用id()查看一个对象的引用是否相同,id是值保存在内存中那块内存地址的标识。

#不可变类型(int类型,str类型,元组类型,都属于不可变类型)
a=1 
def fun(x):
    print('x的地址:{}'.format(id(x)))
    pass
#调用函数
print('a的地址:{}'.format(id(a)))
fun(a)
#a的地址:140628157667632
#x的地址:140628157667632
a=1
def fun(x):
    print('x的地址:{}'.format(id(x)))
    x=2
    print('x修改后的地址:{}'.format(id(x)))
    pass
#调用函数
print('a的地址:{}'.format(id(a)))
fun(a)
#a的地址:140296529778992
#x的地址:140296529778992
#x修改后的地址:140296529779024

#可变类型 (字典和列表属于可变类型)
li=[]
print(id(li))
def testRenc(parms): #parms是形参,不占用内存地址
    print(id(parms))
    pass
print(id(li))
testRenc(li)
#140351363343296
#140351363343296
#140351363343296
li=[]
print(li)
print(id(li))
def testRenc(parms):
    parms.append([1,2,3,4,5])
    print(id(parms))
    print('内部的变量对象{}'.format(parms))
    pass
testRenc(li)
print(id(li))
print(li)
print('外部的变量对象{}'.format(li))
#[]
#140346345907264
#140346345907264
#内部的变量对象[[1, 2, 3, 4, 5]]
#140346345907264
#[[1, 2, 3, 4, 5]]
#外部的变量对象[[1, 2, 3, 4, 5]]

不可变类型被改变时,并没有改变原内存地址中的值,而是重新开辟了一块内存,将原地址对应的值复制过去了,对这块新开辟的内存中的值进行操作。
当全局变量为可变数据类型时,局部函数可以改变其地址所对应的数值,而不改变其地址。

小结:

  1. 在python当中 ,万物皆对象,在函数调用的时候,实参传递的是通过对对象的引用完成的
  2. 了解了原理之后,就可以更好的去把控函数内部的处理是否会影响函数外的变化

⚠️E. 匿名函数

这种函数得名于省略了用def声明函数的标准步骤。

  • 语法:lamda 参数1,参数2...参数n:表达式
  • 特点:
    使用lamda关键字去创建函数
    没有名字的函数
    匿名函数冒号后面的表达式有且只有一个(注意:是表达式不是语句)
    匿名函数自带return,而这个return的结果就是表达式计算后的结果
  • 用途:
    可以简化代码
    匿名函数可以作为参数传递
#普通函数计算累加和 
def compute(x,y):
    '''
    计算累加和
    :param x:
    :param y:
    :return:
    '''
    return x+y
    pass
print(compute(10,20))
#匿名函数计算累加和 
lambda x,y:x+y #创建匿名函数
M=lambda x,y:x+y #通过变量调用匿名函数
print(M(20,12))

缺点:lambda只能是单个表达式,不是代码块。仅能封装有限的逻辑复杂逻辑无法实现,必须使用def来定义函数。

⚠️F. 递归函数

递归满足的条件:
自己调用自己
必须有一个明确的结束条件

优点:
使代码看起来更加整洁、优雅
可以用递归将复杂任务分解成更简单的子问题
使用递归比使用一些嵌套迭代更容易

缺点:
递归逻辑很难调试,递归条件处理不好容易造成程序无法结束,直到达到最大递归错误
递归占用大量内存,耗费计算机资源

所有的递归都可以用循环的方式实现,只是递归逻辑更清晰。

#求阶乘
#循环的写法
def factorial(n):
   for item in range(1,n+1):
       result*=item
       pass
   return result
print('5的阶乘{}'.format(factorial(5)))

#递归的方式:
def factorial(n):
   '''
   递归实现
   :param n:阶乘递归
   :return:
   '''
   if n==1:
       return 1
   else:
       return n*factorial(n-1)
   pass
print('5的阶乘{}'.format(factorial(5)))

#❗️递归案例 模拟实现树形结构的遍历
import os #引入文件操作模块
def findFile(file_Path):
   listRs=os.listdir(file_Path) #得到该路径下所有文件夹
   for fileItem in listRs:
       full_path=os.path.join(file_Path,fileItem) #获取完整文件路径
       if os.path.isdir(full_path):#判断是否是文件夹
           findFile(full_path) #如果是一个文件夹 再次递归
       else:
           print(fileItem)
           pass
       pass
   else:
       return
   pass
#调用搜索文件夹对象
findFile('/Users/hh/Desktop')

小结

作业:

传入一个n值,分别使用循环的写法和递归的写法求1到n的阶乘(答案见上)

你可能感兴趣的:(Python学习 day5-2021.3.3(函数))