Python学习tips(2)

来源:互联网 发布:广电局禁止网络机顶盒 编辑:程序博客网 时间:2024/06/11 14:05

============================================================================

====   注该文档源于个人在学习廖雪峰老师的Python教程时候的随笔,参考网址:

====   https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/

====    其中有少量引用原句,并未标明,若侵权,将致歉删除。

====    本文属于学习笔记,如果理解不正确之处,还望海涵,多请指教

============================================================================= 

 

接Python学习tips(1)


8.       函数

 

8.1 函数调用

函数名本质上是对函数的对象的引用,完全可看做是一个变量,可以赋值给另外一个变量,也既是给函数起一个别名。

 

8.2 定义函数

定义函数要使用def语句,依次写出函数名,括号,括号中的参数和冒号(:),然后函数体要使用缩进。函数返回值使用return语句

如果将函数my_func()函数定义保存为funcs.py文件中,那么可以在该文件的当前目录下启动Python解释器,用

from funcs import my_func

导入my_func()函数。注意funcs是文件名,不包含.py扩展名。

 

8.3空函数

如:

define temp_fun():

    pass

使用pass语句作为占位符。注意:pass语句可以用于其他地方作为占位符,让程序先跑起来。

 

8.4 函数参数检查

使用Python内置方法:isinstance(),如:

def my_abs(x):

    if not isinstance(x,(int,float)):

        ralse TypeError('bad operand type')

    if x > 0:

       return x

   else

      return -x

 

8.5  返回多个参数

如:

import math

def move(x,y,step,angle = 0):

   nx = x + step*math.cos(angle)

   ny = y + step*math.sin(angle)

   return nx,ny

注:import math 语句表示导入math包,则可以引用math中的cos() sin()等函数

 

其实,这是一种假象,返回的是tuple元组,但是为了方便使用,省略了括号。

 

8.6  参数

8.6.1 位置参数

python中普通参数称为位置参数

如:

def power(x):

   return x*x

对于上述函数中的参数x就是位置参数

 

8.6.2 默认参数

在定义函数的时候,给参数初始化一个默认值,这个参数就称为默认参数

如:

def power(x,n = 2)

    s= 1

   while n > 0:

       n = n-1

       s = s * x

   return s

对于上述函数中n为默认参数,在调用时候,如果仅有一个参数,则n就使用默认的参数进行运算

 

Python的函数也允许传入默认参数。

设置默认参数注意事项:

a.必选参数在前,默认参数在后

b.另外,变化频次高的变量放在前面,变化频次小的变量放在后面。

c.当有多个默认参数的时候,只改变后一个默认参数的时候,调用函数时候需要将参数名带上

如:

def eroll(name,gender,age = 6,city = 'SH')

    print(name)

    …

 

调用:

enroll('ww','M',city = 'SQ')

d.重点:默认参数必须指向不变对象,如str,tuple,但不推荐list。

注:如果非要使用list等可变对象作为默认参数,请切记,加入判断使用默认参数的时候,对默认参数复位。

 

 

8.6.3 可变参数

所谓可变参数,是指函数的参数可以是多个不同的值,即传入参数的个数是可变的

当使用普通参数实现这样的功能的时候,需要首先将多个参数装载成list或者tuple,具体实现表现为传入参数时候多个参数需要使用()或者[]包裹。

而可变参数的方法不需要将参数使用()或者[]包裹,直接传入多个参数,个数不定。实现方法和普通参数发的函数定义区别仅仅在与多加上一个星号(*).

普通方法:

define sumup(numbers):

   sum = 0

   for x in numbers:

     sum = sum + x

   return sum

调用方法:

>>>sumup([1,2,3,4])

可变参数法:

define sumup(*numbers):

   sum = 0

   for x in numbers:

     sum = sum + x

   return sum

调用方法:

>>>sumup(1,2,3,4)

在实现可变参数的函数后,对于已经存在的list或tuple参数可以采用如下方法调用:

>>>nums = [1,2,3,4]

>>>sumup(*nums)

即使用星号*把list或者tuple中的参数变成可变参数传入函数中。

 

 

8.6.4关键字参数

可变参数函数允许传入0或者任意个参数,这些可变参数在函数调用的时候被自动组装成一个tuple.而关键字参数同样允许参数0或者任意个含参数名的参数,这些参数在函数内部自动组装成一个dict.

