基础梳理-python基础复习-抽象之自定义函数

介绍

基础不牢,地动山摇”,新的征程开始前,先把基础打牢。基础梳理系列将从离散数学、python、算法原理等方面并行展开。希望,能够坚持下去,把这份学习记录做好。
在这里插入图片描述

系列文章目录

离散数学
第一章:基础梳理-离散数学-01集合、关系、元组

python基础
第一章: 基础梳理-python基础复习-基础知识
第二章: 基础梳理-python基础复习-列表和元组
第三章: 基础梳理-python基础复习-使用字符串
第四章: 基础梳理-python基础复习-字典
第五章: 基础梳理-python基础复习-抽象1
第六章: 基础梳理-python基础复习-抽象2

正文

1 抽象相关理论

  • 抽象的现实价值:将复杂的东西结构化,把不容易理解的封装(隐藏)起来。
  • 结构化编程的核心:自定义函数。

2 使用要义

  • 判断某个函数是否可调用,使用callable(函数名)函数
>>> callable(sqrt)  # 未定义赋值的变量名,报错NameError
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'sqrt' is not defined
>>> a=1 # 存在,但非函数名,返回False
>>> callable(a)
False

'''返回True'''
>>> callable(print) # 内置函数
True
>>> def test():  # 自定义函数
...     return
...
>>> callable(test)
True
  • 给函数编写文档,在函数名后以 字符串 的形式编写
>>> def test(): "test callable()" # 字符串也可以单独一行
...
>>> test._doc_ # 注意function的属性名为 __doc__而非_doc_
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute '_doc_'
>>> test.__doc__ # 
'test callable()'
  • 交互式编译器中可使用 help(函数名)获取有关函数信息(包括文档字符串)。
  • python中存在其实并不是 函数 的函数

3 参数

3.1 区别两个参数:

实参:调用时提供的值
形参:def时提供的值

3.2 函数内修改参数,避免对外部影响

不可变变量:无法修改变量值,故对外部不可能有影响

可变变量:修改内部参数值,对外部有影响—》故为避免给外部带来的影响,实参应为副本

>>> a=[1,2,3,4,5] # 可变变量:外部可修改
>>> a[1]='a'
>>> a
[1, 'a', 3, 4, 5]
>>> change(a)  # 可变变量:内部修改,外部会受到影响
>>> def change(b):
...     b[1]='b'
...
>>> change(a)
>>> a
[1, 'b', 3, 4, 5]

拓展: 没有内置对数组的支持,但可以使用 Python 列表代替。

3.3 使得函数内变量影响函数外

方法如下
return
放在可变数据结构中

3.4 位置参数和关键字参数(实参角度)

位置参数
其位置比名字更重要
直接使用
必须先指定所有的位置参数
关键字参数
通过 = 指定对应的形参
参数的顺序无关紧要
有助与澄清各个参数的作用
关键字参数在位置参数之后指定
调用时,就不想用关键字参数,又不想给每个参数赋值===》 给参数指定默认值
给参数指定默认值(形参)
给参数指定默认值后可不提供
含多个默认值的参数,调用时是否提供、提供多少都可以。
'''函数定义'''
>>> def swap(a,b=1): # b设置了默认值
...     c=a-b
...     return c
...
'''位置参数展示'''
>>> swap(3,5) # 3,5位置参数
-2
>>> swap(5,3) # 位置参数位置交换==》结果变了
2
>>> swap(5) # 5位置参数+默认值b=1==》正常输出
4
'''关键字参数展示'''
>>> swap(a=3,b=5) # 关键字参数
-2
>>> swap(b=5,a=3) # 关键字参数交换位置===》结果不变
-2

3.5 收集参数(形参)

1.参数前面的 * 收集余下的位置参数(不会收关键值),放在一个元组中
2.如果没有可供收集的则为空元组
3.对应的,该函数的实参个数不再有上限,但其下限由不含 * 且未指定默认值的参数个数决定
4.定义时,带星号的参数可不放在最后位置;但调用时,其后续参数必须以关键字形式赋值。
5.要收集关键字可使用 收集为字典, 且 不会收集非关键字
6. * 仅仅表示收集无其他意义

