函数

函数基本介绍:
1、定义:指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
2、语法:
  def sayhi():#函数名
  print("Hello,I'm nobody!")

  sayhi()#调用函数,如果不加括号,不会执行,打印的只是函数的内存地址,想调用就要加(),可以带参数

  
#下面这段代码
  a,b = 5,8 #同时定义a和b的值
  c = a**b
  print(c)

#改成用函数写
  def calc(x,y):
  result = x**y
  return result #返回函数执行结果
  print(result)
  c = calc(a,b) #a,b为两个参数,传递后调用定义的calc后,结果赋值给c变量
  print(c)

  def sayhi(name): #name是参数
  print("hello",name)
  sayhi("Mr Han") #输入参数后,调用

3、函数的特性:
(1)减少重复代码
(2)使程序变的可扩展
(3)使程序变得易维护


4、函数参数:
(1)形参变量: 只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,嘎查的口吻在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
(2)实参变量 :可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

  def calc(x,y): #x,y为形参
  result = x**y
  return result
  print(result)
  c = calc(3,5) #3,5 为实参
  print(c)

4、默认参数:这个参数在调用时不指定时默认的值,指定后就用指定的值

  def stu_register(name,age,course,country="CN"): #默认参数必须放在位置参数后面(不放到最后报错,)
  print(name,age,country,course)

  stu_register("Mr Han",20,'Python')#不传值默认为CN
  stu_register("Mr Li",22,'Python')
  stu_register("Mr Rain",29,'Python','Korean') #当不是默认时,把要传的值写到最后

 

 

5、关键参数(可以不用按顺序传参数):
  正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可(指定了参数名的参数就叫关键参数),但记住一个要求就是,关键参数必须放在位置参数之后(以位置顺序确定对应关系的参数)

  stu_register("Mr Han",course='PY',age=20,country='JP')


6、非固定参数
#(1)需求:发报警:1个运维人员
  def send_alert(msg,user):
  pass
  #send_alert('别浪了','alex')
(2)#发报警:10个运维人员

  def send_alert(msg,*users):#users前加*可以传动态参数(用*users不太专业,一般专业的写法为*args)
  for u in users:
  print('报警发送给他',u)

  send_alert('别浪了','jack','Lili','monkey','dog')

  #总结如果形参中出现了*(星号),传递的参数就可以不再是固定个数,传递过来的所有参数打包成元组发送给users

#方式一:
  send_alert('别浪了','jack')#可以是传递一个
  send_alert('别浪了','jack','Lili','monkey','dog')#可以是传递多个

#方式二:列表形式的非固定参数 + *
  send_alert('别浪了',*['jack','Lili','monkey','dog']) #传递列表时前面需要加*,如果不加是把整个列表打包成一个元素传递过去,加完*后就不再是元组里套列表,而是直接就是个元组数据传递过去('jack','Lili','monkey','dog')
  方式一与方式二的传递效果是一样的,只不过是两种不同的传递方式
注意:*users后面如果再加参数时,但凡是位置参数对应的值users都会拿走("rain","eric"),会截胡
  def send_alert(msg,*users,age):
  for u in users:
  print("报警发送给他",u)
  send_alert("alex","rain","eric",age = 22)

      此处users的值为:"rain","eric" 

(2)字典形式的非固定参数 + **

  def func(name,*args,**kwargs)#指定的是未定义的参数
  print(name,args,kwargs)

  func('Alex',22,'tesla','500W')
结果:Alex(22,'tesla','500W'){} #字典为空

  func('Alex',22,'tesla','500W',addr='山东',num=123456)
结果:Alex(22,'tesla','500W'){'num':123456,'addr':'山东'}

传参时未加**
  d = {'degree':'primary school'}
  func('PeiQi',d)
结果:PeiQi({'degree':'primary school'},){}

传参时加**
  d = {'degree':'primary school'}
  func('PeiQi',**d) #字典传参时 + **
结果:PeiQi(){'degree':'primary school'}


7、函数-返回值
注意(1)函数在执行过程中只要遇到return语句,就会停止执行并返回结果,可以理解为return语句代表函数的结束
       (2)如果未在函数中指定return,那这个函数的返回值为None
实例:
def stu_register(name,age,course='PY',country='CN'):
print("------注册学生信息------")
print("姓名:",name)
print("age:",age)
print("国籍:",country)
print("课程:",course)
if age > 22:
  return False
else:
  return True
registriation_status = stu_register("小王",22,course="全栈开发",country='JP')
  if registriation_status:
    print("注册成功")
  else:
    print("too old to be a student.")