如:

  def person(name, age, **kw):

      print('name:', name, 'age:', age, 'other:', kw)

函数person除了必选参数name和age外,还接受关键字参数kw。在调用该函数时,可以只传入必选参数;也可以传入除了必选参数外的参数,

 

>>> person('Michael', 30)

name: Michael age: 30 other: {}

>>> person('Bob', 35,city='Beijing')

name: Bob age: 35 other: {'city':'Beijing'}

>>> person('Adam', 45, gender='M',job='Engineer')

name: Adam age: 45 other: {'gender': 'M','job': 'Engineer'}

关键字参数的作用:扩展函数功能。

如下,一种简化调用关键字参数的方法。

 

>>> extra = {'city': 'Beijing','job': 'Engineer'}

>>> person('Jack', 24, **extra)

name: Jack age: 24 other: {'city':'Beijing', 'job': 'Engineer'}

 

8.6.5命名关键字参数

如:

def person(name, age, **kw):

   if 'city' in kw:

       # 有city参数,使用if...in...语句来判断,命名关键字参数是否包含某项

       pass

   if 'job' in kw:

       # 有job参数

       pass

   print('name:', name, 'age:', age, 'other:', kw)

如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。这种方式定义的函数如下:

def person(name, age, *, city, job):

 print(name, age, city, job)

和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数。

调用方法,仅限传入如上命名的两种关键字。

 

 

如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:

 

def person(name, age, *args, city, job):

   print(name, age, args, city, job)

命名参数必须赋值。

命名参数可以有缺省值。

命名参数在使用的时候,要将key值标明,否则,会被当做可变参数(当然是,如果函数定义中带有可变参数;如果定义中没有带有可变参数,应该会报错吧?)

 

8.6.6 参数组合:

在Python中共有必选参数(位置参数?),默认参数,可变参数,关键字参数和命名关键字参数,共5种参数类型,这5中参数类型又可以组合使用。但,请注意,使用的时候参数顺序必须按照上述顺序来排列。

 

所以,对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的。

对上述表述解释:任何参数的组合都可以看做是可变参数和关键字参数的组合。可以将必须参数/默认参数装载成tuple,其余参数都是关键字参数,装载成dict,打包放在可变参数中。

 

*args是可变参数,args接收的是一个tuple;输出参数时候可以看到用圆括号()包裹

**kw是关键字参数,kw接收的是一个dict。输出参数看到用大括号{}包裹

以及调用函数时如何传入可变参数和关键字参数的语法:

可变参数既可以直接传入:func(1, 2, 3),又可以先组装list或tuple,再通过*args传入:func(*(1, 2, 3));

关键字参数既可以直接传入:func(a=1, b=2),又可以先组装dict,再通过**kw传入:func(**{'a': 1, 'b': 2})。

使用*args和**kw是Python的习惯写法,当然也可以用其他参数名,但最好使用习惯用法。

命名的关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值。

定义命名的关键字参数在没有可变参数的情况下不要忘了写分隔符*,否则定义的将是位置参数。

 

 

8.7  递归函数

8.7.1定义:如果一个函数内部调用自身,则称为递归函数。

如,求取阶乘的函数:

def fact(n):

   if n = 1:

       return 1

   return n*fact(n-1)

递归函数较之于循环函数逻辑更为清晰。但是递归函数的有着一下特点需要注意:

* 防止栈溢出,因为递归函数每调用一次自身就需要将前一次调用压入栈中,直到最终可计算才逐层退栈。如果递归深度较深,需要注意防止栈溢出

 

8.7.2尾递归

解决调用栈溢出的方法是通过尾递归优化。

定义:函数返回调用函数本身并且不能包含表达式。

如,将上述阶乘函数改为尾递归:

def fact(n):

   return fact_iter(n,1)

 

def fact_iter(num,product):

   if num==1:

       return product

   return fact_iter(num-1,num*product)

可以看出,fact_iter函数返回函数本身,在函数调用前就会将下一步的参数进行计算,传入。

尾递归实际上将递归的多次调用+多层调用栈转化成仅有多次调用来解决,在每次调用之前,计算出下次调用的参数,只占用一个栈帧。

尾递归的方式,在上述实例中可以理解为从尾部开始逆向运算,每次调用首先计算值再递归调用下一次。而递归方法,返回的是一个表达式,将运算压入栈中,直到满足条件的时候再运算,且是正向运算。

 


原创粉丝点击