'''摘自尚学堂的python_人工智能课程,用于复习'''
python是一种解释型的,面向对象的语言
python的特点:
1.可读性强(易修改)
2.简介(关注业务本身,生产效率高)
3.面向对象
4.免费和开源
5.可移植性和跨平台(python被编译成与操作系统相关的二进制代码,再解释执行,提高了执行速度,实现了跨平台)
6.丰富的库(标准库,扩展库)
7.可扩展性(可嵌入C和C++语言,python又被称为胶水式语言)
python的应用范围:
1.科学计算
2.人工智能
3.web服务端和大型网站后端
4.GUI开发(图形用户界面开发)
5.游戏开发
6.移动设备开发
7.嵌入式设备开发
8.系统运维
python解释执行,性能较低,影响性能的功能可以使用C等其他语言进行开发
常用的python解释器:Cpython,jython,Ironpython,Pypy
python的交互模式:
1.进入命令行窗口,输入:python
2.>>>即为提示符
3.关闭交互窗口:(1)ctrl+z+回车(2)输入quit()命令(3)直接关闭命令行窗口
4.中断程序的执行:ctrl+c
IDE之idle的使用:
1.win中搜索idle
2.F5运行程序
3.File中可创建或者修改程序
IDLE常用的快捷键
1.Alt+N Alt + P 查看历史命令上一条、下一条
2.ctrl+F6 重启shell,以前定义的变量失效
3.F1打开帮助文档
4.Alt+/ 自动补全前面出现过的单词
5.ctrl+[ ctrl+] 缩进代码和取消缩进
6.Alt+M 打开模块代码,选选中模块,然后按下此快捷键,会帮你打开该模块的py源代码浏览
7.Alt+C 打开类浏览器,方便在源码文件中的各个方法体之间切换
python对缩进有严格的要求
#行注释
'''
这是一个段注释
'''
开始学习图形化程序设计
import turtle #导入turtle模块
turtle.showturtle() #显示箭头
turtle.write('hh') #写字符串
turtle.forward(300) #前进300像素
turtle.color('red') #画笔颜色改为red
turtle.left(90) #箭头左转90度
turtle.forward(300)
turtle.goto(0, 50) #去坐标(0, 50)
turtle.goto(0, 0)
turtle.penup() #抬笔
turtle.goto(0, 300)
turtle.pendown() #下笔
turtle.circle(100) #画圆
python程序的构成
1.python程序由模块组成
2.模块由语句组成
3.语句是python程序的构造单元
\为行连接符
python中一切皆对象,每个对象由:标识、类型、值组成
1.标识用于唯一表示对象,通常对应于对象在计算机内存中的地址,使用内置函数id(obj)可返回对象obj的标识
2.类型用于表示对象存储的数据类型,类型可以限制对象的取值范围,以及可执行的操作,可以使用type(obj)获取对象所属类型
3.值表示对象所存储的数据的信息,使用print(obj)可以直接打印出值
对象的本质就是:一个内存块,拥有特定的值,支持特定类型的相关操作
引用:在python中,变量也称为:对象的引用,因为变量存储的就是对象的地址,变量通过地址引用了对象
变量位于栈内存
对象位于堆内存
python是动态类型语言:变量不需要显示声明类型,根据变量引用的对象,python解释器自动确定数据类型
python是强类型语言,每个对象都有数据类型,只支持该类型支持的操作
标识符:用于变量、函数、类、模块等的名称
标识符命名规则:
1.区分大小写
2.第一个字符必为字母、下划线(后面是字母、数字、下划线)
3.不能用关键字
4.以下划线开头和结尾的通常有特殊含义,如__init__是类的构造函数
python标识符命名规则
类型 规则 例
模块、包名 小写,多单词用下划线隔开 math
函数名 小写,多单词用下划线隔开 phone
类名 驼峰原则 MyPhone
常量名 大写,多单词用下划线隔开 SPEED
变量使用前必须被赋值
可以通过del语句删除不再使用的变量
如果对象没有变量引用,就会被垃圾回收器回收,清空内存空间
链式赋值:用于同一个对象赋值给多个变量
如: x = y = 123
系列解包赋值:系列数据赋值给对应相同个数的变量
a, b, c = 4, 5, 6 相当于 a = 4 b = 5 c = 6
可以使用该操作实现变量对换 :
a, b = 1, 2
a, b = b, a
常量:python没有语法限制改变常量,但逻辑上不能进行修改
python最基本的数据类型:整形,浮点型,布尔型,字符串型
运算符 说明 运算 结果
/ 浮点数除法 8 / 2 4.0
// 整数除法 7 // 2 3
** 幂 2 ** 3 8
使用divmod() 函数同时得到商和余数
divmod(13, 3)
返回一个元组 (4, 1)
python中,除10进制,还有其他三种进制:
0b或0B开头的数字表示为二进制
0o或0O开头的数字表示为八进制
0x或0X开头的数字表示为十六进制
这三种进制可以非常方便地进行位运算
使用int()实现类型转换
1.浮点数直接舍去小数部分
2.布尔值True转变为1,False转变为0
3.字符串符合整数格式直接转换为对应整数
自动转型:整数和浮点数混合运算时,表达式结果自动转化为浮点数
python3可进行超大数计算,适合科学运算
浮点数(float):用a * 10^b 形式的科学计数法表示
round(value)可以返回四舍五入的值,但不会改变原有的值,而是产生新的值
python可以通过time.time()获得当前的时刻
逻辑运算符:
运算符 格式 结果
or x or y x为True,返回True,x为False,返回y
and x and y x为True,返回y,x为False,返回False
not not x x为True,返回False,x为False,返回True
同一运算符(比较两个对象的地址)
is 两个标识符是不是引用同一个对象
is not 判断两个标识符是不是引用不同的对象
==判断变量引用的对象的值是否相等,默认调用对象的__eq__()方法
整数缓存问题:有的变量若代表的值相同,在一定程度上会对同一个对象进行引用
is运算符比==运算符效率高
字符串的本质:字符序列,Python的字符串是不可变的,我们无法对原字符串进行任何修改,但是可以将字符串的一部分复制到新建的字符串,达到看起来修改的效果
python不支持单字符类型,单字符也是作为一个字符串来使用的
python3的字符默认为16位的unicode编码,Ascll码是Unicode编码的子集
使用内置函数ord()可以将字符转换成对应的Unicode码
使用内置函数chr()可以将十进制数字转换为对应的字符
连续三个单引号或双引号可以创建多行字符串
空字符串和len()函数
python允许空字符串存在,不包含任何字符且长度为0
c = ''
len(c)
0
d = 'abc和'
len(d)
4
汉字算一个字符
转义字符:
\(在行尾时) 续行符
\\ 反斜杠符号
\' 单引号
\'' 双引号
\b 退格
\n 换行
\t 横向制表符
\r 回车
字符串拼接
'aa' + 'bb'
'aabb'
'aa' 'bb'
'aabb'
同种类型才能进行+运算
字符串复制
a = 'sxt' * 3
a
'sxtsxtsxt'
print有一个默认参数为换行符
如
print('sxt', end = ' ')
print('sxt', end = '##')
运行结果是(sxt sxt##)
用input()从控制台读取键盘输入的内容
myname = input("请输入你的名字:")
请输入你的名字:tz
myname
'tz'
str()实现数字转型字符串
str(5.20) -> 5.2
str(3.14e2) -> '314.0'
str(True) -> 'True'
当我们调用print()函数时,解释器自动调用了str()将非字符串的对象转成了字符串
使用[]提取字符串
对a = 'abcdefghijklmnopqrstuvwxyz'
a[3] = 'd'
a[-1] = 'z'
a[-30] -> error
replace()实现字符串替换
a[0] = 'h' 是不被允许的
a.replace('c', '高') #a不变
生成一个新对象是将a中的c用高替代得来的
字符串切片操作:
切片slice操作可以让我们快速提取子字符串
标准格式为[起始偏移量 : 终止偏移量 : 步长]
a[::-1]将字符串a逆序输出
切片操作时,偏移量小于最小值默认为最小值,大于最大值时默认为最大值
split()分割和join()合并
split()可以基于指定的分隔符将字符串分割成多个子字符串(存储到列表中),如果不指定分隔符,则默认使用空字符,示例代码如下:
a = 'to be or not to be'
a.split()
['to', 'be', 'or', 'not', 'to', 'be']
a.split('be')
['to', ' or not to ', ' ']
join()将一系列的字符串连接起来
a = ['sxt', 'sxt100', 'sxt200']
'*'.join(a)
'sxt*sxt100*sxt200'
''.join(a)
'sxtsxt100sxt200'
拼接字符串的要点:使用字符串拼接符+会生成新的字符串对象,因此不推荐使用+来拼接字符串,推荐使用join函数,因为join函数在拼接字符串前会计算所有字符串的长度,然后逐一拷贝,仅新建一次对象
字符串驻留机制和字符串比较
对于符合标识符规则的字符串,会启用字符串驻留机制
a = 'abc_33'
b = 'abc_33'
a is b
True
c = 'dd#'
d = ''dd#'
c is d
False
成员运算符
in / not in 关键字,判断某个字符串是否是一个字符串的子字符串
常用的查找方法
方法 说明
len(a) 返回字符串长度
a.startswith('str') 判断是否以'str'开头
a.endswith('str') 判断是否以'str'结尾
a.find('str') 返回第一次出现'str'的位置
a.rfind('str') 返回最后一次出现'str'的位置
a.count('str') 返回指定的字符串出现的次数
a.isalnum() 判断字符串是否只有字符和数字组成
去除首尾信息:
我们可以通过strip()去除字符串首尾指定信息,通过lstrip()去除字符串左边指定信息,rstrip()去除字符串右边指定信息
大小写转化:
a.capitalize() 产生新的字符串,开头字母大写
a.title() 每个单词的首字母都大写
a.upper() 字符全转大写
a.lower() 字符全转小写
a.swapcase() 所有字母大小写转换
格式排版:
center(),ljust(),rjust()这三个函数用于格式排版
a = 'sxt'
a.center(10, '*')
'***sxt****'
a.center(10)
' sxt '
a.ljust(10, '*')
'sxt*******'
其他方法
1.isalnum() 是否只由字母或数字组成
2.isalpha() 是否只由字母和汉字组成
3.isdigit() 是否只由数字组成
4.isspace() 是否只由空白字符组成
5.isupper() 是否只由大写字母组成
6.islower() 是否只由小写字母组成
字符串的格式化:
format()基本方法
格式化字符串函数 str.format()
format()函数可以接受不限个参数,位置可以不按顺序
a = '名字是:{0}, 年龄是:{1}'
a.format('tz', '18')
'名字是:tz, 年龄是18'
a = '名字是:{name}, 年龄是{age}'
a.format(name = 'tz', age = 18)
'名字是:tz, 年龄是18'
填充与对齐:
^、<、>分别是居中,左对齐,右对齐,后面带宽度
:后面带填充的字符,只能为一个字符,不指定默认为空格填充
'{:*>8}'.format('245')
'*****245'
数字格式化:
浮点数通过f,整数通过d进行需要的格式化
a = '我是{0}, 我存款有{1:.2f}'
a.format('tz', 17000.777)
''我是tz, 我的存款有17000.78'
'{:0>2d}'.format(5) -> '05'
'{:,}'.format(1000000) -> '1,000,000'
'{:.2%}'.format(0.25) -> ’25.00%‘
'{:.2e}.format(1000000000)' -> '1.00E+09'
可变字符串对象:
s = 'tznssm' #s为不可变字符串
import io
ss = io.StringIO(s) #ss为可变字符串
ss.seek(4) #指针移至下标为4的位置
ss.write('h')
ss.getvalue() #输出'tznshm'
比较运算符可连用,并且含义与日常操作一致
a = -2
-3 < -2 < -1
True
位操作:
bin():可将数字转成二进制
a = 0b1010
b = 0b1100
bin(a & b) -> '0b1000'
bin(a | b) -> '0b1110'
bin(a ^ b) -> '0b110'
a = 3
a << 2
12
a = 8
a >> 1
a = 4
列表和元组对于同类型的分别可以进行+和*操作
python不支持++和--
运算符优先级问题:
1.乘除优先于加减
2.位运算和算术操作 > 比较运算符 > 赋值运算符 > 逻辑运算符
序列:序列是一种数据存储方式,用来存储一系列的数据,在内存中,序列是一块用来存放多个值的连续空间。序列中存储的是对象的地址,而不是对象的值,常见的序列结构有:字符串,列表,元组,字典,集合
列表:用于存储任意数目,任意类型的数据集合
例:a = [10, 20, 'abc', True]
list.append(x) 将元素x增加到列表表尾
list.extend(alist) 将列表alist所有元素加到list表尾
list.insert(index, x) 在列表index位置插入x
list.remove(x) 在列表中删除首次出现的x
list.pop([index]) 删除并返回指定位置元素,默认为最后一个元素
list.clear() 删除列表所有元素,而非列表对象
list.index(x) 返回x索引位置,无x则抛出异常
list.count(x) 返回x出现的次数
len(list) 返回列表元素个数
list.reverse() 所有元素原地翻转
list.sort() 所有元素原地排序
list.copy() 返回列表对象的浅拷贝
列表大小可变,可以根据需要增大或者缩小
a = [] #创建一个空的列表对象
a = list('tz,hh')
['t', 'z', ',', 'h', 'h']
range()创建整数列表
range([start,]end[,step])
start参数:可选,表示起始数字,默认为0
end参数:必选,表示结尾数字
step参数:可选,表示步长,默认为1
range() 返回的是一个range对象,通过list() 方法将其转化为列表
a = [x * 2 for x in range(5)]
a
[0, 2, 4, 6, 8]
a = [x * 2 for x in range(100) if x % 9 == 0]
a
[0, 18, 36, 54, 72, 90, 108, 126, 144, 162, 180, 198]
我们一般只在列表的尾部添加或者删除元素,如此会大大提高列表的操作效率
del可以删除列表指定位置的元素
a = [100, 200, 888, 300, 400]
del a[2]
a
[100, 200, 300, 400]
index()获得指定元素在列表中首次出现的索引
index(value, [start,[end]])
start和end指定了搜索的范围
列表有和字符串一样的切片操作
列表的遍历
for obj in listobj:
print(obj)
列表的排序
a.sort() #默认为升序排序
a.sort(reverse = True) #降序排序
import random
random.shuffle(a) #打乱顺序
建立新列表的排序
b = sorted(a)
c = sorted(a, reverse = True)
reversed()返回迭代器,不对原列表进行修改,返回一个逆序排列的迭代器对象
a = [20, 10, 30, 40]
c = reversed(a)
list(c)
[40, 30, 10, 20]
list(c)
[]
max和min返回列表中的最大、最小值
sum:对数值型列表进行求和,非数值型列表则报错
二维列表:即一维列表中有元素为列表
元组:元组没有增加元素,修改元素,删除元素的相关方法
元组的创建:
a = (10, 20, 30)
a = 10, 20, 30
如果元组只有一个元素,则必须在后面加逗号
通过tuple()创建元组
tuple()可接受列表,字符串,其他序列类型,迭代器等生成元组,list()类比可得
元组排序只能使用sorted(),生成一个新的列表对象
a = (20, 10, 30, 9, 8)
sorted(a)
[8, 9, 10, 20, 30]
zip(列表1, 列表2,……)将多个列表对应位置的元素组合成一个元组,并返回这个zip对象
a = [10, 20, 30]
b = [40, 50, 60]
c = [70, 80, 90]
d = zip(a, b, c)
list(d)
[(10, 40, 70), (20, 50, 80), (30, 60, 90)]
生成器
s = (x * 2 for x in range(5))
tuple(s)
(0, 2, 4, 6, 8)
s = (x * 2 for x in range(5))
s.__next__()
0
s.__next__()
2
……
元组总结:
1.元组是一个不可变序列
2.访问与处理速度比列表块
3.与整数和字符串一样,元组可作为字典的键,列表不能作为字典中的键
字典
字典的定义:字典是键值对的无序可变序列,字典中的每个元素都是一个键值对,包含键对象和值对象,可以通过键对象实现快速获取,删除,更新对应的值对象。在列表中我们通过下标数字找到对应的对象,字典中通过键对象找到对应的值对象,键是任意的不可变的数据,比如:整数,浮点数,字符串,元组。但是:列表,字典,集合这些可变对象,不能作为键,并且键可以重复(可以类比数学中映射的概念),值可以是任意数据,并且可以重复
字典的定义方式:
1.a = {'name' : 'tz', 'age' : 18, 'job' : 'student'}
2.a = dict(name = 'tz', age = '18', job = 'student')
3.a = dict([('name', 'tz'), ('age', 18)])
4.a = {} #空的字典对象
5.a = dict() #空的字典对象
6.通过zip()创建字典对象
k = ['name', 'age', 'job']
v = ['tz', 18, 'student']
d = dict(zip(k, v))
d
{'name' : 'tz', 'age' : '18', 'job' : 'student'}
7.通过fromkeys创建值为空的字典
a = dict.fromkeys(['name', 'age', 'job'])
a
{'name' : None, 'age' : None, 'job' : None}
字典元素的访问:
假定一个字典对象 a = {'name' : 'tz', 'age' : '18', 'job' : 'student'}
1.通过[键]直接访问获得值,若键不存在则抛出异常
2.同过get()方法获得值,若键不存在返回None,也可以指定键不存在时默认返回的对象,推荐使用get()获取值对象
3..列出所有的键值对:
>>> a.item()
dict_items([('name', 'tz'), ('age', 18), ('job', 'student')])
4.列出所有的键,列出所有的值
>>> a.keys()
dict_keys(['name', 'age', 'job'])
>>> a.values()
dict_values(['tz', 18, 'student'])
5.len() #返回键值对的个数
6.检测一个键是否在字典中
>>> 'name' in a
True
字典元素添加修改删除
1.给字典新增键值对。如果键已经存在,覆盖旧的键值对,键不存在,新增新的键值对。直接a[obj1] = obj2
2.使用updata()方法将新字典中所有键值全部添加到旧字典的对象上,如果key有重复,直接覆盖
3.用del()函数删除字典中的元素,clear()方法删除所有键值对,pop()方法删除指定的键值对并返回相应的值对象
例如del(a['name']), a.pop('age')
4.popitem():随机删除和返回该键值对,字典是无序可变序列,因此没有第一个元素,最后一个元素的概念,popitem()方法在想要一个接一个的移除并处理项时非常有效(因为不用首先获取键列表)
序列解包:序列解包可以用于元组,列表,字典,让我们方便的对多个变量赋值
>>> x, y, z = (20, 30, 10)
>>> x
20
>>> (a, b, c) = (9, 8, 10)
>>> a
9
[a, b, c] = [10, 20, 30]
>>> a
10
序列解包用于字典时,默认是对键进行操作,如果需要对键值对进行操作需要用items(),如果需要对值进行操作,需要用values()
>>> s = {'name' : 'tz', 'age' : 18, 'job' : 'student'}
>>> name, age, job = s #默认对键操作
>>> name
'name'
>>> name, age, job = s.items() #对键值进行操作
>>> name
('name', 'tz')
>>> name, age, job = s.values() #对值进行操作
name
'tz'
表格数据使用字典和列表存储,并实现访问
源代码:
d1 = {'name' : 'gx1', 'age' : 18, 'salary' : 30000, 'city' : 'bejing'}
d2 = {'name' : 'gx2', 'age' : 19, 'salary' : 20000, 'city' : 'shanghai'}
d3 = {'name' : 'gx5', 'age' : 20, 'salary' : 10000, 'city' : 'shenzhen'}
list = [d1, d2, d3]
for i in range(len(list)) :
print(list[i]['name'], list[i]['age'], list[i]['salary'], list[i]['city'])
字典核心底层原理:字典对象的核心是散列表,散列表是一个稀疏数组(总有空白元素的数组),数组的每个单元叫做bucket,每个bucket有两部分:一个是键对象的引用,一个是值对象的引用,由于,所有bucket结构和大小一致,我们可以通过偏移量来读取指定的bucket。我们是通过哈希函数计算键的哈希值从而确定键值对存放在字典中的具体位置的。
字典注意:
1.键必须可散列的:
(1) 数字,字符串,元组,都是可散列的
(2) 自定义对象需要:支持hash()函数,支持通过__eq__()方法检测相等性,若a == b 为真,则hash(a) = hash(b) 也为真
2.字典在内存中开销巨大,典型的空间换时间
3.键查询速度很快
4.往字典里面添加新建可能导致扩容,导致散列表中键的次序变化,因此,不要在遍历字典的同时进行字典的修改
集合:集合是无序可变且元素不能重复的序列。集合底层由字典实现。
集合的创建和删除:
1.使用{}创建集合对象,并使用add()方法添加元素
>>> a = {3, 5, 7}
>>> a
{3, 5, 7}
>>> add(9)
>>> a
{9, 3, 5, 7}
2.使用set(),将列表,元组等可迭代对象转成集合,如果原来的数据存在重复数据,则只保留一个
>>> a = ['a', 'b', 'c', 'b']
>>> b = set(a)
>>> b
{'b', 'a', 'c'}
3.remove()删除指定元素,clear()清空整个集合
>>> a = {10, 20, 30, 40, 50}
>>> a.remove(20)
>>> a
{50, 40, 10, 30}
集合相关操作
>>> a = {1, 3, 'sxt'}
>>> b = {'he', 'it', 'sxt'}
>>> a | b #并集
{1, 3, 'sxt', 'he', 'it'}
>>> a & b #交集
{'sxt'}
>>> a - b #差集
{1, 3}
>>> a.union(b) #并集
>>> a.intersection(b) #交集
>>> a.difference(b) #差集
单分支选择结构
if 条件表达式:
语句块
注意:
1.条件表示式:可以是逻辑表达式,关系表达式,算术表达式等等
2.语句块:可以是一条语句,也可以是多条语句,多条语句缩进必须对齐一致
表达式详解
在选择和循环结构中,条件表示式为False的情况如下:
False,0,0.0,None,空序列对象,空range对象,空迭代对象
其他情况,均为True。Python所有的合法表达式都可以看做条件表达式,甚至包括函数调用的表达式
条件表达式中,不能有赋值操作符=,出现=会报错
双分支选择结构:
if 条件表示是:
语句块1
else:
语句块2
三元条件运算符
条件为真时的值 if 条件表达式 else 条件为假时的值
多分支结构和选择结构的嵌套语法和C++类似
while循环
while循环的语法格式如下:
while 条件表达式:
循环体
可迭代对象
python包含以下几种可迭代对象
1.序列。包含:字符串,列表,元组
2.字典
3.迭代器对象(iterator)
4.生成器函数(generator)
for循环和可迭代对象遍历
for循环通常用于可迭代对象的遍历
for循环的语法格式如下:
for 变量 in 可迭代对象:
循环体语句
break语句:用于while和for循环,用来结束整个循环,当有嵌套循环时,break语句只能跳出最近一层的循环
continue语句:continue语句用于结束本次循环,继续下一次,多个循环嵌套时,continue也是应用于最近的一层循环
else语句:while和for循环可以附带一个else语句(可选),如果for和while语句没有被break语句结束,则会执行else语句,否则不执行。语法格式如下:
while 条件表达式:
循环体
else:
语句块
或者:
for 变量 in 可迭代对象:
循环体
else:
语句块
循环代码优化
虽然计算机越来越快,空间也越来越大,我们仍然要在性能问题上斤斤计较,编写循环时,遵守下面三个原则可以大大提高运行效率,避免不必要的低效计算:
1.尽量循环减少循环内部不必要的计算
2.嵌套循环中,尽量减少内层循环的计算,尽可能往外提
3.局部变量查询较快,尽量使用局部变量
其他优化手段:
1.拼接多个字符串,使用你join()而不使用+
2.列表进行元素插入和删除,尽量在列表尾部操作
使用zip()并行迭代
我们可以通过zip()函数对多个序列进行并行迭代,zip()函数在最短序列用完时就会停止
for name, age, job in zip(names, ages, jobs)
print("{0} {1} {2}".format(name, age, job))
推导式创建序列:推导式是一个或者多个迭代器快速创建序列的一种方法,它可以将循环和条件判断结合,从而避免冗长的代码
字典推导式生成字典对象:
{key_expression : value_expression for 表达式 in 可迭代对象}
类似列表推导式,字典推导式也可以增加if条件判断,多个for循环
集合推导式生成集合对象:
{表达式 for item in 可迭代对象}
{表达式 for item in 可迭代对象 if 条件判断}
生成器推导式(元组无推导式)
一个生成器只能运行一次,第一次迭代可以得ff
到数据,第二次迭代发现数据没有了
b = tuple(x for x in range(5)) #生成一个(0, 1, 2, 3, 4, 5)的元组
用turtle画简易棋盘的代码
import turtle
t = turtle.Pen()
x, y = -300, 300
t.speed(0)
for i in range(19):
t.penup()
t.goto(x, y - 30 * i)
t.pendown()
t.goto(x + 600, y - 30 * i)
for i in range(19):
t.penup()
t.goto(x + 33.4 * i, y)
t.pendown()
t.goto(x + 33.4 * i, y - 540)
turtle.done()
函数的基本概念:
1.一个程序由一个个任务组成,函数代表一个任务或者一个功能
2.函数是代码复用的通用机制
python函数的分类:
1.内置函数:str(),list(),len()等可以直接使用的函数
2.标准库函数:我们可以通过import语句导入库然后使用其中定义的函数
3.第三方库函数:python社区提供了很多高质量的库,下载安装后,通过import语句导入后可以使用这些第三方库的函数
4.用户自定义函数:用户自己定义的函数
函数的定义和调用
def 函数名([参数列表]):
'''文档字符串'''
函数体
我们使用def来定义函数,创建一个函数对象,并绑定到函数名变量上
通过
函数名([参数列表])
的形式可以进行函数的调用
形参和实参的使用和C++的区别为Python不需要说明参数类型
文档字符串用于说明函数的作用
返回值:要返回多个返回值,使用列表,元组,字典,集合将多个值存起来
函数也是对象
def test01()
print('hh')
test01()
c = test01
c() #效果和test01()是一样的
变量的作用域:当我们调用一个函数时,会在栈区调用一个栈帧,在这个栈帧中生成局部变量,当函数执行完毕之后,栈帧的内存空间被释放
如果要在函数体内使用全局变量,要先用global关键字进行声明
print(local()) #输出当前所有的局部变量
print(globals()) #输出当前所有的全局变量
参数的传递:
函数的参数传递的本质上就是:从实参到形参的赋值操作,Python中一切皆对象,所有的赋值操作都是引用的赋值,所以,Python中参数的传递都是引用传递,不是值传递,具体操作分为两类:
1.对可变对象进行写操作,直接作用于原对象本身
2.对不可变对象进行写操作,会产生一个新的对象空间,并用新的值填充这块空间(起到其他语言的值传递效果,但不是值传递)
可变对象有:字典,列表,集合,自定义的对象等
不可变对象有:数字,字符串,元组,function等 #当我们传入一个不可变对象时,对这个不可变对象进行重定义时会生成一个新对象,变量引用这个新对象的地址
浅拷贝:不会拷贝子对象的内容,只是拷贝子对象的引用,对子对象的修改如果和源对象相关的话会修改源对象
深拷贝:会连子对象的内容也全部拷贝一份,对子对象的修改不会影响源对象
元组对象是不可变的,但元组对象内若某个元素为可变对象,则可以发生改变,即元组对象中元素的地址是不可变的
参数的几种类型
位置参数:函数调用时,实参默认按位置顺序传递,需要个数和形参匹配
默认值参数:我们可以为某些参数设置默认值,这样这些参数在传递时就是可选的,默认值参数放到位置参数的后面
命名参数:我们可以按照形参的名称传递参数
可变参数:*变量名,将多个参数收集到一个元组对象中,**变量名,将多个参数收集到一个字典对象中
强制命名参数:在带星号的可变参数后面增加新的参数,必须是强制命名参数
lambda表达式的使用
f = lambda a, b, c : a + b + c
f(2, 3, 4)
g = [lambda a : a * 2, lambda b : b * 3, lambda c : c * 4]
print(g[0](6), g[1][7], g[2](8))
eval()函数
功能:将字符串str当成有效的表达式来求值并返回计算结果
语法:eval(source[, globals[, locals]]) ——>value
参数:source:一个Python表达式或函数compile()返回的代码对象
globals:可选,必须是dictionary
locals:可选,任意映射对象
递归函数:自己调用自己,在函数体内部直接或简介自己调用自己。每个函数必须包括:
1.终止条件:表示递归什么时候结束,一般用于返回值,不再调用自己
2.递归步骤:把第n步的值和第n-1步相关联
递归函数由于创建大量的函数对象,过量消耗内存和运算能力,在处理大量数据时,应谨慎使用
递归是栈的结构,在类似于
代码块1
f(n - 1)
代码块2
的结构中,先执行代码块1,然后递归调用,最后由于栈的结构,后进先出地调用代码块2
嵌套函数:函数内部定义一个函数,仅在这个函数内部调用的函数(这一点C++不允许内部定义函数),那么什么时候使用嵌套函数呢:
1.封装-数据隐藏:外部无法访问嵌套函数
2.贯彻DRY原则:嵌套函数可以让我们在函数内部避免重复带代码
3.闭包
嵌套函数的一个实例:
def printName(isChinese, name, familyName): #判断是否为中国人,中国人先打印姓
def inner_print(a, b):
print("{0} {1}".format(a, b))
if isChinese:
inner_print(familyName, name)
else
inner_print(name, familyName)
nonlocal关键字
nonlocal 用来声明外层的局部变量
LEGB规则
python在查找名称时,是按照LEGB规则查找的:Local - Enclosed - Global - Built in
Local 指的就是函数或者类的方法内部
Enclosed 指的是嵌套函数
Global 指的是模块中的全局变量
Built in 指的是python为自己保留的特殊名称