"""1.参数前面的 * 收集余下的位置参数(==不会收关键值==),放在一个元组中
"""2.如果没有可供收集的则为空元组"""
"""3.对应的,该函数的实参个数不再有上限,但其下限由不含 * 且未指定默认值的参数个数决定"""
>>> collect("aas",c="asd")
()

"""4.定义时,带星号的参数可不放在最后位置;但调用时,其后续参数==必须==以关键字形式赋值"""
"""6.  * 仅仅表示收集无其他意义"""
>>> collect("aas","sd","asd") # 4
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: collect() missing 1 required keyword-only argument: 'c'
>>> collect("aas","sd",c="asd")
('sd',)

"""5.要收集关键字可使用 **收集为字典, 且** 不会收集非关键字 ** """
>>> collect("aas","sd",m="key",c="asd")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: collect() got an unexpected keyword argument 'm'
>>> def collect(a,*b,c,**d):
...     print(b)
...     print(d)
...
>>> collect("aas","sd",m="key",c="asd")
('sd',)
{'m': 'key'}

""" """
>>> collect("aas","sd",m="key",c="asd")
('sd',)
{'m': 'key'}
>>> def collect(a,c,**d):
...     print(d)
...
>>> collect("aas","sd",m="key",c="asd")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: collect() got multiple values for argument 'c'

3.6 分配参数

1.调用时使用,分配参数多或少一样TypeError
2. * 将元组中的值分配
3. ** 可将字典中的值分配给对应参数名的参数
4. 可以是参数列表的一部分,但应该位于末尾
5. 当调用和分配时都用 * **,将只传递元组或字典==有用只有在定义函数(允许可变数量的参数)、调用参数(拆分字典或序列)时
6. 与关键字不关键字无关

"""  1.调用时使用,分配参数多或少一样TypeError
		2. * 将元组中的值分配  """
>>> def assign(a,b):
...     print(a)
...     print(b)
...
>>> p1=('q',1,2)
>>> assign(*p1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: assign() takes 2 positional arguments but 3 were given
>>> p2=('q',1)
>>> assign(*p2)
q
1


>>> def assign(a,b,c=1,d=2):
...     print(a)
...     print(b)
...     print(c)
...     print(d)
...
>>> p3=('q',1,3,4)
>>> assign(*p3)
q
1
3
4
>>> assign(1,1,*p2)
1
1
q
1

"""3.  ** 可将字典中的值分配给对应参数名的参数
	4.  可以是参数列表的一部分,但应该位于末尾 """

>>> def assign(a,b,c=1,d=2):
...     print(a)
...     print(b)
...     print(c)
...     print(d)
...

>>> p4={'c':3,'d':4}
>>> assign(1,1,**p4)
1
1
3
4
>>> p5={'a':1,'b':2,'c':3,'d':4}
>>> assign(p5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: assign() missing 1 required positional argument: 'b'
>>> assign(**p5)
1
2
3
4

4 作用域

  • 内置函数vars(),返回 命名空间,即一个字典。
  • 不要修改该字典,这样做的结果不确定。
  • 函数内使用的变量叫局部变量,与之对应的是,全局变量。
  • 函数内的变量与全局变量重名时,出现“遮盖”问题。
  • 解决方案globals()[变量名]、local()[变量名]分别访问全局变量、局部变量。
  • 作用域嵌套
    • 一个函数嵌套到另一个函数中;
    • 当外面的函数返回而非调用里面的函数,返回的函数能够访问其定义所在的作用域
      • 每当外部函数被调用,都将重新定义内部函数

5 递归

emmm,不想过多强调,两大必要条件
1.极限条件:满足该条件函数直接返回值
2.递归条件:满足该条件后,会调用一次或多次该函数
此外,在递归条件的操作部分,调用函数的参数一定要有变化,不然够不到极限条件,又是个死循环,造就个没有用滴递归。

>>> def recursion(arg):
...      if(arg<9):
...              print(arg)
...              # return 可省略,此时函数之间在利用嵌套作用域,故可互相影响
...      else:
...              print("当前:"+str(arg))
...              arg-=1
...              recursion(arg)
...              print("目前:"+str(arg))
...
>>> recursion(11)
当前:11
当前:10
当前:9
8
目前:8
目前:9
目前:10

6 函数式编程

  1. map(func,seq[seq])对参数seq序列中的每个元素依次执行func()函数
  2. filter(func,seq[seq])对参数seq序列中的每个元素依次执行func()函数,依据返回的布尔值进行过滤
  3. 通常将返回结果list化
  4. 提供lambda表达式创建内嵌的简单函数(),主要供函数式编程使用
  5. howerver没有列表推导可读性高
""" 
	1. map(func,seq[seq])对参数seq序列中的每个元素依次执行func()函数
	 3. 通常将返回结果list化
"""
>>> map(str,range(1,10))
<map object at 0x000001F9C1778820>
>>> list(map(str,range(1,10)))
['1', '2', '3', '4', '5', '6', '7', '8', '9']


""" 
 	2. filter(func,seq[seq])对参数seq序列中的每个元素依次执行func()函数,依据返回的布尔值进行过滤
 	3. 通常将返回结果list化
	4. 提供lambda表达式创建内嵌的简单函数(),主要供函数式编程使用
"""
>>> list(filter(lambda x:x.isalnum(),('1','3','','s')))
['1', '3', 's']

总结

以上就是本章内容,本文仅仅梳理了抽象的一小部分,下一章将继续整理。


如有错漏,敬请指正

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值