python学习笔记(三)

函数定义
定义函数

def cylinder_volume(height,radius):
	pi=3.14
	return height*pi*radius**2

调用函数

cylinder_volume(

函数头部:
以def开始,对函数进行定义
自定义函数名称
名称之后是括号,括号里的内容是形参或者实参,是当函数被调用时作为输入传入的值,用在函数主体中,用逗号分割。如果函数没有参数,这些括号留空。
头部始终以英文冒号:结束

函数主体:
函数的剩余部分包含在主题中
在主体中,引用参数并定义新的变量,这些变量只能在这些缩进代码行内使用
包括return语句,用于当函数被调用时返回输入值。

函数的命名规范:
函数名称遵守和变量一样的命名规范

仅在函数名称中使用普通字母,数字和下划线。不能有空格,需要以字母或下划线开头
不能使用python中具有重要作用的保留字或内置标识符

默认参数:
可以向函数中添加默认参数,以便为在函数调用中未指定的参数提供默认值

def cylinder_volume(height,radius=5):
 pi=3.14
 return height*pi*radius**2

在上述示例中,如果在函数调用中忽略了radius,则将该参数设为5.如果在调用中设置了radius,将会把默认值覆盖

函数返回值
return(x,y)时 python函数返回的仍然时单一值 返回的时一个tuple,但是在语法上,返回一个tuple可以省略括号,而多个变量可以同事接收一个tuple,按位置赋给对应的值,所以,python的函数返回多值其实就是返回一个tuple

函数的参数
位置参数

默认参数
定义函数的时候,把参数的名字和位置确定下来,参数的接口定义就完成了。对于函数的调用者来说,只需要知道如何传递正确的参数,以及参数将返回什么样的值就够了。函数内部的复杂逻辑被封装起来,调用者无需了解
默认参数必须指向不变对象
不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。
此外,由于对象不变,多任务环境下同事读取对象不需要加锁,同事读一点问题都没有。在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象

python在函数定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了

可变参数

def calc(numbers):
	sum=0
	for n in numbers:
		sum=sum+n*n
	return sum

但是调用的时候,需要先组装出一个list或tuple:

>calc([1,2,3]
14
>calc(1,3,5,7)
84
如果是可变参数,表达式如下:
>calc(1,2,3)
14

改成可变参数

def calc(*numbers)

定义可变参数和定义一个list或tuple参数相比,仅仅在参数面前加了一个*号。在函数内部,参数numbers接收到的时一个tuple,因此,函数代码完全不变。
calc(*nums):*nums表示把nums这个list的所有元素作为可变参数传进去。

关键字参数
可变参数允许传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许传入0个或人一个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict

def person(name,age,**kw):
	print('name:',name,'age',age,'other:',kw)

kw为关键字参数。可以扩展函数的功能。在person函数里,保证能接收到name和age这两个参数,但是,如果调用者愿意提供更多的参数,也能收到

也可以先组装出一个dict,然后把dict转换为关键字参数传进去

>extra={'city':'beijing','job':'engineer'}
>person('jack',24,city=extra['city'],job=extra['job'])
>person('jack',24,**extra)  //简化写法
name:jack age: 24 other:{'city':'beijing','job':'engineer'}

extra表示把extra这个dict的所有key-value用关键字参数传入到函数的kw参数,kw将获得一个dict,kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra

命名关键字参数
对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。
需要特殊分隔符 * 后面的参数被视为命名关键字参数

def person (name,age,*,city)

*city就是命名关键字参数

参数组合
在python中定义函数,可以用必选参数,默认参数,可变参数,关键字参数和命名关键字参数,这五种参数都可以组合使用。
顺序:必选参数,默认参数,可变参数,命名关键字参数和关键字参数

变量作用域
是指可以在程序的哪个部分引用或使用某个变量
在函数中使用变量时,无比要考虑作用域。如果变量是在函数内创建的,则只能在该函数内使用该变量。无法从该函数外访问该变量。
这意味着可以在不同函数内的不同变量使用相同的名称

def some_function():
	word='hello'
def anther_function():
	word='goodbye'

在函数之外定义的变量依然可以在函数内访问。

word='hello'
def some_function():
	print(word)
print(word)

两个输出的word一样,可以在此函数内以及函数外输出word。

关于变量作用域的更多信息:
在编程时,经常会发现相似的想法不断出现,将使用变量进行计数,迭代和累积要返回的值。为了编写容易读懂的代码,需要对相似的想法使用相似的名称。一旦将多段代码放在一起(比如一个脚本中有多个函数或者函数调用)可能需要为两个不同的概念使用相同的名称
不需要相处新的名称,可以为对象重复使用相同的名称,只要它们位于不同的作用域即可。

最好是将变量定义在所需的最小作用域内。

文档
文档使代码更容易理解和使用。函数由器容易理解,因为他们通常使用文档字符串,简称docstrings。文档字符串是一种注释,用于解释函数的作用以及使用方式。

文档字符串用三个双引号引起来,简要解释了函数的作用

lambda 表达式
可以使用Lanbda表达式创建匿名函数,即没有名称的函数。
lambda表达式非常适合快速创建在代码中以后不会用到的函数。尤其对高阶函数或将其他函数作为参数的函数来说,非常实用。

def multiply(x,y):
	return x*y
改写成:
double=lambda x,y:x*y

lambda函数的组成部分
1 关键字lambda 表示这是一个lambda表达式
2 lambda之后是该匿名函数的一个或多个参数(用英文逗号分割),接着是一个英文冒号:
和函数相似,lambda表达式中的参数名称是随意的
3 最后一部分是被评估并在该函数中返回的表达式,和return语句很像。
lambda不太适合复杂的函数(可以直接写进函数)

迭代器和生成器
迭代器是每次可以返回一个对象元素的对象,例如返回一个列表。
迭代器是一种表示数据流的对象。这与列表不同,列表是可迭代对象,但不是迭代器,因为他不是数据流。

迭代器
直接作用于for循环的数据类型:
1 集合数据类型 list tuple dict set str
2 generator 包括生成器和带yield的generator function

可以直接作用于for循环的对象统称为可迭代对象:Interable

而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,知道最后抛出stopinteration错误表示无法继续返回下一个值了
可以被next()函数调用并不断返回下一个值的对象称为迭代器:iterator

生成器都是iterator对象,但list、dict、str虽然是iterable,却不是iterator
可以使用iter()函数

生成器是使用函数创建迭代器的简单方式,也可以使用类定义迭代器。

def my_range(x):
	i=0
	while i<x:
	yield i
	i+=1

my_range是一个生成器函数,他会生成一个从0到(x-1)的数字流
该函数使用了yield而不是关键字return。这样使函数能够一次返回一个值,并且每次被调用时都从停下的位置继续,关键字yield是将生成器与普通函数区分开来的依据

不使用列表,使用生成器:
生成器是构建迭代器的’懒惰‘的方式,第三内存不够存储完整实现的列表时,或者计算每个列表元素的代价很高,希望尽量推迟计算时,就可以使用生成器。但是这些元素只能遍历一次。

在这里插入图片描述
在这里插入图片描述
生成器 杨辉三角形

递归函数
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数

计算n!

def fact(n):
	if n==1:
		return 1
	else:
	return n*fact(n-1)

递归函数的有点是定义简单,逻辑清晰,理论上所有的递归函数都可以写成循环的方式。但循环的逻辑不如递归清晰

使用递归函数需要注意防止栈溢出。在计算机中,函数调用时通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧,
由于栈的大小不是无限的,所以递归调用的次数过多,会导致栈溢出。

解决递归调用栈溢出的方法时通过尾递归优化,事实上尾递归和循环的效果时一样的,所以,把循环看成时一种特殊的尾递归函数也是可以的。

尾递归是指,在函数返回的时候,调用自身本身,并且return语句不能包含表达式。这样编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况
尾递归:

def fact(1):
	return fact_iter(n,1)
def fact_iter(num,product):
	if num==1:
		return product
	return fact_iter(num-1,num*product)

num-1和num*product在函数调用前就会被计算,不影响函数调用

汉诺塔游戏
它接收参数n,表示3个柱子A、B、C中第1个柱子A的盘子数量,然后打印出把所有盘子从A借助B移动到C的方法
在这里插入图片描述

函数:
map()是一个高阶内置函数,接受函数可迭代对象作为输入,并返回一个将该函数应用到可迭代对象的每个元素的迭代器

filter()是一个高阶内置函数,接受函数和可迭代对象作为输入,并返回一个由可迭代对象中的特定元素(该函数针对该元素会返回true)组成的迭代器。

isinstance()判断一个对象是否是可迭代的对象

参数
*args是可变参数,args接收的是一个tuple
**kw是关键字参数,kw接收的是一个dict

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值