一 函数知识体系

什么是函数?
为什么要用函数?
函数的分类:内置函数与自定义函数
如何自定义函数
语法
定义有参数函数,及有参函数的应用场景
定义无参数函数,及无参函数的应用场景
定义空函数,及空函数的应用场景
调用函数
如何调用函数
函数的返回值
函数参数的应用:形参和实参,位置参数,关键字参数,默认参数,*args,**kwargs
高阶函数(函数对象)
函数嵌套
作用域与名称空间
装饰器
迭代器与生成器及协程函数
三元运算,列表解析、生成器表达式
函数的递归调用
内置函数
面向过程编程与函数式编程

二 函数基础

一 引子

 1 什么是函数
函数1就是具备某一功能的工具 2 为什么要用函数
1 程序的组织结构不清晰,可读性差
2 代码冗余
3 可扩展性差 3 如何用函数
函数的使用必须遵循的原则:先定义,后调用
修理工事先准备工具的过程即函数的定义
修理工遇到应用场景拿来工具就用即函数的调用 语法:
def 函数名(参数1,参数2,...):
"""
文档注释
"""
code1
code2
code3
......
return 返回值 def:定义函数的关键字
函数名: 就相当于一个变量名,指向函数的内存地址,
注意:函数的内存地址()就可以出发函数体代码的执行 参数: 参数是函数的调用者为函数体代码传值的媒介,在python中函数的参数无需声明类型
"""文档注释""" : 推荐写上
代码块:就是函数体功能的具体实现
return 返回值 :函数体代码块运行的成果 函数的使用分为两个阶段:
定义阶段: 只检测语法,不执行代码
调用阶段:运行函数体代码
def foo():
xxx
print()

二 定义函数

三 调用函数

函数的调用:函数名加括号
1 先找到名字
2 根据名字调用代码
无return->None
return 1个值->返回1个值
return 逗号分隔多个值->元组

四 函数的参数

#形参即变量名,实参即变量值,函数调用时,将值绑定到变量名上,函数调用结束,解除绑定
#1、位置参数:按照从左到右的顺序定义的参数
位置形参:必选参数
位置实参:按照位置给形参传值
总结:依位传值
#2、关键字参数:按照key=value的形式定义的实参
无需按照位置为形参传值
注意的问题:
1. 关键字实参必须在位置实参右面
2. 对同一个形参不能重复传值
总结:依关键词传值
#3、默认参数:形参在定义时就已经为其赋值
可以传值也可以不传值,经常需要变得参数定义成位置形参,变化较小的参数定义成默认参数(形参)
注意的问题:
1. 只在定义时赋值一次
2. 默认参数的定义应该在位置形参右面
3. 默认参数通常应该定义成不可变类型
总结:选择传值
#4、可变长参数:
可变长指的是实参值的个数不固定
而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参对应有两种解决方案来完整地存放它们,分别是*args,**kwargs 总结:*元组与位置参数转换,**字典与关键字参数转换
#5、命名关键字参数:
    *后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递可以保证,传入的参数中一定包含某些关键字
总结:限制关键词传值

五 练习题

三 函数对象、函数嵌套、名称空间与作用域、装饰器

一 函数对象

#1 可以被引用
#2 可以当作参数传递
#3 返回值可以是函数
#3 可以当作容器类型的元素
 利用该特性,优雅的取代多分支的if
 def foo():
print('foo') def bar():
print('bar') dic={
'foo':foo,
'bar':bar,
}
while True:
choice=input('>>: ').strip()
if choice in dic:
dic[choice]()

二 函数嵌套

三 名称空间与作用域

#名称空间:存放名字的地方,三种名称空间,(之前遗留的问题x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方)
python test.py
#1、python解释器先启动,因而首先加载的是:内置名称空间
#2、执行test.py文件,然后以文件为基础,加载全局名称空间
#3、在执行文件的过程中如果调用函数,则临时产生局部名称空间
名字的查找顺序
局部名称空间--->全局名称空间--->内置名称空间

 #1、作用域即范围
- 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效
  - 局部范围(局部名称空间属于该范围):临时存活,局部有效
#2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下
x=1
def f1():
def f2():
print(x)
return f2
x=100
def f3(func):
x=2
func()
x=10000
f3(f1()) #3、查看作用域:globals(),locals() LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
locals 是函数内的名字空间,包括局部变量和形参
enclosing 外部嵌套函数的名字空间(闭包中常见)
globals 全局变量,函数定义所在模块的名字空间
builtins 内置模块的名字空间
 #global:在局部声明一个名字是来自于全局作用域的,可以用来在局部修改全局的不可变类型
# x=1
# def foo():
# global x
# x=2
#
# foo()
# print(x) #nonlocal:声明一个名字是来自于当前层外一层作用域的,可以用来在局部修改外层函数的不可变类型
x=0
def f1():
x=111
def f2():
# global x
nonlocal x
x=222
f2()
print(x) f1()
# print(x)

四 闭包函数

闭包的意义与应用

 #闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
#应用领域:延迟计算(原来我们是传参,现在我们是包起来)
from urllib.request import urlopen def index(url):
def get():
return urlopen(url).read()
return get baidu=index('http://www.baidu.com')
print(baidu().decode('utf-8'))
 # 为函数体传值的方式一:参数
# def func(x,y):
# print(x+y)
#
# func(1,2) # 为函数体传值的方式二:闭包
# def outter(x,y):
# # x=1
# # y=2
# def func():
# print(x+y)
# return func
#
# f=outter(1,2)
# f()
# f()
# f()

五 装饰器

装饰器的依据是闭包函数,通过复数闭包实现在不改变原函数的情况下插入操作的目的,即装饰。

 无参装饰器:
def outter(func):
def wrapper(*args,**kwargs):
前部操作
res=func(*args,**kwargs)
后部操作
return res
return wrapper
# 有参装饰器的模板
def outter1(x,y,z):
def outter2(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
return outter2
装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
wraps补充:
functools.wraps 的作用是将原函数对象的指定属性复制给包装函数对象, 默认有 module、name、doc,或者通过参数选择。
 from functools import wraps

 def deco(func):
@wraps(func) #加在最内层函数正上方
def wrapper(*args,**kwargs):
return func(*args,**kwargs)
return wrapper @deco
def index():
'''哈哈哈哈'''
print('from index') print(index.__doc__)

六 练习题

四 迭代器、生成器、面向过程编程

#1、为何要有迭代器?
对于序列类型:字符串、列表、元组,我们可以使用索引的方式迭代取出其包含的元素。但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则必须找出一种不依赖于索引的迭代方式,这就是迭代器 #2、什么是可迭代对象?
可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,如下
'hello'.__iter__
(1,2,3).__iter__
[1,2,3].__iter__
{'a':1}.__iter__
{'a','b'}.__iter__
open('a.txt').__iter__ #3、什么是迭代器对象?
可迭代对象执行obj.__iter__()得到的结果就是迭代器对象
而迭代器对象指的是即内置有__iter__又内置有__next__方法的对象

 即:iter() 函数用来生成迭代器。

  next() 返回迭代器的下一个项目。

 dic={'a':1,'b':2,'c':3}
iter_dic=dic.__iter__()
while 1:
try:
k=next(iter_dic)
print(dic[k])
except StopIteration:
break
等于
#基于for循环,我们可以完全不再依赖索引去取值了
dic={'a':1,'b':2,'c':3}
for k in dic:
print(dic[k]) #for循环的工作原理
#1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
#2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
#3: 重复过程2,直到捕捉到异常StopIteration,结束循环

生成器:yield

 def func():
print('====>first')
yield
print('====>second')
yield
print('====>third')
yield
print('====>end') f=func()
#f=f.__iter__()
print(next(f))
print(next(f)) C:\Users\王康杰\AppData\Local\Programs\Python\Python36-32\python.exe C:/Users/王康杰/PycharmProjects/python博客/8-2.py
====>first
None
====>second
None 进程完成,退出码 0
 def func():
print('====>first')
yield 1
print('====>second')
yield 2
print('====>third')
yield 3
print('====>end') f=func()
#f=f.__iter__()
print(next(f))
print(next(f)) C:\Users\王康杰\AppData\Local\Programs\Python\Python36-32\python.exe C:/Users/王康杰/PycharmProjects/python博客/8-2.py
====>first
1
====>second
2 进程完成,退出码 0

五 三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数

三元表达式

 name=input('姓名>>: ')
res='SB' if name == 'alex' else 'NB'
print(res)

列表推导式

 #2、语法
[expression for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN
]

生成器表达式

 #1、把列表推导式的[]换成()就是生成器表达式

 #2、示例:生一筐鸡蛋变成给你一只老母鸡,用的时候就下蛋,这也是生成器的特性
>>> chicken=('鸡蛋%s' %i for i in range(5))
>>> chicken
<generator object <genexpr> at 0x10143f200>
>>> next(chicken)
'鸡蛋0'
>>> list(chicken) #因chicken可迭代,因而可以转成列表
['鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4',] #3、优点:省内存,一次只产生一个值在内存中

递归

1、递归调用应该包含两个明确的阶段:回溯,递推
回溯就是从外向里一层一层递归调用下去,
回溯阶段必须要有一个明确地结束条件,每进入下一次递归时,问题的规模都应该有所减少(否则,单纯地重复调用自身是毫无意义的) 递推就是从里向外一层一层结束递归
2、

  

 #总结递归的使用:
1. 必须有一个明确的结束条件 2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少 3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

匿名函数

lambda

内置函数

abs()求绝对值函数

all() 函数用于判断给定的可迭代参数 iterable 中的所有元素是否都为 TRUE,如果是返回 True,否则返回 False。

any() 函数用于判断给定的可迭代参数 iterable 是否全部为 False,则返回 False,如果有一个为 True,则返回 True。
# print(any([0,'',None,False]))

# bin 10——》2
# oct 10——》8
# hex 10——》16

bool() 函数用于将给定参数转换为布尔类型,如果没有参数,返回 False。

bool 是 int 的子类。

# res='你'.encode('utf-8')
# res='你'.encode('utf-8')
# res=bytes('你',encoding='utf-8')
# print(res,type(res))

# print(callable(len))

# print(chr(65))
# print(chr(90))
#
# print(chr(97))
# print(chr(122))
#

ord() 函数是 chr() 函数(对于8位的ASCII字符串)或 unichr() 函数(对于Unicode对象)的配对函数,它以一个字符(长度为1的字符串)作为参数,返回对应的 ASCII 数值,或者 Unicode 数值,如果所给的 Unicode 字符超出了你的 Python 定义范围,则会引发一个 TypeError 的异常。

# import time
# print(dir(time))

python divmod() 函数把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)。
# print(divmod(3003,20))

# for i in enumerate(['a','b','c']):
# print(i)

# res=eval('[1,2,3]')
# print(res,type(res))

# s=set({1,2,3})
# s.add(4)
# print(s)

# fs=frozenset({1,2,3})   frozenset() 返回一个冻结的集合,冻结后集合不能再添加或删除任何元素。

函数是计算x的y次方,如果z在存在,则再对结果进行取模,其结果等效于pow(x,y) %z

注意:pow() 通过内置的方法直接调用,内置方法会把参数作为整型,而 math 模块则会把参数转换为 float。

# print(pow(2,3,3)) #(2**3)%3

# l=[1,'a','3',3]
# l1=reversed(l)函数返回一个反转的迭代器。
# print(list(l1))

# print(round(3.5))round(数值,保留小数位数) 方法返回浮点数x的四舍五入值。
#

print(round(5656.3657,-2))
5700

l=['a','b','c','d','e']
s='helloworld'

slice() 函数实现切片对象,主要用在切片操作函数里的参数传递。

class slice(stop)
class slice(start, stop[, step])
  • start -- 起始位置
  • stop -- 结束位置
  • step -- 间距

obj=slice(1,5,2)

# print(l[1:5:2])
# print(l[obj])

# print(s[1:5:2])
# print(s[obj])

# print(vars() is locals())vars() 函数返回对象object的属性和属性值的字典对象。

zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存

# l=[1,2,3,4,5,6,7]
# s='hello'
#
# res=zip(l,s)
# print(list(res))

__import__() 函数用于动态加载类和函数 。

如果一个模块经常变化就可以使用 __import__() 来动态载入。

# import 'time'
m=__import__('time')
print(m.time())

# 面向对象
object.__dict__

classmethod
staticmethod
property

delattr
hasattr
getattr getattr() 函数用于返回一个对象属性值。
setattr setattr 函数对应函数 getatt(),用于设置属性值,该属性必须存在

isinstance
issubclass

object

super

eval() 函数用来执行一个字符串表达式,并返回表达式的值。

 >>>x = 7
>>> eval( '3 * x' )
21
>>> eval('pow(2,2)')
4
>>> eval('2 + 2')
4
>>> n=81
>>> eval("n + 4")
85

exec 执行储存在字符串或文件中的Python语句,相比于 eval,exec可以执行更复杂的 Python 代码。

 >>>exec 'print "Hello World"'
Hello World
# 单行语句字符串
>>> exec "print 'runoob.com'"
runoob.com # 多行语句字符串
>>> exec """for i in range(5):
... print "iter time: %d" % i
... """
iter time: 0
iter time: 1
iter time: 2
iter time: 3
iter time: 4
 x = 10
expr = """
z = 30
sum = x + y + z
print(sum)
"""
def func():
y = 20
exec(expr)
exec(expr, {'x': 1, 'y': 2})
exec(expr, {'x': 1, 'y': 2}, {'y': 3, 'z': 4}) func()

六 函数草稿 

最新文章

  1. Boost正则表达式的编译与使用方法集
  2. Winform水印
  3. C\C++ sizeof 陷阱&amp;&amp;总结
  4. hdu 5653 Bomber Man wants to bomb an Array
  5. BZOJ2675 : Bomb
  6. jsp 标签、 项目全路径引用${CTX}
  7. python用装饰器实现缓存函数执行结果
  8. 8.11-8.16:usaco
  9. 安装mod_deflate模块启用apache的GZIP压缩
  10. memcache和memcached
  11. Java Spring各种依赖注入注解的区别
  12. 使用ant自动编译、打包生成apk文件
  13. 从汇编看c++中全局对象和全局变量
  14. luogu P2617 Dynamic Rankings &amp;&amp; bzoj 1901 (带修改区间第k大)
  15. MPICH2简单的安装配置总结
  16. HDU 5950 Recursive sequence(矩阵快速幂)
  17. Linux Input子系统
  18. (转载)mybatis中传入参数是list或map
  19. flask框架----设置配置文件的几种方式
  20. 十:python 对象类型详解六:文件

热门文章

  1. 查看mysql连接数和状态
  2. Discuz!开发之时间处理函数dgmdate()详解
  3. centos7删除Apache组件
  4. var定义变量的使用细节
  5. mybatis框架-resultMap的自动映射级别-partial 和full的探讨
  6. 2016 ACM/ICPC亚洲区沈阳站
  7. OpenCV 学习笔记(15)openc解帧视频
  8. learning shell check requires root privileges
  9. ESA2GJK1DH1K基础篇: Android连接MQTT简单的Demo
  10. 在Hadoop-3.1.2上安装HBase-2.2.1