总结:函数永远且只能返回一个值,如果想返回多个值加逗号,会变为一个元组返回,但仍然为一个值,就是一个元组
例如:return name,age #此处返回一个元组
返回结果:('PeiQi',29)

8、函数-局部变量
局部变量:指在函数里面定义的变量就叫做局部变量,局部变量,只能在局部生效,函数一旦执行完毕局部变量就结束;
全局变量:定义在函数外部一级代码的变量,叫全局变量,全局能用(按照顺序)

在函数内部,可以引用全局变量
如果,全局和局部都有相同的变量,函数会查找变量的顺序是由内而外的

  global 修改全局变量
  字典、列表、集合、对象、类都可修改,字符串,数字,字母不可修改

9、嵌套函数
  def func1():
    print('alex')
    def func2():
      print('eric')
  func1()

(1)func1() #返回结果:alex ,因为函数定义后不去调用永远不会去执行

(2)
  def func1():
    print('alex')
    def func2():
      print('eric')
    func2()
func1()

func1() #返回结果:alex 
           eric
#总结:======>1、函数内部可以再次定义函数;2、函数要想执行必须要去调用

(3)
age = 19
def func1():
  age = 73
  print(age)
  def func2():
    age = 84
    print(age)
  func2()
func1()

返回结果:73
        84

(4)
age = 19
def func1():
  age = 73
  print(age)


  def func2():
    print(age)
  func2()
func1()
返回结果:73
     73
总结:============》由内向外找,一层一层找,在最里层找不到时,去父级级,父级没有再去父级的父级找,在最外面的是全局变量,里面的都是局部变量

(5)
age = 19
def func1():
  age = 73 #age在这里,输出结果?
  def func2():
    print(age)
  func2()
func1()
返回结果:73


(6)
age = 19
def func1():
  print(age)

  def func2():
    print(age)
  age = 73#age在这里输出结果?
  func2()#调用函数前age=73已经存在就不会再到上一级去找
func1()
返回结果:73

(7)
age = 19
def func1():
  def func2():
    print(age)
  func2()
  age = 73#age在这里输出结果?如果此处没有age = 73,会向上找,此时有,系统就不知道该找谁
func1()

返回结果:报错

(8)

age = 19
def func1():
  global age
  def func2():#此处函数未执行前,age已经是19了,往下走到age = 73 后,age = 73就会修改为全局变量
    print(age)
  func2()
  age = 73
func1()
print(age)

返回结果:19
        73
(9)func1先执行,global把全局的已经定义成73了
age = 19
def func1():
  global age
  def func2():
    print(age)
  age = 73 #把age改为73后执行func2
  func2()#执行func2时,在中间的作用域,其实未找到age,因为没有创建变量,用的就是全局变量,就再往上找到age=19,其实在中间作用域的时候已经把age修改为73了
func1()
print(age)
返回结果:73
     73

10、作用域
在python中,一个函数就是一个作用域(与JavaScript类似),局部变量放置在其作用域中;代码定义完后,作用域已经生成,作用域链向上查找

 

11、匿名函数:(可以把多行代码变为一行),主要作用节省代码量和看起来更方便,是和其它方法搭配使用,匿名函数用一次就不再用了,所以没必要起名字
#正常定义函数
def calc(x,y):
  return x*y

#声明一个匿名函数,
lambda x,y:x*y

func = lambda x,y:x*y #因为没有函数名,要调用时先赋值

print(calc(3,8))
print(func(3,8))

 

 流程函数实现

def calc(x,y):
  if x < y:
    return x*y
  else:
    return x/y

匿名函数实现上面的操作,最多支持三元运算,复杂流程函数的无法使用
  func = lambda x,y: x*y if x < y else x/y #等同于上面的流程函数实现方式

 

#需求打印0-10内自己乘自己
data = list(range(10))
print(data)
返回结果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

 

#利用for循环实现0-10内自己乘自己功能
data = list(range(10))
print(data)
for index,i in enumerate(data):
  data[index] = i*i
print(data)

#利用匿名函数实现0-10内自己乘自己功能
data = list(range(10))
print(data)
def f2(n):
  return n*n
#print(map(f2,data))#输出map计算的对象,这时map已经计算出来,想要输出值需要加list
print(list(map(f2,data)))#这里可以用匿名函数代替f2
print(list(map(lambda x:x*x,data)))#同上面的print效果一样======》此种方法就是与其它方法搭配使用
返回:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
      [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

posted @ 2018-05-26 23:40  MrHB  阅读(105)  评论(0编辑  收藏  举报