Python学习tips(2)

论坛 期权论坛 脚本     
匿名技术用户   2020-12-30 16:20   11   0

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

==== 注该文档源于个人在学习廖雪峰老师的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函数返回函数本身,在函数调用前就会将下一步的参数进行计算,传入。

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

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


分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP