75.字符串的创建与驻留机制
字符串
- 在Python中字符串是基本数据类型,是一个不可变的字符序列
- 什么叫字符串驻留机制呢?
- 仅保存一份相同且不可变字符串的方法,不同的值被存放在字符串的驻留池中,Python的驻留机制对相同的字符串只保留一份拷贝,后续创建相同字符串时,不会开辟新空间,而是把该字符串的地址赋给新创建的变量
#实例
a='Python'
b="Python"
c='''Python'''
print(a,id(a)) #输出变量a,查看id地址
print(b,id(b))
print(c,id(c))
驻留机制的几种情况(交互模式)
- 字符串的长度为0或1时
- 符合标识符的字符串
- 字符串只在编译时进行驻留,而非运行时
- [-5,256]之间的整数数字
sys中的intern方法强制2个字符串指向同一个对象
- PyCharm对字符串进行了优化处理
打开Python交互式进行测试
- 字符串的长度为0或1时
符合标识符的字符串
- 下面这个就是符合标识符的字符串了,可以看到id内存地址均为3424
- 下面这个就是符合标识符的字符串了,可以看到id内存地址均为3424
字符串只在编译时进行驻留,而非运行时
- python是一种解释型语言,但实际上它的解释器也可以理解成编译器,它负责将python代码编译成字节码,也就是.pyc文件,
[-5,256]之间的整数数字
字符串驻留机制的优缺点
- 当需要值相同的字符串时,可以直接从字符串池里拿来使用,避免频繁的创建和销毁,提升效率和节约内存,因此拼接字符串和修改字符串是会比较影响性能的。
在需要进行字符串拼接时建议使用str类型的join方法,而非+,因为join()方法是先计算出所有字符中的长度,然后再拷贝,只new一次对象,效率要比"+"效率高
76.字符串的常用操作_字符串的查询操作
- 可以把字符串看成是字符的列表,所以字符串与列表查的操作是非常相似的,但区别就在于,当获得字符串中指定的索引时,除了有Index外,还有rindex、find以及rfind方法,
#实例
s='hello,hello'
print(s.index('lo')) #运行结果3
print(s.find('lo')) #运行结果3
print(s.rindex('lo')) #运行结果9
print(s.rfind('lo')) #运行结果9
#实例
#print(s.index('k')) #运行结果为ValueError: substring not found 译文:子串没找到
print(s.find('k')) #运行结果为-1 -->-->查找最后一次出现的位置,不存在返回-1;建议用不抛异常这种方法
#print(s.rindex('k')) #运行结果为SyntaxError: unexpected EOF while parsing 译文:解析时出现意外
print(s.rfind('k')) #运行结果为-1 -->查找最后一次出现的位置,不存在返回-1
77.字符串的常用操作_字符串的大小写转换操作方法
#实例
print('---字符串中的大小写转换的方法---')
s='hello,python'
a=s.upper() #转大写后会产生一个新的字符串对象(通俗讲就是会添加一个内存空间,内存地址会变)
print(a,id(a)) #转换后;运行结果为HELLO,PYTHON 2969352950256
print(s,id(s)) #转换前;运行结果为hello,python 2969352985584
b=s.lower() #转换后会产生一个新的字符串对象
print(b,id(b)) #运行结果为hello,python 1939784160688
print(s,id(s)) #运行结果为hello,python 1939783867376
print(b==s) #内容相同
print(b is a) #运行结果为false,也就是说内容是相同的,内存地址不同,没有字符串驻留机制
#print(s.lower(),id(s.lower()))
#print(s,id(s))
s2='hello,Python'
print(s2.swapcase()) #运行结果为HELLO,pYTHON -->小写转大写,大写转小写
print(s2.title()) #运行结果为Hello,Python -->每个单词首字母都转大写,其它都转小写
78.字符串的常用操作_字符串内容对齐操作的方法
#实例(很像文档中的左对齐、居中对齐、右对齐)
s='hello.Python' #声明一个变量
print('---居中对齐.center()---')
print(s.center(20,'*')) #运行结果为****hello.Python**** -->设置s变量的字符串为居中20个字符,hello,Python为12个字符,20-12=8因此指定星号*为两侧填充内容
print('---左对齐.ljust()---')
print(s.ljust(20,'*')) #
print(s.ljust(10)) #运行结果为hello.Python -->设置参数小于字符串字符长度且不指定第二个参数,将返回原字符
print(s.ljust(20)) #运行结果为hello.Python -->不指定第二个参数,输出结果后面是相应的空格
print('---右对齐.rjust()---')
print(s.rjust(20,'*')) #运行结果为********hello.Python
print(s.rjust(20)) #运行结果为 hello.Python
print(s.rjust(10)) #运行结果为hello.Python
print('---右对齐.zfill() 使用0进行填充---')
print(s.zfill(20))
print(s.zfill(10))
print('-8910'.zfill(8))
#运行结果
---居中对齐.center()---
****hello.Python****
---左对齐.ljust()---
hello.Python********
hello.Python
hello.Python
---右对齐.rjust()---
********hello.Python
hello.Python
hello.Python
---右对齐.zjust() 使用0进行填充---
00000000hello.Python
hello.Python
-0008910
79.字符串的常用操作_字符串的劈分
#实例
print('---split()--从字符串的左边开始劈分,默认的劈分字符是空格字符串,返回的值都是一个列表---')
s='hello world Python'
lst=s.split()
print(lst)
print('---split()--通过参数sep指定劈分字符串是的劈分符---')
s1='hello|world|Python'
print(s1.split(sep='|'))
print('---split()--通过参数maxsplit指定劈分字符串时的最大劈分次数,在经过最大次劈分之后,剩余的子串会单独做为一部分---')
print(s1.split(sep='|',maxsplit=1))
print('---rsplit()--从字符串的右边开始劈分,默认的劈分字符是空格字符串,返回的值都是一个列表---')
print(s.rsplit())
print('---rsplit()--以通过参数sep指定劈分字符串是的劈分符---')
print(s1.rsplit('|')) #可以指定分隔符
print('---rsplit()--通过参数maxsplit指定劈分字符串时的最大劈分次数,在经过最大次劈分之后,剩余的子串会单独做为一部分---')
print(s1.rsplit(sep='|',maxsplit=1)) #从右边指定分割次数为1
#运行结果
---split()--从字符串的左边开始劈分,默认的劈分字符是空格字符串,返回的值都是一个列表---
['hello', 'world', 'Python']
---split()--通过参数sep指定劈分字符串是的劈分符---
['hello', 'world', 'Python']
---split()--通过参数maxsplit指定劈分字符串时的最大劈分次数,在经过最大次劈分之后,剩余的子串会单独做为一部分---
['hello', 'world|Python']
---rsplit()--从字符串的右边开始劈分,默认的劈分字符是空格字符串,返回的值都是一个列表---
['hello', 'world', 'Python']
---rsplit()--以通过参数sep指定劈分字符串是的劈分符---
['hello', 'world', 'Python']
---rsplit()--通过参数maxsplit指定劈分字符串时的最大劈分次数,在经过最大次劈分之后,剩余的子串会单独做为一部分---
['hello|world', 'Python']
80.字符串的常用操作_字符串判断的相关方法
#字符串遍历补充
print('---直接遍历---')
source='appke,tiger,banana'
for sh in source:
print(sh)
print('---下标遍历---')
for index,sh in enumerate(source):
print(index,end='')
print(sh)
print('---range遍历---')
for index in range(len(source)):
print(index)
print('---迭代器---')
for sh in iter(source):
print(sh)
#实例
'''判断指定的字符串是不是合法的标识符'''
s='hello,python'
print('1',s.isidentifier()) #运行结果为false
print('2','hello'.isidentifier()) #运行结果为true
print('3','张三_'.isidentifier()) #运行结果为true
print('4','张三_123'.isidentifier()) #运行结果为true
'''判断指定的字符串是否全部由空白字符组成(回车、换行,水平制表符)'''
print('5','\t'.isspace()) #运行结果为true
'''判断指定的字符串是否全部由字母组成'''
print('6','abc'.isalpha()) #运行结果true
print('7','张三'.isalpha()) #运行结果为true
print('8','张三1'.isalpha()) #运行结果为false
'''判断指定字符串是否全部由十进制的数字组成'''
print('9','123'.isdecimal()) #运行结果为true
print('10','123四'.isdecimal()) #运行结果为false
print('11','ⅡⅡⅡ'.isdecimal()) #运行结果为false
'''判断指定的字符串是否全部由数字组成'''
print('12','123'.isnumeric()) #运行结果为true
print('13','123四'.isnumeric()) #运行结果为true
print('14','ⅡⅡⅡ'.isnumeric()) #运行结果为true -->验证罗马数字也是数字
'''判断指定字符串是否全部由字母和数字组成'''
print('15','abc1'.isalnum()) #运行结果为true
print('16','张三123'.isalnum()) #运行结果为true
print('17','abc!'.isalnum()) #运行结果为false
81.字符串的常用操作_替换与合并
#实例
print('---.replace()字符串替换__两个参数---')
s='hello,Python'
print(s.replace('Python','Java'))
print('---.replace()字符串替换__三个参数---')
s1='hello,Python,Python,Python'
print(s1.replace('Python','Java',2))
print('---.join()字符串合并---')
lst=['hello','java','Python']
print('|'.join(lst))
print(''.join(lst)) #为空会把三个单词连在一起组成新字符串
print('*'.join('Python')) #会把Python当作字符串序列进行连接
#运行结果
---.replace()字符串替换__两个参数---
hello,Java
---.replace()字符串替换__三个参数---
hello,Java,Java,Python
---.join()字符串合并---
hello|java|Python
hellojavaPython
P*y*t*h*o*n
82.字符串的比较操作
字符串的比较操作
- 运算符:>,>=,<,<=,==,!=
- 比较规则:首先比较两个字符串中的第一个字符,如果相等则继续比较下一个字符,依次比较下去,直到两个字符串中的字符不相等时,其比较结果就是两个字符串的比较结果,两个字符串中的所有后续字符将不再被比较
- 比较原理:两上字符进行比较时,比较的是其ordinal value(原始值),调用内置函数ord可以得到指定字符的ordinal value。与内置函数ord对应的是内置函数chr,调用内置函数chr时指定ordinal value可以得到其对应的字符
#实例
print('apple'>'app') #true
print('apple'>'banana') #false -->相当于97>98吗?当然不大于所以为false
print(ord('a'),ord('b'))
print(ord('杨')) #26472 -->看下的原始值是多少
print(chr(97),chr(98)) #a b -->能输出a和b说明它们互为相反的操作
print(chr(26472)) #杨 -->26472原始值会得到对应字符码?输出结果为杨,答案是会
'''==与is的区别 ==比较的是value值 is比较的是id内存是否相等'''
a=b='Python'
c='Python'
print(a==b) #True
print(a==c) #True
print(a is b) #True
print(a is c) #True
print(id(a)) #3004608322480
print(id(b)) #3004608322480
print(id(c)) #3004608322480 -->abc内存都一直的原因是,字符串常量内存驻留机制,有相同的内容会指向同一个id内存空间
83.字符串的切片操作
字符串是不可变类型
- 不具备增、删、改等操作
- 切片操作将产生新的对象
#s[:5] -->不指定起始位置切到索引为5的位置实际切到4
#s[6:] -->不指定结束位置从索引为6的位置一直切到最后,而切出的字符串将从0重新开始表示
#s1+!+s2 --> +号是连接符,因此s1+!+s2几十将hello加上!加上Python组成新字符串,而索引从0重新开始标识
#实例
s='hello,Python'
s1=s[:5] #由于没有指定起始位置,所以从0开始切到索引为4的元素
s2=s[6:] #由于没有指定结束位置,所以切到字符串最后一个元素
s3='!' #将叹号赋值给s3
new_str=s1+s3+s2 #将切出来的两个字符串s1和s2与s3叹号通过连接符+连接,赋值给new_str
print(s1)
print(s2)
print(new_str)
print('---验证id内存地址是否相同---')
print(id(s))
print(id(s1))
print(id(s2))
print(id(s3))
print(id(new_str)) #答案是不相同的,由此可见每一次切出来的都是一个新的字符串
print('---切片[start:end:step] 完整的写法---')
print(s[1:5:1]) #从1开始截到5(不包含5),步长为1
print(s[::2]) #默认从0开始,没有写结束,默认到字符串最后一个元素,步长为2,两个元素之间的索引间隔为2
print(s[::-1]) #默认从字符串的最后一个元素开始,到字符串的第一个元素结束,因为步长为负数
print(s[-6::1]) #从索引为-6开始,到字符串最后一个元素结束,步长为1
#运行结果
hello
Python
hello!Python
---验证id内存地址是否相同---
3091268033584
3091270854256
3091270918576
3091263557744
3091270920432
---切片[start:end:step] 完整的写法---
ello
hloPto
nohtyP,olleh
84.格式化字符串
解析:字符串的拼接操作会产生很多新的字符串会造成空间的浪费,所以这时候就需要使用格式化字符串就可以了(按一定格式输出的字符串)。
#我的名字叫:{0},今年{1}岁了,我真的叫:{0}'.format(name,age)解析
#所有format(name)都会用0去替换
#实例
'''格式化字符串常用基本用法'''
print('---格式化字符串一:%作占位符---')
name='某酷'
age=20
print('我叫%s,今年%d岁' % (name,age)) #固定符号百分号 name和age是一个元组(此时name就会添加到%s位置,age就会添加到%d位置)
print('---格式化字符串二:{}作占位符---')
print('我叫{0},今年{1}岁'.format(name,age))
print('---格式化字符串三:f-string---')
print(f'我叫{name},今年{age}岁') #这种写法前面加个f就代表”格式化字符串“
#除了这三种,还有一些表示宽度和精度怎么使用
print('---表示宽度d---')
print('%d' % 99)
print('%10d' % 99) #在%d中间加上值,表示宽度,10个宽度就代表10个字符的宽度
print('hellohello')
print('---表示精度f---')
print('%f' % 3.1415926)
print('%.3f' % 3.1415926) #如想保留三位小数,在%f中间加上.3即可
print('---同时表示宽度和精度---')
print('%10.3f' % 3.1415926) #一共总宽度为10字符,小数点后三位;在%f中间加上10.3即可
print('---不使用%,使用{}也可以实现---')
print('{0}'.format(3.1415926)) #花括号{}内索引不写也可以,但建议在花括号{}多的情况下要写一下
print('---不使用%,使用{}也实现精度控制---')
print('{0:.3}'.format(3.1415926)) # .3表示的是一共3位数,如果想表示小数要在后面加f
print('{0:.3f}'.format(3.1415926)) #冒号:前面的0代表的是占位符的顺序,也就是format()内的第几个,与索引类似
print('---不使用%,使用{}同时实现宽度和精度的控制---')
print('{0:10.3f}'.format(3.1415926)) #占位符0,宽度10个字符,保留后三位小数
#运行结果
---格式化字符串一:%作占位符---
我叫某酷,今年20岁
---格式化字符串二:{}作占位符---
我叫某酷,今年20岁
---格式化字符串三:f-string---
我叫某酷,今年20岁
---表示宽度d---
99
99
hellohello
---表示精度f---
3.141593
3.142
---同时表示宽度和精度---
3.142
---不使用%,使用{}也可以实现---
3.1415926
---不使用%,使用{}也可以实现---
3.14
3.142
85.字符串的编码与解码
编码与解码的万式
- 编码:将字符串转换为二进制数据(bytes)
- 解码:将bytes类型的数据转换成字符串类型
- 解析:例如将A计算机数据传到B计算机中,需要使用字节进行传输,这时候就需要将str字符串转换成二进制数据传送到B计算机,尔后B计算机再将二进制数据转换成字符串显示。
#实例
s='夏天的风'
print('---编码---')
print(s.encode(encoding='GBK')) #在GBK这种编码格式中,一个英文占两个字节(输出结果前面的b'表示bits类型二进制),夏天的风4个字符8个字节
print(s.encode(encoding='utf-8')) #在UTF-8这种编码格式中,一个中文占三个字节
print('---解码---')
#byte代表一个二进制数据(字节类型的数据),注意:编码和解码的格式要相同。
byte=s.encode(encoding='GBK') #编码
print(byte.decode(encoding='GBK')) #解码
byte=s.encode(encoding='UTF-8') #编码
print(byte.decode(encoding='UTF-8')) #解码
#运行结果
---编码---
b'\xcf\xc4\xcc\xec\xb5\xc4\xb7\xe7'
b'\xe5\xa4\x8f\xe5\xa4\xa9\xe7\x9a\x84\xe9\xa3\x8e'
---解码---
夏天的风
夏天的风
86.函数的定义与调用
内容导学:1、函数的创建和调用;2、函数的参数传递;3、函数的返回值;4、函数的参数定义;5、变量的作用域;6、递归函数
函数的创建和调用
- 什么是函数
- 函数就是执行特定任和以完成特定功能的一段代码
为什么需要函数
- 复用代码
- 隐藏实现细节
- 提高可维护性
- 提高可读性便于调试
- 函数的创建
解析: 输出的print函数,输入的input函数,以及可以获取对象类型的type函数,获取对象标识的id函数等等,这些都叫做函数,而这些函数是执行特定任务,每个函数都有自己的独立功能,完成特定功能的一段代码。使用函数可以实现代码的复用。在python中函数的定义使用def,函数的名字是自己起的,但需要遵守函数名的命名规则(字母数字下划线)。
#解析
def calc(a,b): #calc是函数名,a和b是是输入参数起到占位符的作用
c=a+b #a和b的和存到了c当中
return c #结束这个函数同时把a+b的结果给调用数
#实例
#语句执行流程:1.calc函数名,a和b是占位符;2.a+b结果赋给c;3.结束函数同时将结果提交给调用数;4.函数名为calc的两个a和b占位符分别值为10和20,赋值给result(结合上面函数a+b故等于30);5.print输出result
'''函数创建'''
def calc(a,b): #a和b占了两个变量的位置;称为形式参数,简称形参,形参的位置是在含义的定义处
c=a+b
return c #结束这个函数,同时将结果提交调用数
'''函数调用__位置实参'''
result=calc(10,20) #10,20称为实际参数的值,简称实参,实参的位置是函数的调用处
print(result) #运行结果为30
'''关键字实参'''
res=calc(b=10,a=20) #赋值名称相同的形参占位符
print(res) #运行结果为30,虽然结果是一样的,但传递的方式不一样,会根据等号=左侧的名字传;另外等号=左侧变量的名称称为“关键字参数”
88.函数参数传递的内存分析
提示:形式参数和实际参数名称可以不相同
#实例
'''函数定义'''
def fun(arg1,arg2): #定义函数def,函数名fun,arg1作为第一个形参,arg2作为第2个形参
print('arg1',arg1) #输出arg1的值
print('arg2',arg2) #输出arg2的值
arg1=100 #arg1值更改为100
arg2.append(10) #arg2追加了一个10
print('arg1',arg1) #再次输出arg1的值
print('arg2',arg2) #再次输出arg2的值
#因为上述语句函数的执行,没有携带任何结果,所以这里return可以不写,也就是不需要把结果给调用数(如果要写直接return即可)
#return
'''函数调用'''
n1=11
n2=[22,33,44]
print('n1',n1)
print('n2',n2)
fun(n1,n2) #将位置传参,arg1,arg2是函数定义出的形参,n1,n2是函数调用处的实参(实参名称与形参名称可以不一致)
print('n1',n1)
print('n2',n2)
'''总结:在函数调用过程中,进行参数的传递
如果是不可变对象,在函数体的修改不会影响实参的值(例如本案例中对arg1进行修改为100,但最后还是以11输出,因其是不可变对象)
如果是可变对象,在函数体的修改会影响到实参的值(例如本案例中向arg2追加append了一个10,因列表是可变对象)
#运行结果
n1 11
n2 [22, 33, 44]
arg1 11
arg2 [22, 33, 44]
arg1 100
arg2 [22, 33, 44, 10]
n1 11
n2 [22, 33, 44, 10]
89.函数的返回值
#实例
print('---布尔复习---')
print(bool(0)) #false #4/2=2余0,为0是false
print(bool(8)) #true #3/2=1余1,1不为0是true
def fun(num): #函数定义,函数名为fun,传入一个形参num
odd=[] #存奇数
even=[] #存偶数
for i in num: #使用for去遍历num列表
if i%2: #如果i与2的布尔值为true(布尔值为true说明是一个奇数)
odd.append(i) #奇数的列表append追加
else: #否则
even.append(i) #偶数的列表append追加
return odd,even #函数结束时将奇数odd,偶数even的列表返回
'''函数调用'''
lst=[10,29,34,23,44,53,55]
print(fun(lst))
'''函数的返回值
(1)如果函数没有返回值(函数执行完毕后,不需要给调用处提供数据) return可以省略不写
(2)函数的返回值,如果是1个,直接返回类型
(3)函数的返回值,如果是多个,返回的结果为元组
'''
print('---第一种情况---')
def fun1():
print('hello')
# return #此处return可以省略不写,因为没有可返回的值(并且已经print输出,没必要再返回)
fun1()
print('---第二种情况---')
def fun2():
return 'hello'
'''函数调用'''
res=fun2()
print(res)
print('---第三种情况---')
def fun3():
return 'hello','world'
print(fun3()) #运行结果为('hello', 'world') -->将两个返回值放到了一个元组中(由此得出结论,在写函数的时候到底要不要return需要视情况而定)
#运行结果
---布尔复习---
False
True
([29, 23, 53, 55], [10, 34, 44])
---第一种情况---
hello
---第二种情况---
hello
---第三种情况---
('hello', 'world')
90.函数参数定义默认值参数
- 函数定义默认值参数
- 函数定义时,给形参设置默认值,只有与默认值不符的时候才需要传递实参
#实例
def fun(a,b=10): #b称为默认值参数
print(a,b)
'''函数调用'''
fun(100) #实参100会传参给a
fun(20,30) #实参20传参给b,实参30传参并替换b形参
print('---单击print跳到源码定义处,过去是\\n换行,现在定义为\\t制表符使其一行输出---')
print('hello',end='\t')
print('world')
#运行结果
100 10
20 30
---单击print跳到源码定义处,过去是\n换行,现在定义为\t制表符使其一行输出---
hello world
91.函数参数定义个数可变的位置形参_个数可变的关键字形参
函数的参数定义
- 个数可变的位置参数
- 定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的位置参数
- 使用*定义个数可变的位置形参
- 结果为一个元组
个数可变的关键字形参
- 定义函数时,无法事先确定传递的关键字实参的个数时,使用可变的关键字形参
- 使用**定义个数可变的关键字形参
- 结果为一个字典
#实例
print('---*个数可变的位置形参---')
'''函数定义'''
def fun(*args): #定义函数,函数名为fun
print(args)
# print(args[0])
'''函数调用'''
fun(10)
fun(10,30)
fun(30,130,50)
print('---**个数可变的关键字形参---')
'''函数定义'''
def fun1(**args):
print(args)
'''函数调用'''
fun1(a=10)
fun1(a=20,b=30,c=30)
print('hello','world','Python') #按住ctrl单击print进入函数定义查看,可以看到的是*args位置可变参数,所以写一个两个三个都没问题
'''测试:在定义个数可变的位置形参和关键字形参可以定义几个呢?'''
'''def fun1(*args,*a): #两个可变“位置形参”测试
pass
以上代码程序会报错,可变的位置参数,只能是一个
'''
'''def fun2(**args,**args): #两个可变“关键字形参”测试
pass
以上代码也报错,可变的关键字参数,也只能是一个
'''
def fun2(*args1,**args2):
pass
'''def fun3(**args1,*arg2):
pass
在一个函数的定义过程中,既有个数可变的关键字形参,也有个数可变的位置形参,要求个数可变的位置形参,放在个数可变的关键字形参之前
'''
#运行结果
---*个数可变的位置形参---
(10,)
(10, 30)
(30, 130, 50)
---**个数可变的关键字形参---
{'a': 10}
{'a': 20, 'b': 30, 'c': 30}
hello world Python
92.函数的参数总结
#实例
print('---使用**将字典中的每个键值对都转换为关键字实参---')
'''函数定义__形参'''
def fun(a,b,c): #a,b,c在函数的定义处,所以是形式参数
print('a=',a) #分别输出abc的值
print('b=',b)
print('c=',c)
'''函数调用__实参'''
fun(10,20,30) #函数调用时的参数传递,称为位置传参(因为它会把10赋给a,20赋给b,30赋给c)
print('---将列表中的元素作为实参,尔后加*位置传参---')
lst=[11,22,33]
'''函数调用'''
fun(*lst) #在函数调用时,将列表中的每个元素都转换为位置实参传入
print('---关键字实参的函数调用---')
fun(a=100,c=300,b=200) #使用关键字实参函数调用,它就不会像位置传参一样逐个传,而是通过实参关键字与形参占位名匹配继而完成赋值
print('---关键字实参的函数调用__字典---')
dic={'a':111,'b':222,'c':333}
'''函数调用'''
fun(**dic) #因为字典是一个参数,如果向进行关键字传参,想将字典中每个关键字都转为关键字实参传入加两个星**
print('-----------------------------------')
'''函数定义__复习案例'''
def fun(a,b=10): #b是在函数的定义处,所以b是形参,而且进行了赋值,所以b称为默认值形参
print('a=',a) #分别输出ab的值
print('b=',b)
def fun2(*args): #这是个数可变的”位置形参”
print(args)
def fun3(**args2): #这是个数可变的”关键字形参“
print(args2)
'''函数调用__复习案例'''
fun2(10,20,30,40) #它的结果是元组;反正是个数可变的,传多少都可以
fun3(a=11,b=22,c=33,d=44,e=55) #它的结果是字典(键值对的形式);
print('---关键字形参---')
'''函数定义'''
def fun4(a,b,*,c,d): #从*之后的参数,在函数调用时,只能采用关键字参数传递
print('a=',a) #分别输出abcd的值
print('b=',b)
print('c=',c)
print('d=',d)
'''函数调用'''
#fun4(10,20,30,40) #位置实参传递(此处注释掉,因为fun4定义了从*之后的cd只能采用关键字参数传递
fun4(a=10,b=20,c=30,d=40) #关键字实参传递
fun4(10,20,c=30,d=40) #前两个参数采用的是“位置实参传递”,而c,d采用的是“关键字实参传递“
print('---函数定义时的顺序形参问题---')
def fun5(a,b,*,c,d,**args): #此处定义*后的cd只能按照”关键字实参传递“(后面又加了**,这种加了个数可变”关键字形参“是可以的)
pass
def fun6(*args,**args2): #个数可变的关键字形参也是可以的
pass
def fun7(a,b=10,*args,**args2): #b”默认值形参“,个数可变的”位置形参“,个数可变的”关键字形参“,这几种组合都是可以的
pass
#运行结果
---使用**将字典中的每个键值对都转换为关键字实参---
a= 10
b= 20
c= 30
---将列表中的元素作为实参,尔后加*位置传参---
a= 11
b= 22
c= 33
---关键字实参的函数调用---
a= 100
b= 200
c= 300
---关键字实参的函数调用__字典---
a= 111
b= 222
c= 333
-----------------------------------
(10, 20, 30, 40)
{'a': 11, 'b': 22, 'c': 33, 'd': 44, 'e': 55}
---关键字形参---
a= 10
b= 20
c= 30
d= 40
a= 10
b= 20
c= 30
d= 40
---函数定义时的顺序形参问题---
93.变量的作用域
变量的作用域
- 程序代码能访问该变量的区域
根据变量的有效范围可分为
局部变量
- 在函数内定义并使用的变量,只在函数内部有效,局部变量使用global声明,这个变量就会就成全局变量
全局变量
- 函数体外定义的变量,可作用于函数内外
#实例
print('---局部变量---')
'''函数定义'''
def fun(a,b):
c=a+b #c就称为局部变量,因为c是函数体内进行定义的变量,a,b为函数的形参,作用范围也是函数内部,相当于局部变量
#print(c) #因为a,c超出了起作用的范围(超出了作用域)
#print(a)
print('----------------------------')
name='杨老师' #name的作用范围为函数内部和外部都可以使用,就称为全局变量
print(name)
'''函数定义'''
def fun2():
print(name)
'''函数调用'''
fun2()
print('---使用“global声明”,让局部变量变成全局变量-----')
'''函数定义'''
def fun3():
global age #函数内部定义的变量是局部变量,局部变量使用global声明,这个变量实际上就变成了全局变量
age=20
print(age)
'''函数调用'''
fun3()
print(age)
#运行结果
---局部变量---
----------------------------
杨老师
杨老师
---使用“global声明”,让局部变量变成全局变量-----
20
20
94.递归函数
- 什么是递归函数
- 如果在一个函数的函数体内调用了该函数本身,这个函数就称为递归函数
- 递归的组成部分
- 递归调用与递归终止条件
- 递归的调用过程
- 每递归调用一次函数,都会在栈内存分配一个栈帧,每执行完一次函数,都会释放相应的空间
递归的优缺点
- 缺点:占用内存多,效率低下
- 优点:思路和代码简单
- 什么叫阶乘:6的阶乘等于65432*1=720
#实例
'''函数定义'''
def fac(n): #定义函数,函数名为fac,n是要去计算阶乘的数
if n==1: #如果n等于1
return 1 #直接return结束(如果不等于1自己调自己)
else:
return n*fac(n-1) #6*fac 5
print(fac(6))
#运行结果
720
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。