python 从0-1笔记
学习python之前的了解的几个基本概念
1、表达式:一般仅仅用于一些计算结果。10+5 8-4
2、语句:在程序中语句一般需要完成某种功能。比如打印信息 print() ,获取信息 input(),变量赋值 a = 10 。
3、程序(program):由一条一条的语句和表达式构成。
4、函数(function):是一种语句,函数专门用来完成特定的功能 xxx()
函数的分类:
内置函数
由python解释器提供的函数,可以在python中直接使用
自定义函数
自主创建的函数
函数的作用:当我们需要完成某个功能时,就可以去调用内置函数,或者自定义函数
函数的两个要素:
参数:()中的内容就是函数的参数
返回值:函数返回的结果 max(4,5,6) 返回值是6 ,不是所有的函数都有返回值
语法:
python中严格区分大小写;
每一行就是一条语句
每一行语句的长度不要过长,一条语句可以分行书写以 \ 结尾 然后换行书写
变量:可以用来保存字面量(字面的值),变量中保存的字面量是不定的,它会根据不同的字面量表示不同的意思。
变量和标识符
数据类型
变量的值的类型,也就是变量赋的哪些值,整数、浮点数、复数。
所有的整数类型都是int类型,如果数字的长度过大,可以使用下划线作为分隔符 c = 123_456_210
十进制的数字不能以0开头。
可以通过运算符对数字进行运算,并且可以保证整数运算的精确
浮点数:所有的小数都是浮点数类型(float)
对浮点数进行运算时可能会得到一个不精确的结果
c = 0.1 + 0.2
print(c) #0.30000000000000004
保留1位小数
print('c = %.1f '%c) # c = 0.3
字符串:
用来表示一段文本信息,字符串需要用引号引起来。
相同的引号之间不能嵌套,应该这样写
s = '子曰:“温故而知新可以为师傅" '
单引号和双引号不能跨行使用,如果要跨行需要这样写,使用三重引号来表示长字符,并且保留字符串的格式
s=‘’‘锄禾日当午,
汗滴禾下土,
谁知盘中餐,
粒粒皆辛苦。’‘’
print(s)
转义字符
可以使用 \ 作为转义字符,通过转义字符可以在字符串中使用特殊的内容
s = "子曰:“温故而知新可以为师傅\""
print(s) # 子曰:“温故而知新可以为师傅"
\t 表示制表符 s = "子曰:“温故而知新,\t可以为师傅\""
\n 表示换行符 s = "子曰:“温故而知新,\n可以为师傅\""
格式化字符串
字符串之间可以进行加法运算
s= 'abc'+'def' # 字符串拼接,两个字符串加起来,输出结果为:abcdef
print("s = " + s) # 注意:字符串不能和其他类型进行加法运算。 输出结果: s = abcdef
print("s =",s) # 输出结果:s = abcdef
print("s= %s"%s) # 输出结果:s= abcdef
在创建字符串时,在字符串中制定占位符
%s 表示任意字符串
s= 'hello %s'%'孙悟空' # s就是孙悟空
s1= 'hello %s,你好,我是%s'%('tom','孙悟空') # hello tom,你好,我是孙悟空 占位符按顺序填充
s2= 'hello %3s'%'1234567890' # %3.5s 字符串长度限制在3-5之间,最少填充3个,最多5个,如果要填充的内容不够就补空格。
%f 浮点数占位符
s3= 'hello %.3f'%3.1415926537 # hello 3.142 表示保留3位小数
%d 整数占位符
s2= 'hello %.3d'%3.1415926537 # hello 003
格式化字符串
可以通过在字符串前添加一个f来创建一个格式化字符串
在格式化字符串中可以直接嵌入变量
a = '孙悟空,'
b = 'tom'
c = f'hello {a} {b}'
print(f'c={c}') # c=hello 孙悟空, tom
字符串复制
字符串和数字相乘
a = 'abc'
#如果将字符串和数字相乘,则解释器会将字符串重复指定的次数并返回
a = a * 2
print(a) #abcabc
布尔值和空值
#布尔值(bool) True False
布尔值主要用来做逻辑判断
#None(空值)
表示不存在
类型检查:
通过类型检查指定值或者(变量)的类型
a = 123
b = '123'
print(type(a)) # <class 'int'>
print(type(b)) # <class 'str'>
对象
每个对象中都要保存三个
id (标识)
标识对象的唯一性,每一个对象都有唯一的id,可通过id()函数查看对象的id
对象一旦创建,则它的id永远不能再改
type(类型)
类型用来表示当前对象所属的类型,比如:int float str bool,类型决定了对象有哪些功能
value
对象中存储的具体值
变量和对象的关系
变量,对象的别名。变量中存储的不是对象的值而是对象的id(内存地址)
当我们使用时,在id查找对象
a = 3 a存的并不是3,而是3的id
类型转换:不是转换对象本身类型,而是将对象的值转换为新的对象
int() float() str() bool()
int()可以用来将其他的对象转换为整型,不会对原来的变量产生影响,如果要修改原来的变量需要对变量进行重新赋值
规则:
布尔值 True -> 1 False -> 0
浮点数 对于浮点数,直接去掉小数部分取整
字符串 合法的整数字符串直接转换为对应的数字,如果不是合法的整数字符串则报错。
对其他不可转换的类型对象,直接抛出异常
a = True
print('a = ', a) #a = True
print('a 的类型是',type(a)) # a 的类型是 <class 'bool'>
# 对变量进行重新赋值
a = int(a)
print('a = ', a) # a = 1
print('a 的类型是',type(a)) # a 的类型是 <class 'int'>
浮点数
a = 11.5
a = int(a)
print('a = ',a,type(a)) # a = 11 <class 'int'>
字符串
a = '11'
a = int(a)
print('a = ',a,type(a)) # a = 11 <class 'int'>
不是合法的整数字符串则报错
a = '11.5'
a = int(a)
print('a = ',a,type(a)) # ValueError: invalid literal for int() with base 10: '11.5'
对其他不可转换的类型对象,直接抛出异常
a = None
a = int(a)
print('a = ',a,type(a)) # TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'
bool() 任何对象都可以转换为布尔值
规则:对于所有表示空性的对象都会转换成False,其余的都会转换成True
a = ''
a = bool(a)
print(a,type(a)) # False <class 'bool'>
表示空性的: 0 、 None、 ''等等
可变对象:
a = [1,2,3]
a[0] = 10 (改对象)
这个操作是在通过变量去修改对象的值,这种操作不会改变变量所指向的对象
a = [10,2,3] (改变量)
这个操作是在给变量重新赋值,这种操作会改变变量所指向的对象。
a = [1, 2, 3]
print('修改前:',a,id(a)) # 修改前: [1, 2, 3] 1839173004800
# 通过索引修改
a[0] = 10
print('修改后:',a,id(a)) # 修改后: [10, 2, 3] 1839173004800
# 为变量重新赋值
a = [10,2,3]
print('修改后:',a,id(a)) # 修改后: [10, 2, 3] 1839173005248
# 当我们去修改对象时,如果有其他变量也指向了该对象,则也修改了其他变量
a = [1, 2, 3]
b = a
print(a,id(a),b,id(b)) # [1, 2, 3] 2807470878208 [1, 2, 3] 2807470878208
b[0] = 10
print('修改后:',a,id(a),b,id(b)) # 修改后: [10, 2, 3] 2807470878208 [10, 2,3]2807470878208
# 当我们为一个变量重新赋值时都不会影响其他变量
a = [1, 2, 3]
b = a
print(a,id(a),b,id(b)) # [1, 2, 3] 2096425594368 [1, 2, 3] 2096425594368
# b[0] = 10
b = [10,2,3]
print('修改后:',a,id(a),b,id(b)) # 修改后: [1, 2, 3] 2096425594368 [10, 2, 3] 2096425594816
运算符
对一个或多个值进行运算或各种操作,比如 + - =
运算符的分类:
算数运算符
赋值运算符
比较运算符(关系运算符)
逻辑运算符
条件运算符(三元运算符)
算数运算符:+ - * / , 整除 //
如果是两个字符串之间进行加法运算,则会进行拼串操作 a = 'hello' + 'world'
整除
a = 10 // 3
print('a = ',a) # a = 3
求16的平方根
a = 16 ** 0.5
print('a = ',a) # a = 4.0
% 取模 求两个数相除的余数
a = 10 % 5
print('a = ',a) # a = 0
a = 10 % 4
print('a = ',a) # a = 2
关系运算符
比较两个值之间的关系,总会返回一个布尔值,如果关系成立,返回 True,否则返回 False
> 、>= 、 < 、 <= 、 == 、 !=
在 Python 中可以对两个字符串进行大于等于或小于等于的运算,比较的是字符串的 Unicode 编码
result = 'a' > 'b'
print(result) # False
比较两个字符串的Unicode编码是是逐比较。可利用该特性对字符串进行排序,但是对于中文来说意义不大。
result = 'ab' > 'b'
print(result) # False
如果不希望比较两个字符串的Unicode编码,则需要将其转换为数字再比较
print(int('2') > int('11')) # False
相等和不等比较的是对象的值
result = 1 == True
print(result) #True
print(type(1),type(True)) # <class 'int'> <class 'bool'>
print(id(1),id(True)) # 140708035823280 140708035544912
is 、 is not 比较两个对象是否是同一个对象,比较的是对象的 id
result = 1 is True
print(result) # False
result = 1 is not True
print(result) # True
a = 10 < 20 > 15
print(a) # True
逻辑运算符
not and or 非 与 或 主要用来做一些逻辑判断
not对右侧的值进行非运算
对于布尔值,非运算会对其进行取反操作,对于非布尔值,非运算会将其转换成布尔值,然后再取反
a = True
a = not a # 对 a 进行非运算
print('a = ',a) # a = False
a = 1
a = not a # 对 a 进行非运算
print('a = ',a) # a = False
and 可以对符号两侧的值进行与运算
只有在符号两侧的值都为 True 时,才会返回 True ,只要有一个 False 就会返回 False
与运算找False,Python 中的与运算时短路与,如果第一个值为False则不在看第二个值。
result = True and True
print(result) # True
与运算找False,Python 中的与运算时短路与,如果第一个值为False则不在看第二个值。
第一个值是True会看第二个值
True and print('你猜我出来吗') # 你猜我出来吗
result = False and print('你猜我出来吗') #
or 符号两侧进行或运算
两个值中只要有一个 True 就为 True
或运算是找 True ,如果第一个值为 True,则不再看第二个。
result = True or False
print(result) # True
result = False or False
print(result) # False
或运算是找 True ,如果第一个值为 True,则不再看第二个。
True or print('你猜我出来吗') #
False or print('你猜我出来吗') # 你猜我出来吗
练习:对不同的布尔值进行3种逻辑运算,然后尝试对非布尔值进行3种逻辑运算,并观察返回结果。
非布尔值的与或运算
非布尔值与或运算时,Python会将其当作布尔值运算,最终会返回原值
#True and True
result = 1 and 3
print(result) # 3 与运算找False,第一个值是True于是去看第二个值,也是True 但是只能返回第二个值了
# False and True
result = 0 and 3
print(result) # 0
# False and False
result = 0 and None
print(result) # 0
或运算是找 True ,如果第一个值为 True,则不再看第二个。否则返回第二个。
result = 2 or 1
print(result) # 2
result = 0 or 1
print(result) # 1
条件运算符
语法:
语句1 if 条件表达式 else 语句2
执行流程:
条件是运算符在执行时,先对条件表达式求值判断,
如果判断结果为True,则执行语句1,并返回执行结果
如果判断结果为False,则执行语句2,并返回执行结果
a = 10
b = 20
print('a大') if a > b else print('b大')
# 获取较大值
max = a if a > b else b
print(max)
练习:a b c三个变量,通过条件运算符获取三个值中的较大值
a = 10
b = 20
c = 30
max = a if a > b else b
max = max if max > c else c
print(max)max = a if a > b and a > c else b if b > c else c #不方便阅读
print(max)
运算符的优先级
和数学中一样,Python中,也是先乘除后加减
and or
先算and 再算or
a = 1 or 2 and 3
print(a) # 1
== 、 = 、 is 、 is not 、 !=
== 、!= 比较的是对象的值是否相等,
is 、is not 比较的id是否相等,比较两个对象是否是同一个对象
a = [1,2,3]b = [1,2,3]print(a == b) # Trueprint(a is b) # a 和 b 不是同一个对象,因此返回 False
控制流
流程控制语句
改变程序的执行顺序,也可以让指定的程序反复执行多次。
条件判断语句,循环语句
条件判断语句(if 语句)
if 条件表达式 : 语句
在执行时,先对条件表达式进行求职判断,如果为 True,则执行 if 后的语句
if True : print('你猜我出来吗') # 你猜我出来吗
如果希望if可以控制多个语句,则可以增加代码块
number = 20
if number > 10 :print('number 比10大') # number 比10大print('谁也管不了我')
else :print('number 比10小')print('你比较厉害')
可以使用逻辑运算符来连接多个条件,同时满足用 and ,只希望满足一个条件即可则使用 or
number = int(input('请输入一个数:'))
if number > 10 and number < 20:print('number 比10大,比20小') # number number 比10大,比20小
练习1
while True:try:number = int(input('请输入一个整数:'))if number >=10 and number <= 20:print('number 在10和20之间')break #break语句作用:跳出for 和 while循环,注意:只能跳出距离它最近的那一层循环except ValueError as e:print("您输入有误!请按照提示重新输入!")
练习2:
让用户输入一个用户名,获取用户输入,并进行判断,如果用户输入的用户名为admin,则显示欢迎管理员登录
如果用户输入发是其他的用户名则什么也不做。
user_name = input('请输入用户名:')
if user_name == 'admin':print('欢迎管理员登录!')
input()函数
调用后,程序会立即暂停,等待用户输入,用户输入后以返回值(字符串)形式返回,
a = input('请输入内容:')
print('用户输入的是:‘,a)
也可以用以暂时阻止程序结束,例如:
print('hello')
input('按回车键退出。。。')
练习3:
让用户在控制台输入一个年龄,判断成年了没有
age = int(input('请输入你的年龄:'))
# input()返回值是一个字符串,必须转换成int类型才能比较
if age >= 18:print("你已经成年了")
if-elif-else 语句 只会有一个代码块会被执行。
语法:
if 条件表达式:
代码块
elif 条件表达式:
代码块
elif 条件表达式:
代码块
else:
代码块
# 如果表达式的结果为True,则执行当前代码块,然后语句结束,
age = int(input('请输入你的年龄:'))
if age > 200:print('活着可真没劲呢!')
elif age > 100:print('你也是老大不小了!')
elif age >= 60:print('你已经退休了!')
elif age >= 30:print('你已经是中年了')
elif age >= 18:print('你已经成年了!')
else:print('你还是个小孩!')
练习4
获取用户输入的整数,判断这个数是奇数还是偶数
while True:try:number = int(input('请输入一个整数:'))if number == 0:print('既不是奇数也不是偶数!')breakelif number%2 == 0:print(number,'是一个偶数!')breakelse:print(number,'是一个奇数!')breakexcept ValueError as e:print('你输入有误,请重新输入!')
练习5
检查任意一个年份是否是闰年,能够被4整除不能被100整除,或者可一个被400整除,这个年份就是闰年
while True:try:number = int(input('请输入一个年份:'))if number == 0:print('不能输入0')elif number%4 == 0 and number%100 != 0 or number%400 == 0:print(number,'是闰年!')breakelse:print(number,'是平年!')breakexcept ValueError as e:print('你输入有误,请重新输入!')
练习6
狗5岁了,相当于人类多少岁?
狗的前两年每一年相当于人类的10.5岁,然后每增加一年就增加四岁。5岁的狗相当于 10.5+10.5+4+4+4 = 33岁
用户输入狗的年龄,显示相当于人类的年龄狗多少岁了?如果是负数则提醒输入有误
# 当用户输入有误时,需要提示错误并且重新输入,所以此处需要一个循环,直到用户输入正确,执行相应语句,然后 break 跳出while循环程序结束
while True:try:number = float(input('请输入狗狗的年龄:')) # 将输入的内容转换为浮点数类型,才可以输入小数。if number < 0:print('您输入的是负数')elif number <= 2 :age = number * 10.5print('狗狗的年龄相当于人年龄的:%.1f岁'% age ) # %.1f 保留小数点后一位breakelse:age = (number-2)*4 + 21print('狗狗的年龄相当于人年龄的:%.1f岁'% age )breakexcept ValueError as e: #当输入的是字符串不是数字类型时,抛出错误print('你输入有误,请重新输入!')
while True:try:dog_age = float(input('请输入狗狗的年龄:'))like_person_age = 0if dog_age > 0:if dog_age <= 2 :like_person_age = dog_age * 10.5else:like_person_age = 2*10.5like_person_age += (dog_age-2)*4print(dog_age,'岁的狗相当于',like_person_age,'岁的人')breakelse:print('您输入不合法!')except ValueError as e: #当输入的是字符串不是数字类型时,抛出错误print('你输入有误,请重新输入!')
练习7
从键盘输入小明的期末成绩:
当成绩为100时,奖励一辆BMW
当成绩是【80-99】时,奖励一台iphone
当成绩是【60-79】时,奖励一本参考书
其他时,什么奖励也没有
while True:try:number = int(input('请输入成绩:'))# 打印分割线print('='*40)if number > 100 or number < 0:print('输入超出范围,重新输入!')elif number == 100:print('成绩优异!你将获得一辆BMW')breakelif 80 <= number:print('成绩不错!你将获得一台iphone' )breakelif 60 <= number:print('成绩一般!需要努力,奖励一本参考书')breakelse:print('成绩不合格!什么也没有')breakexcept ValueError as e:print('你输入有误,请重新输入!')
练习8
满足3个条件就嫁给他:1、身高超过180cm;2、超过1000万资产;3、颜值高于500分
满足其中一个,还将就,一个都不满足,不嫁
while True:try:high = int(input('请输入你的身高:'))money = int(input('请输入你的财富值:'))look = int(input('请评估自己的颜值分:'))if high >= 180 and money >= 1000 and look >= 500:print('我一定嫁给他')breakelif high < 180 and money < 1000 and look < 500:print('我不嫁给他')breakelse:print('也不是一定不行,考虑一下吧!')breakexcept ValueError as e:print('你输入有误,请重新输入!')
fou ...else
for line in open('practice-for-else.txt'):if 'cat' in line:print(line)break
else:print('there is not cat,please search again')
# practice-for-else.txt 这是一个练习用的自己随便编写的一些内容,文本文件需要和python放在同一个目录。
循环语句
while循环、for循环
while 循环
while 条件表达式:
代码块
先对while后的条件表达式进行求值判断
如果判断结果为True,则执行循环体(代码块),循环体执行完毕,继续对条件表达式进行求值判断,
如果判断结果仍为True,则执行循环体(代码块),直到判断结果为False,循环终止。如果循环有对应的else
,则执行else代码块。
循环的3个要件
初始化表达式,通过初始化表达式初始化一个变量
条件表达式:用来设置循环执行的条件
更新表达式:修改变量的值
i = 0 # 初始化表达式,通过初始化表达式初始化一个变量
while i < 10: # 条件表达式:用来设置循环执行的条件
i += 1 # 更新表达式:修改变量的值
print('hello')
练习1
求100以内奇数的和
i = 1
sum = 0
while i < 100:sum += ii += 2
print(sum)
法二:
i = 0
sum = 0
while i < 100:i += 1# 判断是否是奇数if i % 2 != 0:sum += i
print(sum)
练习2
求100以内所有7的倍数和,以及个数
i = 0
sum = 0
while 7*i < 100:sum = sum + 7*ii += 1
print(i)
print(sum)
法二:
i = 7
sum = 0
# 创建一个计数的变量
count = 0
while i < 100:count += 1sum += ii += 7
print('总和是',sum,'总共次数是',count)
练习3
水仙花数是指一个 n 位数(n >= 3),它的每个位上的数字的n次幂之和等于它本身(如: 1**3 + 5**3 + 3**3 = 157)
求1000以内所有的水仙花数
a = 100
e = 0
while a < 1000:b = a % 10 # 个位数c = a // 10 % 10 # 十位数d = a // 100 # 百位数if b ** 3 + c ** 3 + d ** 3 == a:e += 1print(a)a += 1
print(e)
练习4
获取用户输入的任意数,判断是否是质数
num= int(input('输入一个任意的大于1的整数'))
# 要获取到所有可能整除num的整数。来判断有没有它的因数,全部给除一遍。
i = 2
flag = True
while i < num:# 判断num能否被i整除# 如果num能i整除,则说明num一定不是质数if num % i == 0:flag = Falseprint(num)i += 1if flag :print(num,'是质数')
else:print(num,'不是质数')
循环嵌套
外层循环每执行一次,内层循环就要执行一圈例如
i = 0
while i < 5:# 创建内层循环j = 0while j < 5:print('*',end = '') # end = '' 不换行j += 1print()i += 1
外层执行了5次,内层执行了25次
i = 0
while i < 5:
# 创建内层循环
j = 0
while j < i + 1:
print('*',end = '') # end = '' 不换行
j += 1
print()
i += 1
i = 0
while i < 5:
# 创建内层循环
j = 5
while j > i :
print('*',end = '') # end = '' 不换行
j -= 1
print()
i += 1
练习1
打印99乘法表
b = 1
while b < 10:# 创建内层循环a = 1while a <= b :i = a * bprint(a,'*',b,'=',i,end=' ')a += 1print()b += 1
法二:
i = 0
while i < 9:i += 1j = 0while j < i:j += 1print(f'{j}*{j}={i*j} ',end='')print()
练习2
求100以内所有的质数
num = 2
while num < 100:flag = True # 创建一个变量,记录num的状态,默认是质数。i = 2# 判断num能否被i整除# 如果num能i整除,则说明num一定不是质数while i < num:if num % i == 0:flag = False # 如果 i 不能被 j 整除,修改为 Falsei += 1if flag:print(num,end=' ')num += 1
优化:
# 原始 9.2 秒
# 第一次优化 1.22 秒
# 第二次优化 0.07 秒
from time import *
# time() 函数用来获取当前的时间,返回单位是秒
begin = time()
num = 2
while num < 10000:
flag = True
i = 2
while i <= num ** 0.5: # 第二次优化点,时间 0.07 ,对 num 进行了开方,因数的出现是一对一对的。没有必要对因数重复判断例如 3*6=18,6*3=18;2*9=18,9*2=18
if num % i == 0:
flag = False
# 一旦进入判断,则证明 num 一定不是质数,此时内层循环没有继续执行的必要,例如 8%2=0,则就没有必要再去对3、4、5、6、7继续取模判断了。
break # 第一次优化点,时间 1 .22秒
i += 1
if flag:
print(num)
num += 1
end = time()
print()
print('程序花费了',end-begin,'秒')
break
用来立即跳出循环语句(包括 else)
num = 0
while num < 10:
if num == 4:
break
print(num)
num += 1
else:
print('结束了')
continue 可以用来跳过当次循环
num = 0
while num < 5:
num += 1
if num == 4:
continue
print(num)
else:
print('结束了')
range() 可以用来生成一个自然数序列的函数
r = range(5)
print(list(r)) # [0, 1, 2, 3, 4]
# 该函数需要三个参数:起始位置(默认位置是0),结束位置,步长(默认是1)
# 通过 range 可以创建一个执行指定次数的 for 循环
for i in range(10):
print(i,end='')
# for 循环除了创建方式以外,其余的都和 while 一样
综合练习:唐僧大战白骨精
# 显示提示信息
print('='*20,'欢迎光临《唐僧大战白骨精》','='*20)
# 选择你的身份:
print('请选择你的身份:')
print('\t 1、唐僧')
print('\t 2、白骨精')
# 提示用户选择,并获取用户的选择
player = input('请选择【1 - 2】:')
# 打印分隔线
print('-'*64)
# 根据用户的选择显示提示不同信息
if player == '1':
print('你已经选择了1,你将以<唐僧>的身份来进行游戏')
elif player == '2':
print('你竟然选择了白骨精,太不要脸了,系统将自动分配身份')
else:
print('你的输入有误,系统将自动分配身份')
# 根据用户的选择分配身份:(显示不同的提示消息)
# 创建变量保存玩家和Boss的生命值和攻击力
player_life = 20 # 生命值
player_attack = 2 # 攻击力
Boss_life = 50
Boss_attack = 10
# 游戏进行:
# 显示玩家的基本信息(攻击力,生命值)
print(f'你的身份是唐僧,你的生命值是 {player_life},攻击力是 {player_attack}')
# 显示玩家可以进行的操作:练级、打Boss、逃跑
# 打印分隔线
print('-'*64)
# 由于游戏选项需要反复显示,所以必须要在循环中
while True:
print('请选择你的操作:')
print('\t 1、练级')
print('\t 2、打Boss')
print('\t 3、逃跑')
game_choose = input('请选择你要进行的操作【1-3】')
# 练级:提升玩家的攻击力和生命值
if game_choose == '1':
# 增加玩家的生命和攻击
player_life += 5
player_attack += 2
print('-'*64)
print(f'唐僧,恭喜你升级了!你的生命值是 {player_life},攻击力是 {player_attack}')
# 打Boss:玩家对Boss进行攻击,减去Bosss生命值,减去的生命值应该等于玩家的攻击力
elif game_choose == '2':
Boss_life -= player_attack
print('-'*64)
print('<唐僧>攻击了<白骨精>')
# 检查Boss是否死亡
if Boss_life <= 0:
# Boss死亡,玩家胜利,游戏结束
print(f'<白骨精>收到了{player_attack}点伤害,重伤死了,<唐僧赢得了胜利!>')
break
# Boss对玩家进行反击,减少玩家生命值
player_life -= Boss_attack
print('-'*64)
print('<白骨精>攻击了<唐僧>')
if player_life <= 0:
print(f'你受到了{Boss_attack}点伤害,重伤死了!')
print('='*20,'GAME OVER!','='*20)
break
elif game_choose == '3':
print('-' * 64)
print('唐僧一扭头,撒腿就跑,游戏结束!')
break
else:
print('-' * 64)
print('你的输入有误,请重新输入!')
列表
列表(list)
python 中的一个对象,列表可以用来保存多个有序的数据
1、创建列表
my_list = [] # 创建了一个空列表
print(type(my_list))
# 创建了一个包含了5个元素的列表
my_list = [10,20,30,40,50]
# 列表中可以存储任何对象
my_list = [10,'hello',True,None,[1,2,3],print]
# 列表中的对象按照插入顺序保存
my_list = [10,20,30,40,50,60]
# 通过索引(index)来获取列表中的元素,索引是元素在列表中的位置,索引是从0开始的整数
# 通过索引(index)来获取列表中的元素
print(my_list[0])
# 如果使用的索引超过范围,抛出错误:IndexError: list index out of range
# 获取列表中元素的长度,获取到的长度的值是列表的最大索引+1
print(len(my_list))
练习1:
创建一个列表,在列表中保存最好的5个朋友的名字,然后通过索引来获取朋友的名字。
my_friend = ['A','B','C','D','E']
print(my_friend[0])
print(my_friend[1])
...
print(my_friend[4])
切片
切片指在现有列表中,获取一个子列表
列表的索引可以是负数,如果索引是负数,则从列表的后往前获取。
通过切片获取指定的元素:
列表[起始:结束]
my_list = [10,20,30,40,50,60]
print(my_list[0:2]) # 获取到的元素包括起始位置,不包括结束位置元素
# 切片操作返回的是一个新的列表
如果省略结束位置,会一直截取到最后
print(my_list[0:])
如果省略开始位置,会从第一个元素开始截取
print(my_list[:3])
如果开始和结束位置全部省略,则相当于创建了一个列表的副本
print(my_list[:])
列表[起始:结束:步长] 步长:每次获取元素的间隔,默认为 1
print(my_list[0:6:2])
步长不能是0,可以是负数(从列表后向前取)
2、操作列表中的数据
+ 将两个列表拼接为一个列表
list1 = [10,20,30]
list2 = [10,50,60]
my_list = list1 + list2
print(my_list)
* 将列表复制指定次数
list1 = [10,20,30]
my_list = list1 * 3
print(my_list)
in 用来检查指定元素是否存在于列表中
print(50 in my_list)
not in 用来检查指定元素是否不在于列表中
print(50 not in my_list)
len() 获取列表长度
print(len(my_list))
max() 获取列表最大值
print(max(my_list))
min() 获取列表最小值
print(min(my_list))
方法:和函数基本一样,通过 对象.方法() 的形式调用
s.index() 获取指定元素在列表中第一次出现的位置索引
print(my_list.index(50))
第二个参数:表示查找的起始位置
print(my_list.index(50,4))
第三个参数:表示查找的结束位置
print(my_list.index(50,4,6))
s.count() 统计指定元素在列表中出现的次数
print(my_list.count(50))
序列:最基本的一种数据结构,用于保存一组有序的数据,所有的数据在序列当中都有一个唯一的位置(索引),
序列的顺序会按照添加的顺序存储。
分类:序列中的元素是否可以改变
可变序列:列表(list)
不可变序列:字符串(string),元组(tuple)
可变序列修改元素
创建一个列表:
list1 = ['孙悟空',‘猪八戒’,'沙和尚','唐僧','蜘蛛精','白骨精']
# 修改沙和尚为沙悟净
# list1[2] = '沙悟净'
# print(list1)
# 删除索引为2的元素
# del list1[2]
# print(list1)
# 通过切片修改列表,使用新的替换原来的
# list1[0:2] = ['牛魔王','红孩儿','二郎神']
# print(list1) # ['牛魔王', '红孩儿', '二郎神', '沙和尚', '唐僧', '蜘蛛精', '白骨精']
# 向索引为0的位置插入元素
# list1[0:0] = ['牛魔王']
# print(list1) # ['牛魔王', '孙悟空', '猪八戒', '沙和尚', '唐僧', '蜘蛛精', '白骨精']
# 当设置了步长时。序列中元素的个数必须和切片中元素的个数一致
# list1[::2] = ['牛魔王','红孩儿','二郎神']
# print(list1) # ['牛魔王', '猪八戒', '红孩儿', '唐僧', '二郎神', '白骨精']
# 删除列表元素
# del list1[0:2]
# print(list1) # ['沙和尚', '唐僧', '蜘蛛精', '白骨精']
# list1[1:3] = []
# print(list1) # ['孙悟空', '唐僧', '蜘蛛精', '白骨精']
不可变序列修改元素时可通过list()函数将其转换成列表类型之后再就行修改。
操作列表基本方法:
创建一个列表:
list1 = ['孙悟空',‘猪八戒’,'沙和尚']
# s.append(x) 向列表最后添加元素
# list1.append('唐僧')
# s.insert(i,x) 向列表的指定位置添加元素
# list1.insert(2,'唐僧')
# extend(t) 使用新的序列来扩展当前的序列,需要一个序列作为参数,将该序列中的元素添加到当前列表
# list1.extend(['唐僧','白骨精'])
# list1 += ['唐僧','白骨精']
# clear() 清空序列
# list1.clear()
# pop() 根据索引删除,并返回被删除元素
# result = list1.pop(2)
# 删除最后一个元素
# result = list1.pop()
# print(result)
# remove() 删除指定值的元素,如果相同值的元素有多个,只会删除一个
# list1.remove('猪八戒')
# reverse() 反转列表
# list1.reverse()
# sort() 用来对列表中的元素进行排序,默认是升序
# my_list = [5,9,3,8,-2,4,0]
# my_list.sort()
# 降序排列
# my_list.sort(reverse=True)
# print(my_list)
遍历列表:将列表中的所有元素取出来
创建一个列表:
list1 = ['孙悟空','猪八戒', '沙和尚','唐僧']
# while 创建一个循环,来遍历
# i = 0
# while i < len(list1):
# print(list1[i])
# i += 1
# for 循环遍历
# 语法:
# for 变量 in 序列:
# 代码块
# 每执行一次就会将序列中的一个元素赋值给变量
# for i in list1:
# print(i)
# 练习1:将去取出的变量保存到另外一个列表
# list2 = []
# for i in list1:
# list2.append(i)
# print(list2)
练习2:EMS员工管理系统
做一个命令行版本的员工管理系统
# 创建列表保存员工信息
Employee_information = ['孙悟空\t刺客\t花果山','猪八戒\t坦克\t高老庄','沙和尚\t无\t流沙河']
# 欢迎使用员工管理系统
print('='*20,'欢迎使用员工管理系统','='*20)
# 请选择要做的操作
while True:
print(' 请选择要做的操作: ')
print('\t 1、查询员工')
print('\t 2、添加员工')
print('\t 3、删除员工')
print('\t 4、退出系统')
print('-'*60)
# 1、查询员工
# 显示当前系统的所有员工
Operation = input('请输入你的选择【1-4】:')
print('-'*60)
if Operation == '1':
# 打印表头
print('\t序号\t姓名\t职业\t住址')
# 创建一个变量保存员工的序号
n = 1
for Ei in Employee_information:
print(f'\t{n}\t{Ei}')
n += 1
# 2、添加员工
elif Operation == '2':
name = input('请输入员工姓名:')
job = input('请输入员工职业:')
address = input('请输入员工住址:')
# 创建员工信息
infor = f'{name}\t{job}\t{address}'
# 显示是否要添加
# print('员工:',infor,'将会添加')
print('一下员工将会被添加')
print('姓名\t职业\t住址')
print(infor)
user_con = input('是否确认操作[Y/N]')
if user_con == 'Y' or user_con == 'y':
Employee_information.append(f'{name}\t{job}\t{address}')
print('添加成功')
else:
print('添加取消')
pass
# 输入员工姓名、年龄、住址,添加到系统中
# 3、删除员工,根据序号删除
elif Operation == '3':
# 获取要删除员工的序号
del_num = int(input('请输入要删除员工序号:'))
# 判断序号是否有效
if 0 < del_num <= len(Employee_information):
# 根据序号获取索引
del_index = del_num - 1
# 显示提示
print('一下员工将会被删除')
print('\t序号\t姓名\t职业\t住址')
print(f'\t{del_num}\t{Employee_information[del_index]}')
user_con = input('是否确认操作[Y/N]')
if user_con == 'Y' or user_con == 'y':
Employee_information.pop(del_index)
print('删除成功')
else:
print('删除取消')
pass
else:
print('输入有误!')
# 将员工从系统中删除
# 4、退出系统
elif Operation == '4':
input('点击回车键退出!')
break
else:
print('你输入有误,重新选择!')
print('='*60)
元组
元组 tuple 不可变的序列,操作方式基本和列表一致(导致对象改变的,在元组中不能使用)。当希望数据不改变时,使用元组。
创建元组,使用 () 创建元组
# my_tuple = ()
# print(type(my_tuple)) # <class 'tuple'>
# 创建了一个五个元素的元组
# my_tuple = (1,2,3,4,5)
# print(my_tuple[3])
# 不能对元组中的元素重新赋值
# my_tuple[3] = 10
# print(my_tuple[3]) # TypeError: 'tuple' object does not support item assignment
# 当元组不是空元组时,括号可以省略
# my_tuple = 10,20,30,40
# print(type(my_tuple)) # <class 'tuple'>
# 如果元组不是空元组,至少要有一个逗号
# my_tuple = 10,
# print(type(my_tuple)) # <class 'tuple'>
# 元组解包:将元组中的每一个元素都赋值给一个变量
# my_tuple = 10,20,30,40
# a,b,c,d = my_tuple
# print('a=',a)
# print('b=',b)
# print('c=',c)
# print('d=',d)
# 交换两个变量的值
# a = 100
# b = 300
# print(a,b)
# a,b = b,a
# print(a,b)
# 在对一个元组进行解包时,变量的数量必须和元组的元素数量一致
# my_tuple = 10,20,30,40
# a,b = my_tuple
# print(a,b) # ValueError: too many values to unpack (expected 2)
# 也可以在变量前边加一个*,这样变量将会获取元组中剩余的元素
# my_tuple = 10,20,30,40
# a,b ,*c= my_tuple
# a,*b,c = my_tuple
# *a,b,c = my_tuple
# print(*a)
# 不能同时出现两个或以上的 * 变量
字典
字典(dict),一种数据结构,成为映射,和列表类似,都是用来存储对象的容器
# 列表的查询性能很差,在字典中,每一个元素都有唯一的名字,通过唯一的名字可以快速查找到指定的元素
# 字典中可以保存多个对象,每一个对象都会有一个唯一的名字,这个唯一的名字称为 键(key),通过 key 可以快速查询 value
# 这个对象称其为 值(value),所以字典我们也叫键值对(key-value)结构,每一个键值对就是:项(item)
# 创建一个字典
# d = {}
# print(d,type(d)) # {} <class 'dict'>
# 语法
# {key:vlaue,key:vlaue,key:vlaue}
# 字典的值(value)可以时任意对象,字典的键(key)可以是任意的不可变对象(int、str、bool、tuple...)
d = {'name':'孙悟空','age':'18','gender':'男'}
# 字典的键(key)是不能重复的,如果出现了重复的,后面的会替换掉前面的
# d = {'name':'孙悟空','age':'18','gender':'男','name':'sunwukong'}
# print(d) # {'name': 'sunwukong', 'age': '18', 'gender': '男'}
# 需要根据键来获取值
# print(d['name'],d['age'],d['gender'])
# 如果使用了字典中不存在的键,会报错
# print(d['hello']) # KeyError: 'hello'
字典的官方文档
字典的使用
# 使用dict()函数来创建字典,,每一个参数都是一个键值对,这种方式创建的字典key都是字符串
# d = dict(name = '孙悟空',age = 18,gender = '男')
# 也可以将一个包含双值序列的序列转换为字典。双值序列,序列中只有两个值,[1,2]、(a,3)
# 子序列,如果序列中的元素也是序列,那么我们称这个元素为子序列 [(1,2),(3,5)]
# d = dict([('name','孙悟空'),('age',18)])
# print(d,type(d)) # {'name': '孙悟空', 'age': 18} <class 'dict'>
# len()获取字典中键值对的个数
# print(len(d))
# in、not in 检查字典中是否包含指定的键
# print('hello' in d)
# 获取字典中的值,根据键来获取
# 语法:d[key]
# print(d['name'])
# 通过[]来获取值时,如果键不存在会抛出异常 KerError
# get(key,default) 该方法用来根据键来获取字典中的值,如果获取的键在字典中不存在,会返回None
# print(d.get('hello')) # None
# 也可以指定一个默认值,来作为第二个参数,这样获取不到值时将会返回默认值
# print(d.get('hello','默认值')) # 默认值
# 修改字典
# dict[key] = value 如果key存在则修改,不存在则添加
# d['name'] = '猪八戒'
# d['address'] = '花果山'
# setdefault(key,default),如果key存在于字典中,则返回key的值,不会对字典进行任何操作。如果key不存在,则向字典中添加这个key,并设置value
# d.setdefault('name','猪八戒')
# result = d.setdefault('name','猪八戒')
# print(result) # 孙悟空
# d.setdefault('hello','猪八戒')
# print(d) # {'name': '孙悟空', 'age': 18, 'hello': '猪八戒'}
# update[other] 将字典中的key-value添加到当前字典中, 如果有重复的key,后面的会替换前面的
# d = {'a':1,'b':2,'c':3}
# d2 = {'d':4,'e':5,'f':6,'a':7}
# d.update(d2)
# print(d) # {'a': 7, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}
# 删除,可以使用del删除字典中的key、value
# del d['a']
# popitem() 随机删除字典中的一个键值对。一般都会删除最后一个键值对,删除之后会将删除的key-value作为返回值返回,
# 返回的是一个元组,第一个元素是删除的key,第二个是删除的value
# d.popitem()
# result = d.popitem()
# print(d) # {'b': 2, 'c': 3, 'd': 4}
# print(result) # ('e', 5)
# pop(key,default) 根据key删除字典中的key-value,会将被删除的value返回
# result = d.pop('d')
# print(result) # 4
# 如果删除不存在的key,会抛出错误
# result = d.pop('z') # KeyError: 'z'
# 如果指定了默认值再删除不存在的key时不会报错,而是直接返回默认值
# result = d.pop('z','这是默认值')
# print(result) # 这是默认值
# 用来清空字典
# d.clear()
# copy() 该方法用于对字典进行复制,复制后的对象和原对象是独立的,不会相互影响。
# d3 = d2.copy()
# print(d3,id(d3))
# print(d2,id(d2))
# 该方法是浅复制,如果值也是一个可变对象,这个可变对象不会被复制
# d4 = {'a':{'name':'孙悟空','age':18},'b':2,'c':3}
# d5 = d4.copy()
# print(d5)
# d4['a']['name'] = '猪八戒'
# print(d5)
# 字典的遍历
# keys() 该方法会返回字典的所有的key,该方法会返回一个序列,序列中会保存所有字典的所有键。
# d = {'name':'孙悟空','age':18,'gender':'男'}
# print(d.keys())
# 通过遍历keys()获取所有的键
# for k in d.keys():
# print(k)
# 通过遍历keys()获取所有的值
# for k in d.keys():
# print(d[k])
# 通过遍历keys()获取所有的键值
# for k in d.keys():
# print(k,d[k])
# values()
# 通过遍历values()获取所有的值
# for v in d.values():
# print(v)
# items() 该方法会返回字典中所有的项,会返回一个序列,序列中包含双值序列
# 双值分别是字典中的 key 和 value
# for k,v in d.items():
# print(k,'=',v)
集合
集合(set)
集合中只能存储不可变对象
集合中存储的对象是无序的(不是按照元素的插入顺序)
集合中不能出现重复的元素,重复的元素会自动删除,只是保留一个。
# 使用{}创建集合
# s = {10,2,5,4}
# print(s,type(s)) # {10, 2, 4, 5} <class 'set'>
# 集合中只能存储不可变对象
# s = {[4,5,6],[1,2,3]} # TypeError: unhashable type: 'list'
# 使用set()创建集合
# s = set() # 空集合
# 可以通过set()来将序列和字典转化为集合
# s = set([1,2,2,2,3,5,6,4])
# print(s,type(s)) # {1, 2, 3, 4, 5, 6} <class 'set'>
# 使用set()将字典转换为集合时,只会包含字典中的键
# s = set({'a':1,'b':2,'c':3,'d':4})
# print(s,type(s)) # {'c', 'b', 'd', 'a'} <class 'set'>
# 集合不能通过索引,只能转换为列表再取值
# s = {'a','b',1,2,3}
# print(s[0]) # TypeError: 'set' object is not subscriptable
# print(list(s)[0]) # 1
# 集合也可使用in 、not 检查集合中的元素
# 集合也可使用len()获取元素长度
# 向集合中添加元素
# s = {'a', 'b', 1, 2, 3}
# s.add(10)
# print(s)
# update()将集合中的元素添加到当前集合中,可以传递序列或字典作为参数,字典只会使用键
# s = {'a', 'b', 1, 2, 3}
# s2 = {4,5,6}
# s.update(s2)
# s.update((7,8,9))
# print(s)
# pop() 随机删除集合中的元素,并返回
# s = {'a', 'b', 1, 2, 3}
# s.pop()
# result = s.pop()
# print(result)
# remove()删除集合中指定的元素
# s = {'a', 'b', 1, 2, 3}
# s.remove('a')
# 清空集合
# s = {'a', 'b', 1, 2, 3}
# s.clear()
# 集合浅复制
# s.copy()
# 集合的运算,在对集合进行运算时不会影响原来的集合,而是返回一个运算结果
# 创建两个集合
s = {1,2,3,4,5}
s2 = {3,4,5,6,7}
# 交集运算
result = s & s2
# 并集运算
result2 = s | s2
# 差集
result3 = s - s2
# 亦或集,获取只在一个集合出现的元素,两个集合不相交的部分
result4 = s ^ s2
# 检查一个集合是否时另一个集合的子集
result5 = s <= s2 # False
# 检查一个集合是否是另一个集合的真子集,一个集合含有另一个集合的全部元素,且这个集合还有另一个集合不含有的元素,另一个集合就为这个集合的真子集。
函数
'''
# 函数也是一个对象
# 对象是内存中专门用来存储数据的一块区域
# 函数可以用来保存一些可执行的代码,并且可以在需要时对这些语句多次的调用
# 创建函数:
# def 函数名([形参1,形参2,形参n]):
# 代码块
# 定义一个函数
def fun():
print('这是我的第一个函数')
# 打印函数
print(fun) # <function fun at 0x0000025D817AF430>
print(type(fun)) # <class 'function'>
# 函数中保存的代码不会立即执行,需要调用才会执行
# 调用函数:
# fun是函数对象,fun()是调用函数
# print是函数对象,print()是调用函数
fun() # 这是我的第一个函数
# 定义函数,一般都是实现某种功能的。
# 定义一个函数,求任意两个数的和
# 定义函数时,可以在函数后的()中定义数量不等的形参,多个形参之间用逗号,隔开。
# 形参(形式参数),定义形参就相当于在函数内部声明了变量,但不是赋值
def sum(a,b):
print(a + b)
# 调用函数
# 如果函数定义时,指定了形参a,b,那么在函数调用时必须传递实参3,4。有几个形参传递几个实参.
sum(3,4) # 7
# 练习1
# 定义一个函数,可以用来求任意三个数的乘积
def multiply(a,b,c):
print(a*b*c)
multiply(2,3,4) # 24
# 练习2
# 定义一个函数,可以根据不同的用户名显示不同的欢迎信息
def wel(name):
print('欢迎',name,'光临')
wel('孙悟空') # 欢迎 孙悟空 光临
# 定义一个函数,可以为形参指定默认值,
# 指定了默认值以后,如果用户传递了参数,则默认值没有任何作用。如果用户没有传递,默认值生效。
def fn(a,b,c = 20):
print('a=',a)
print('b=',b)
print('c=',c)
fn(1,2,3)
fn(1,2)
# 实参的传递方式
# 位置参数,将对应位置的实参复制给对应位置的形参,即第一个实参赋值第一个形参,第二个实参赋值给第二个形参以此类推
fn(1,2,3)
# 关键字参数,可以不按照形参定义的位置传递,而直接根据参数名去传递参数
fn(a=1,b=2,c=3)
# 位置参数和关键字参数可以混合使用,混合使用时,必须将位置参数写到前面
print('hello',end='')
# 实参的类型
def fn2(a):
print('a=',a)
# b = 123
b = 'hello'
# 函数在调用时,不会检查实参的类型
# fn2(b) # a= 123
fn2(b) # a= hello
fn2(fn) # a= <function fn at 0x000001DF7DABF430>
def fn4(a):
# 在函数中对形参进行重新赋值不会影响其他变量
a = 20
print('a=',a)
c = 10
fn4(c) # a= 20
print(c) # 10
def fn5(a):
# 如果形参指向的是一个对象,当我们通过形参修改对象时,会影响到所有指向该对象的变量
a[0] = 10
print('a=',a,id(a))
c = [1,2,3]
# 形参修改对象时,会影响到所有指向该对象的变量
fn5(c) # a= [10, 2, 3] 2096055512448
print(c,id(c)) # [10, 2, 3] 2096055512448
# 如果不改变,则复制一个副本进去传参
fn5(c.copy()) # a= [10, 2, 3] 2741749608320
print(c,id(c)) # [1, 2, 3] 2741749607872
# 不定长参数
# 要求定义一个函数,可以求任意个数字的和
def sum(*num):
# 定义一个变量保存结果
result = 0
# 遍历元组,并将元组中的数值进行累加
for i in num:
result += i
print(result)
sum(4,5,6) # 15
sum(1,2) # 3
# 定义函数时可以在形参前面加*,这样形参将会获取到所有的实参,将所有的实参保存到一个元组中。
def fn(*a):
print(a,type(a))
fn() # () <class 'tuple'>
# 带 * 的形参只能写一个,带 * 的参数可以和其他参数配合使用
def fn2(a,b,*c):
print('a =',a)
print('b =',b)
print('c =',c)
# 第一个参数给 a 第二个参数给 b ,剩下的参数给 c
fn2(1,2,3,4,5,6)
# 带 * 参数不是必须写在最后,但是带 * 参数后的所有参数,必须以关键字参数的形式传递
# 第一个参数给 a ,剩下的参数都给 b , c必须使用关键字参数
def fn3(a,*b,c):
print('a =',a)
print('b =',b)
print('c =',c)
# 带 * 参数后的所有参数,必须以关键字参数的形式传递
fn3(1,2,3,4,5,c = 6)
# 要求所有的参数必须以关键字参数进行传递
def fn4(*,a,b,c):
print('a =',a)
print('b =',b)
print('c =',c)
# * 形参只能接受位置参数,而不能接受关键字参数
def fn5(*a):
print('a =',a)
# fn5(a =1) # TypeError: fn5() got an unexpected keyword argument 'a'
# **形参可以接受其他的关键字参数,将会把这些参数保存到一个字典中,字典的key就是参数的名字,字典的value就是参数的值
# **形参只能有一个,并且必须写在所有参数的最后
def fn6(b,c,**a):
print('a =',a)
print('b =',b)
print('c =',c)
fn6(a =1,b = 2,c = 3)
# **形参只能有一个,并且必须写在所有参数的最后
# 参数的解包
def fn7(a,b,c):
print('a =',a)
print('b =',b)
print('c =',c)
# 创建一个元组
t = (10,20,30)
# 解包,传递实参时,也可以在序列类型的参数前添加 * ,这样他会自动将序列中的元素依次作为参数传递。
# 要求序列中元素的个数必须和形参的个数一致。
fn7(*t)
# 创建一个字典
d = {'a':100,'b':200,'c':300}
# 通过 ** 来对一个字典进行解包
fn7(**d)
# 返回值,返回值就是函数执行以后返回的结果
# 可以通过 return 来指定函数的返回值,可以通过一个变量来接受函数的返回值
def sum(*num):
# 定义一个变量保存结果
result = 0
# 遍历元组,并将元组中的数值进行累加
for i in num:
result += i
return result
r = sum(1,2,3)
print(r + 4)
# return 后面跟什么值,返回的就是什么值。
# return 后面可以跟任意的对象,返回值甚至可以是一个函数
def fn():
# return 100
def fn2():
print('hello')
return fn2 # 返回值甚至可以是一个函数
r = fn() # 这个函数的执行结果就是它的返回值
print(r) # <function fn.<locals>.fn2 at 0x000002570D6EF790>
# 如果仅仅跟一个 return,或者不写 return,则相当于return none
def fn2():
return
r = fn2()
print(r)
# 在函数中, return 后的代码都不会执行, return 执行,函数自动结束。
def fn3():
print('hello')
return
print('abc')
r = fn3()
print(r)
def fn4():
return 10
print(fn4) # fn4 是函数对象,<function fn4 at 0x00000234FF58F820>
print(fn4()) # fn4()是在调用函数,打印的是fn4()函数的返回值 10
# help() 可以查询函数的用法
help(print)
# 作用域与运行空间
# 作用域(scope):指的是变量生效的区域
b = 20 # 全局变量
def fn5():
a = 10 # a 定义在函数内部,所以它的作用域就是函数内部,函数外部无法访问
print('函数内部 a = ',a)
print('函数外部 b = ',b)
fn5()
# 全局作用域:在程序执行时创建,在程序结束时销毁,所有函数以外的区域都是全局作用域
# 全局作用域中定义变量,都属于全局变量,可以在程序的任意位置都可以被访问
# 函数作用域,在函数调用时创建,在函数结束时销毁,每调用一次就会产生一个新的函数作用域
# 在函数作用域中定义的变量,都是局部变量,它只能在函数内部被访问。
# 变量的查找
# 会优先在当前作用域中寻找变量,如果有则使用,如果没有则继续去上一级作用域中寻找
# 直到全局作用域依然没有找到,则会抛出异常
def fn6():
a = 30
def fn7():
# a = 40
print('fn7中:','a =',a)
fn7()
# fn6() # 优先在当前作用域中寻找变量 fn7中: a = 40
fn6() # fn7中: a = 30
a = 20
def fn7():
# a = 10 # 在函数中为变量赋值时,默认都是为局部变量赋值
# 如果希望在函数内部修改全局变量,则需要使用global关键字,来声明变量
global a
a = 10
print('函数内部 a = ',a)
fn7() # 函数内部 a = 10
print('函数外部 a = ', a) # 函数外部 a = 10
# 命名空间(namespce):
变量存储的位置,每一个变量都需要存储到指定的命名空间中,每一个作用域都有一个它对应的命名空间。
# 全局命名空间用来保存全局变量,函数命名空间用来保存函数中的变量
# 命名空间实际上就是一个专门用来存储变量的字典
locals() # 用来获取当前作用域的命名空间
print(locals())
# 如果在全局作用域中调用 locals() 则获取全局命名空间,如果在函数作用域中调用 locals() 则获取函数的命名空间
globals() # 获取全局命名空间
# 递归
# 尝试求10的阶乘(10!)
# 1!=1
# 2!= 1*2
# 3!=1*2*3
# 4!=1*2*3*4
# 创建一个变量保存结果
n = 10
for i in range(1,10):
n *= i
print(n)
# 创建一个函数,可以用来求任意数的阶乘
def factorial(n):
'''
# 该函数用来求任意数的阶乘
# 参数:
# n要求阶乘的数字
'''
# 创建一个变量,来保存结果
result = n
for i in range(1, n):
result *= i
return result
print(factorial(10))
# 递归式的函数,在函数中自己调用自己
# 无穷递归,类似于死循环
# def fn():
# fn()
# 递归的整体思想是,将一个大问题分解成一个个的小问题,直到问题无法分解时,再去解决问题。
# 递归式函数的两个要件
# 基线条件
# 可以被分解为最小的问题,当满足基线条件时,递归不在执行
# 递归条件
# 将问题继续分解的条件
# 求10的阶乘
# 10!= 10*9!
# 9!=9*8!
# 8!=8*7!
# 1!=1
def factorial(n):
'''
# 该函数用来求任意数的阶乘
# 参数:
# n要求阶乘的数字
'''
# 基线条件 判断n 是否为1 ,如果为1则此时不能再继续递归
if n == 1:
return 1
# 递归的条件
return n * factorial(n-1)
print(factorial(10))
# 练习1 创建一个函数 power 来求任意数字的幂运算 n ** i
def power(n,i):
'''
# 例如:
# 10**4= 10*10**3
# 10**3= 10*10**2
# 10**2= 10*10**1
'''
if i == 0:
return 1
return n*power(n,i-1)
print(power(2,4))
# 练习2 创建一个函数,用来检查任意的字符串是否是回文字符串,是,返回true否则返回false
# 回文字符串,从前往后念和从后往前念一样的。 abcba
def fn2(str):
'''
# 检查 abcdefgfedcba 是不是回文
# 检查 bcdefgfedcb 是不是回文
# 检查 cdefgfedc 是不是回文
# 检查 defgfed 是不是回文
# 检查 efgfe 是不是回文
# 检查 fgf 是不是回文
# 检查 g 是不是回文
'''
# 基线添加
if len(str) < 2:
return True
if str[0] != str[-1]:
return False
# 递归条件
return fn2(str[1:-1])
str = input("请输入一个字符串:")
if fn2(str):
print("该字符串为回文字符串")
else:
print("该字符串不是回文")
# 高阶函数:
# 接收一个或多个函数作为参数或者将函数作为返回值返回的函数
# 当使用一个函数作为参数时,我们实际上传进去的是函数的代码
# 创建一个列表
l = [1,2,3,4,5,6,7,8,9,10]
# 定义一个函数检查任意的数字是否是偶数:
def fn2(i):
if i % 2 == 0:
return True
return False
# 定义一个函数用来检查任意数字是否大于5
def fn3(i):
if i > 5:
return True
return False
# 定义一个函数判断能都被3整除
def fn5(i):
if i % 3 == 0:
return True
return False
# 可改写成:
def fn5(i):
return i % 3 ==0
# 也可改写成匿名函数,见下方匿名函数lamdba
lambda i : i % 3 == 0
# 高阶函数
def fn4(func,l):
'''
# func :可以传递一个函数作为参数
'''
# 创建一个新列表
new_list = []
# 对列表进行筛选
for n in l:
if func(n):
new_list.append(n)
# 返回新列表a
return new_list
print(fn4(fn5,l))
# filter() 可以从序列中过滤处符合条件的元素,然后保存到新的序列
# 参数:
# 1、函数,根据该函数来过滤序列(可迭代结构)
# 2、需要过滤的序列(可迭代结构)
# 返回值:
# 过滤后的新序列(可迭代结构)
# fn5作为参数传递进 filter() 函数中
print(filter(fn5,l)) # 返回值是过滤后的新序列(可迭代结构)# <filter object at 0x00000199CC08B520>
print(list(filter(fn5,l))) # [3, 6, 9]
# fn5 改成匿名函数后
print(list(filter(lambda i : i % 3 == 0,l))) # [3, 6, 9]
# 匿名函数 lambda 函数表达式 ,专门用来创建一些简单的函数,是函数创建的又一种方式
# 语法:lamdba 参数列表:返回值
# 定义一个函数,返回任意两个数的和
# 一般用来做参数,其他地方不用
def fn6(a,b):
return a + b
# 匿名函数,返回任意两个数的和
lambda c , d : c+d
# (lambda c , d : c+d)(10,20)
# 将匿名函数赋值给变量
fn7 = lambda c , d : c+d
print(fn7(10,20))
print(fn6(10,20))
# map()函数可以对可迭代对象中的所有元素做指定的操作,然后将其保存到一个新的对象中返回
l = [1,2,3,4,5,6,7,8,9,10]
# 将列表中每个元素都 +1
r = map(lambda i : i+1,l)
print(r) # <map object at 0x0000022C3FB6B520>
print(list(r)) # [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
# sort() 用来对列表中的元素进行排序,默认直接比较列表中的元素大小
l1 = ['bb','aaaa','c','dddddd','fff']
l1.sort()
print(l1) # ['aaaa', 'bb', 'c', 'dddddd', 'fff']
# 根据字符串长度排序。sort() 可以接受一个关键字参数:key
# key 需要一个函数作为参数,当设置了函数作为参数,每一次都会以列表中的一个元素作为参数来调用函数,并且使用函数的返回值来比较元素的大小
l1.sort(key=len)
print(l1) # ['c', 'bb', 'fff', 'aaaa', 'dddddd']
l3 = [2,5,'1',3,'6','4']
l3.sort(key=int)
print(l3) # ['1', 2, 3, '4', 5, '6']
# sorted()和sort()用大基本一致,但是sorted()可以对任意的序列进行排序,并且使用sorted()排序不会影响原来的对象,而是返回一个新对象
l2 = [2,5,'1',3,'6','4']
print(sorted(l2,key=int)) # ['1', 2, 3, '4', 5, '6']
print('排序后:',l2) # 排序后: [2, 5, '1', 3, '6', '4']
# 闭包
将函数作为返回值返回,也是一种高阶函数.
# 通过闭包可以创建一些只有当前函数能够访问的变量,例如可以创建一些私有的数据藏到闭包中
def fn8():
a = 10
# 在函数内部再定义一个函数
def fn1():
print('我是fn1',a)
# 将内部函数fn1作为返回值返回
return fn1
# r是一个函数,是调用fn8()后返回的函数,这个函数是在fn8()内部定义,并不是全局函数,所以这个函数总是能访问到fn8()内的变量
r = fn8()
print(r) # <function fn8.<locals>.fn1 at 0x0000026D98E6FC10>
r() # 我是fn1 10
# 求多个数的平均值(这种方法是固定的个数,当需要再添加一个数字的平均值时,需要更改nums)
nums= [50,30,20,10,77]
# sum()用来列表中所有元素的和
print(sum(nums)/len(nums)) # 37.4
# 例如:求多个数的平均值(将 num 列表置于函数内部,当需要再添加一个数字的平均值时,直接在外部打印,在外部是无法更改 num 这个列表的。)
def make_averager():
# 创建一个列表用来保存数值
num = []
# 创建一个函数用来计算平均值
def averager(n):
# 将 n 添加到列表中
num.append(n)
# 求平均值
return sum(num)/len(num)
# 将内部函数作为返回值返回
return averager
averager = make_averager()
print(averager(10)) # 10.0
print(averager(20)) # 15.0
# 形成闭包的条件:
# 函数嵌套
# 将内部函数作为返回值返回
# 内部函数必须要使用到外部函数的变量
# 装饰器
# 创建几个函数
def add(a,b):
# 求和
r = a + b
return r
def mul(a,b):
# 求积
r = a*b
return r
# 希望在函数可以在计算前,打印开始计算,计算结束后打印计算完毕
# 可以直接通过修改函数中的代码来完成这个需求,但是会产生一些问题
# 1、如果修改的函数较多,修改麻烦且不方便后期维护
# 2、并且这样做会违反开闭原则(OCP)
# 程序的设计要求开放对程序的扩展,而要关闭对程序的修改
# 在不修改原函数的情况下,对函数进行扩展
def fn9():
print('我是fn9函数......')
# 只需要根据现有的函数创建一个新的函数
def fn9_1():
print('函数开始执行...')
fn9()
print('函数执行结束...')
fn9_1()
def new_add(a,b):
print('函数开始执行...')
r = add(a,b)
print('函数执行结束...')
return r
r = new_add(1,2)
print(r) # 3
# 上面的方式已经可以在不修改源代码的情况下对函数进行扩展,但是这种方式要求我们每扩展一个函数,就要求我们手动创建一个新的函数,实在是太麻烦了。
# 为了解决这个问题,可以创建一个函数,让这个函数可以自动的帮助我们生产函数
def begin_end(old):
'''
# 用来对其他函数进行扩展,使其他函数可以在执行前打印执行开始,执行后打印执行结束
# 参数:
# old 要扩展的函数对象
'''
# 创建一个新的函数
def new_func(*args,**kwargs):
# 如果我们不确定要往函数中传入多少个参数,或者我们想往函数中以列表和元组的形式传参数时,那就使要用*args;
# 如果我们不知道要往函数中传入多少个关键词参数,或者想传入字典的值作为关键词参数时,那就要使用**kwargs。
print('函数开始执行...')
# 调用被扩展的函数
result = old(*args,**kwargs)
print('函数执行结束...')
# 返回函数执行结果
return result
# 返回新函数
return new_func
f = begin_end(fn9)
f1 = begin_end(add)
print(f1) # <function begin_end.<locals>.new_func at 0x00000212544C20D0>
f2 = begin_end(mul)
f()
print(f) # <function begin_end.<locals>.new_func at 0x000001DCB7382040>
r1 = f1(1,2)
print(r1) # 3
r2 = f2(1,2)
print(r2) # 2
# 像 begin_end()这种函数就是我们的装饰器
# 通过装饰器可以在不修改原来函数的情况下对函数进行扩展。
# 在定义函数时,可以通过@装饰器来使用指定的装饰器来装饰函数。可以同时为一个函数指定多个装饰器,函数将会按照从内向外装饰
@begin_end
def say_hello():
print('大家好...')
say_hello()
# 函数开始执行...
# 大家好...
# 函数执行结束...
'''
类与对象
# 面向对象
对象:内存中专门用来存储数据的一块区域
象中可以存储各种数据(比如:数字、布尔值、代码)
对象有三部分组成:
对象的标识(id)
对象的类型(type)
对象的值(value)
# 面向过程
将程序的逻辑分解为一个一个的步骤
通过对每个步骤的抽象,来完成程序,但是这种方式往往只适用用一个功能,如果要实现别的功能,往往要重新编写代码,可复用性较低。
例子:
孩子起床
1、妈妈起床
2、妈妈上厕所
3、妈妈洗漱
4、妈妈做早饭
5、妈妈叫孩子起床
6、孩子上厕所
7、孩子洗漱
8、孩子吃饭
9、孩子背着书包上学
这种编程方式符合我们人类的思维,编写起来相对比较简单。
# 面向对象的编程
关注的是对象,而不关注过程。
将所有的功能统一保存到对应的对象里
例子:
妈妈的功能保存到妈妈这个对象里,孩子的功能保存到孩子这个对象中,要使用某个功能直接找到对应的对象即可
这种方式编写的代码比较容易阅读,并且比较易于维护。但是这种方式编写不太符合常规的思维
# 面向对象思维:
1、找对象
2、用对象
# 类(class)
对象是类的实例(instance),如果多个对象是通过一个类创建的,那么这些都是一类对象
int()、float()、str()、list()......这些都是类
a = int(10) # 创建一个类的实例,类似于 a = 10
# 定义一个简单的类
使用class关键字来定义类
class 类名:
代码块
# 创建一个简单的类
class MyClass():
pass
print(MyClass) # <class '__main__.MyClass'>
# 使用类来创建对象
mc = MyClass()
mc1 = MyClass()
print(mc) # <__main__.MyClass object at 0x0000022AF48C2FD0>
# mc mc1都是MyClass的实例,他们都是一类对象
# isinstance() 检查一个对象的是否是一个类的实例
result = isinstance(mc,MyClass)
print(result) # True
# 类也是一个对象,用来创建对象的对象
print(id(MyClass),type(MyClass)) # 2853281920496 <class 'type'>
# 向对象中添加变量,对象中的变量成为属性
语法:对象.属性名 = 属性值
mc.name = '孙悟空'
print(mc.name) # 孙悟空
# 类的定义
类和对象都是对程序中的内容的抽象
实际上所有的事物都有两部分构成:
1、数据(属性) 例如:人的属性:身高、体重、
2、行为(方法) 例如:人的行为:行走、吃饭
尝试定义一个表示人的类:
class Person():
# 在类的代码块中可以定义变量和函数
# 在类中所定义的变量将会成为所有实例的公共属性,所有实例都可访问
name = '孙悟空'
# 在类中定义的函数,称为方法,这些方法可以通过该类的所有实例来访问
def say_hello(a):
print('你好!')
# 创建Person的实例
p1 = Person()
p2 = Person()
# 方法调用和函数调用的区别:
# 函数调用,调用时传递几个参数,就会有几个实参,方法调用则默认回传递一个参数。所以方法中至少要定义一个形参。
# 如果定义的函数不带形参则:TypeError: say_hello() takes 0 positional arguments but 1 was given
p2.say_hello() # 你好!
# 在类的代码块中可以定义变量和函数,变量会成为该类的公共属性,所有该类的实例都可以通过 对象.属性名 的形式访问
# 函数会成为该类的公共方法,所有该类的实例都可以通过 对象.方法名() 的形式调用方法
# 方法在调用时,第一个参数由解析器自动传递,定义方法时至少要定义一个形参
# 实例为什么能访问到类中的属性和方法
# 类中定义的属性和方法都是公共的,任何该类实例都可访问
# 属性和方法的查找流程
# 当我们调用一个对象的属性时,解析器会先在当前对象中寻找是否含有该属性,如果有则直接返回当前对象的属性值,
# 如果没有则取当前对象的类对象中取寻找,如果有则返回类对象属性值,如果没有则报错。
p1.name = '猪八戒'
print(p1.name,p2.name) # 猪八戒 孙悟空
# 类对象和实例对象中都可以保存属性(方法)
# 如果这个属性(方法)是所有实例共享的,则应该保存到类对象中,
# 如果这个属性(方法)是某个实例独有,则应该保存到实例对象中。
# 一般情况下,属性保存到实例对象中。方法保存到类对象中
p2.name = '沙和尚'
print(p1.name,p2.name) # 猪八戒 沙和尚
# del p2.name # 删除 p2 的 name 属性
class Person1():
name = 'swk'
# 在类中定义的函数,称为方法,这些方法可以通过该类的所有实例来访问
def say_hello(self):
# 方法每次被调用,解析器都会自动传递一个实参
# 第一个参数,就是调用方法的对象本身
# 如果是p1调的,则第一个参数就是p1对像
# 如果是p2调的,则第一个参数就是p2对像
# 一般我们将这个参数命名为 self
# say_hello() 这个方法可以显示如下格式的数据:
# 你好!我是xxx
# 在方法中不能直接访问类中的属性
print('你好!我是 %s'% self.name)
pass
# 创建Person1的实例
p1 = Person1()
p2 = Person1()
p1.name = '孙悟空'
p2.name = '猪八戒'
p1.say_hello() # 你好!我是 孙悟空
p2.say_hello() # 你好!我是 猪八戒
class Person2:
# 在类中可以定义一些特殊方法,特殊方法都是以__开头__结尾的方法
# 特殊方法不需要我们自己调用,不要去尝试调用特殊方法,特殊方法在特殊的时刻自动调用
# 学习特殊方法:特殊方法什么时候调用;特殊方法有什么作用
# 创建对象的流程:
# 1、创建一个变量
# 2、在类中创建一个新对象
# 3、__init__(self)执行
# 4、将对象的id赋值给变量
# __init__(self) 会在对象创建以后立即执行; __init__(self) 向新创建的对象中初始化属性
# 调用类创建对象时,类后面的所有参数都会依次传递到 __init__()中
def __init__(self,name1):
# print("__init__执行了")
# 通过self 向新建的对象中初始化属性
self.name1 = name1
def say_hell(self):
print('大家好,我是%s'%self.name1)
#################################################################################
# 目前来讲,对于Person2类来讲name1是必须的,并且每一个对象中的name1属性基本上都是不同的。
# 而我们现在是将name1属性在定义对象以后,手动添加到对象中,这种方式很容易出现错误
p1 = Person2()
# 手动添加属性
p1.name1 = '孙悟空'
p2 = Person2()
# 手动添加属性
p2.name1 = '猪八戒'
#################################################################################
# 我们希望用户在创建对象必须设置name1属性,如果不设置对象将无法创建,并且属性的创建应该是自动完成的,而不是在创建对象以后手动完成
# p1 = Person2() # __init__执行了
p1 = Person2('沙和尚')
print(p1.name1)
p1.say_hell() # 大家好,我是沙和尚
# 类的基本结构
class 类名(父类):
公共的属性
# 对象的初始化方法
def __init__(self,...):
...
# 其他的方法
def method_1(self):
...
def method_2(self):
...
# 练习
# 自定义一个类,表示狗的类(Dog)
# 属性:name、age、gender、height
# 方法:jiao() yao()
class Dog():
def __init__(self,name,age,gender,height='12cm'):
self.name = name
self.age = age
self.gender = gender
self.height = height
def dog_jiao(self):
print('%s岁的'%self.age + self.gender +'%s狗又开始叫了!'%self.name)
def dog_yao(self):
print('%s岁的'%self.age + self.gender +self.height +'%s狗会咬人了!'%self.name)
dog1 = Dog('旺旺','1','公','20cm')
dog2 = Dog('旺财',age= 1,gender='公')
# 目前我们可以直接通过 对象.属性 的方式来修改属性的值,这种方式导致对象中的属性可任意修改,非常的不安全,值可以任意修改,不论对错
# 现在我们就需要一种方式来增强数据的安全性
# 1、属性不能随意修改
# 2、属性值不能修改喂任意的值(年龄不能是负数)
dog1.name = '小黑'
dog2.age = -10
dog1.dog_jiao()
dog1.dog_yao()
dog2.dog_yao()
封装
# 封装是面向对象的三大特性之一
# 封装指的是隐藏对象中一些不希望被外部所访问到的属性和方法
class Dog():
'''
表示狗的类
'''
def __init__(self,name,age):
self.hidden_name = name
self.hidden_age = age
def say_hello(self):
print('大家好,我是%s'%self.hidden_name)
def get_name(self):
'''
get_name() 获取对象 name 属性
'''
print('用户读取了属性')
return self.hidden_name
def set_name(self,name):
print('用户修改了属性')
self.hidden_name = name
def get_age(self):
return self.hidden_age
def set_age(self,age):
if age > 0: # 使用setter方法设置属性,可以增加数据的验证,确保数据的值是正确的
self.hidden_age = age
# 如何隐藏
# 将对象的属性名修改为一个外部不知道的名字 name 改为 hidden_name 用户就不好猜这个名字了,就不好改
# 如何获取(修改)对象中的属性?
# 需要提供一个 getter 和 setter 方法使外部可以访问到属性
# getter 获取对象中指定属性(get_属性名)
# setter 用来设置对象的指定属性(set_属性名 )
d = Dog('旺财','10')
d.say_hello() # 大家好,我是旺财
print(d.get_name()) # 旺财
# 调用 setter 来修改 name 属性
d.say_hello() # 大家好,我是旺财
d.set_name('小黑')
d.say_hello() # 大家好,我是小黑
# 使用封装确实增加了类的定义复杂程度,但是也确保了数据的安全性
# 1、隐藏了属性名,使调用者无法随意修改对象中的属性
# 2、增加了getter 和setter方法,很好的控制属性是否是只读的。
# 如果只希望属性是只读的,则可以直接去掉setter方法
# 如果希望属性不能被外部访问,则可以直接去掉getter方法
# 3、使用setter方法设置属性,可以增加数据的验证,确保数据的值是正确的
# 4、使用 getter 方法获取属性,使用 setter 方法设置属性
# 可以在读取属性和修改属性的同时做一些其他处理
class Rectangle:
'''
表示矩形的类
'''
def __init__(self,width,height):
self.hidden_width = width
self.hidden_height = height
def get_width(self):
return self.hidden_width
def get_height(self):
return self.hidden_height
def set_width(self,width):
self.hidden_width = width
def set_height(self,height):
self.hidden_height = height
def get_area(self):
return self.hidden_height * self.hidden_width
r = Rectangle(5,3)
print(r.get_area()) # 15
# 可以为对象的属性使用双下划线开头 __xxx
# 双下划线开头的属性,是对象的隐藏属性,隐藏属性只能在类的内部提问,无法通过对象访问。
# 一般不用,因为还是可以通过 _类名__属性名 从外部访问
# 一般情况下使用 _开头的都是私有属性,没有特殊需要不要修改
class Person():
def __init__(self,name):
self.__name = name
def get_name(self):
return self.__name
def set_name(self,name):
self.__name = name
p = Person('孙悟空')
#print(p.__name) # __开头的是隐藏属性(实际上是将名字修改为了_类名__属性名),无法通过对象访问 'Person' object has no attribute '__name'
print(p._Person__name) # 孙悟空 实际上是将名字修改为了_类名__属性名 ,依然可以在外部访问。
print(p.get_name())
property 装饰器
class Person():
def __init__(self,name,age):
self._name = name
# property 装饰器,用来将一个get方法,转义为对象的属性
# 添加 property 装饰器 以后,我们就可以调用属性一样使用 get 方法
# 使用 property 装饰的方法,必须和属性名是一样的。
@property
def name(self):
print('get 方法执行了')
return self._name
# setter 方法的装饰器:@属性名.setter
@name.setter
def name(self,name):
print('set执行了')
self._name = name
@property
def age(self):
return self._age
@age.setter
def age(self,age):
self._age = age
p = Person('孙悟空',18)
print(p.name)
p.name = '猪八戒'
p.age = 18
print(p.name,p.age)
继承和多态
继承
# 定义一个类 Animal(表示动物)
# 这个类中需要两个方法: run()、sleep()
class Animal():
def run(self):
print('this animal can run!')
def sleep(self):
print('This anmial can sleep!')
# 定义一个类 Dog()
# 这个类中需要三个方法:run()、sleep()、bark()
# 有一个类能够实现我们需要的大部分功能,但是不能实现全部的功能,如何能让这个类实现全部的功能
# 通过继承可以使一个类获取到其他类中的属性和方法
# 在定义类的时候,可以在类名后的括号中指定当前类的父类
# 子类可以继承如父类中的所有属性和方法
class Dog(Animal):
def bark(self):
print('汪汪汪...')
d = Dog()
d.sleep() # This anmial can sleep!
# 通过继承可以直接让子类获取到父类的方法或属性,避免重复编写,经常需要通过继承来对一个类进行扩展
class HaShiQi(Dog):
def fang_sha(self):
print('哈士奇犯傻')
h = HaShiQi()
h.run()
h.bark()
# 检查一个类是否是另一个类的子类
print(issubclass(Dog,Animal)) # True
# 检查一个对象是否是一个类的实例
print(isinstance(h,HaShiQi)) # True
方法重写
# 定义一个类 Animal(表示动物)
# 这个类中需要两个方法: run()、sleep()
class Animal():
def run(self):
print('this animal can run!')
def sleep(self):
print('This anmial can sleep!')
class Dog(Animal):
def bark(self):
print('汪汪汪...')
def run(self):
print('dog can run!')
d = Dog()
d.run() # dog can run!
# 在子类中如果有和父类同名的方法,则通过子类实例去调用方法时,会调用子类的方法而不是父类的方法
# 这个特点叫做方法的重写
class A(object):
def test(self):
print('AAA')
class B(A):
pass
class C(B):
pass
c = C()
c.test()
# 当我们调用一个对象的方法时,会优先去从当前对象中寻找方法,如果有则直接调用,如果没有则去当前的父类中寻找,如果还没有则去父类中的父类寻找,以此类推。
supper()
class Animal(object):
def __init__(self,name):
self._name = name
def run(self):
print('this animal can run!')
def sleep(self):
print('This anmial can sleep!')
@property
def name(self):
return self._name
@name.setter
def name(self,name):
self._name = name
# 父类中所有的方法都会被子类继承,包括特殊方法,也可以重写特殊方法
class Dog(Animal):
def __init__(self,name,age):
# 希望可以直接调用父类的 __init__ 来初始化父类定义的属性
# supper() 动态获取当前类的父类,并且通过supper()调用父类的方法时,不需要传递 self
super().__init__(name) # 继续使用父类的属性
self._age = age
def bark(self):
print('汪汪汪...')
def run(self):
print('dog can run!')
@property
def age(self):
return self._age
@age.setter
def age(self,age):
self._age = age
d = Dog('旺财',18)
print(d.age)
print(d.name)
多重继承
class A(object):
def test(self):
print('AAA')
class B(object):
def test2(self):
print('BBB')
# 在python中是支持多重继承的,也就是我们可以为一个类同事指定多个父类,
# 可以在类名()后添加多个类,用来实现多重继承,多重继承会让代码过于复杂。
# 如果多个父类中有同名的方法,则会在第一个父类中寻找,然后找第二个,前边父类的方法会覆盖后边父类的方法。
class C(A,B):
pass
# 多重继承会使子类同时拥有多个父类,并且会获取到多有父类中的方法
# 类名.__bases__ 这个属性可以用来获取当前类的所有父类
print(C.__bases__) # (<class '__main__.A'>, <class '__main__.B'>)
c = C()
c.test2() # BBB
多态
# 面向对象的三大特征之一
# 狗(狼狗、哈士奇、古牧、、、)
# 一个对象可以以不同的形态去呈现
# 定义两个类
class A:
def __init__(self,name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self,name):
self._name = name
class B:
def __init__(self,name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self,name):
self._name = name
a = A('孙悟空')
b = B('猪八戒')
print(a.name) # 孙悟空
# 定义一个函数
# 对于 say_Hello() 这个函数来说,只要对象中含有name属性,他就可以作为参数传递
# 并不会考虑对象的类型,只有 name 属性即可
def say_Hello(obj):
print('你好 %s'%obj.name)
say_Hello(a) # 你好 孙悟空
# say_Hello_2() 中我们做了一个类型检查,也就是只有obj是A类型的对象时才可以正常使用,
# 其他类型的对象都无法使用该函数,这个函数就违反了多态,
# 违反了多态的函数,只适用于一种类型的对象,无法处理其他类型对象。导致函数的适应性非常差
# isinstance()函数,在开发中一般不使用
def say_Hello_2(obj):
# 做类型检查
if isinstance(obj,A):
print('你好 %s'%obj.name)
else:
print('该对象不是A的实例')
say_Hello_2(a) # 你好 孙悟空
say_Hello_2(b) # 该对象不是A的实例
# 鸭子类型
# 如果一个东西走路像鸭子,叫声像鸭子,那么它就是鸭子
# len()
# 之所以一个对象能通过len()来获取长度,是因为对象中具有一个特殊方法__len__
# 只要对象中具有__len__特殊方法,就可以通过len()来获取它的长度
l = [1,2,3]
s = 'hello'
print(len(l))
print(len(s))
# 面向对象的三大特征
# 封装:
# 确保了对象中的数据安全
# 继承:
# 保证了对象的可扩展性
# 多态:
# 保证了程序的灵活性
属性和方法
# 定义一个类
class A(object):
# 类属性,直接在类中定义的属性是类属性,可以通过类或类的实例访问到
count = 0
def __init__(self):
# 实例属性 通过实例对象添加的属性属于实例属性
# 实例属性只能通过实例对象来访问和修改,类对象无法访问和修改
self.name = '孙悟空'
# 实例方法
# 在类中定义,以 self 为第一个参数的方法都是实例方法
# 实例方法在调用时,python 会将调用对象作为 self 传入
def test(self):
print('这是 test 方法',self)
# 类方法
# 在类内部使用 @classmethod 来修饰的方法属于类方法
# 类方法的第一个参数时cls 也会被自动传递, cls 就是当前的类对象
@classmethod
def test_2(cls):
print('这是test_2方法,它是一个类方法...',cls)
print(cls.count)
# 静态方法
# 在类中使用 @staticmethod 来修饰的方法属于静态方法
# 静态方法,基本上是一个和当前类无关的方法,只是一个保存到当前类中的一个函数
# 静态方法一般都是一些工具方法
@staticmethod
def test_3():
print('这是test_3执行了')
a = A()
# 类属性,可以通过类或类的实例访问到
print(a.count)
# 类属性只能通过类对象来修改,不能通过实例对象修改
a.count = 10 # 通过实例对象添加的属性属于实例属性
print('A',A.count)
print('a',a.count)
a.test() # 这是 test 方法 <__main__.A object at 0x000002997082A400>
# 实例方法可以通过实例和类去调用
# A.test() # TypeError: test() missing 1 required positional argument: 'self'
A.test(a) # 这是 test 方法 <__main__.A object at 0x000001AFBBD9A400>
# 当通过实例调用时,会自动将当前调用对象作为 self 传入
# 当通过类调用时,不会自动传递 self ,此时必须手动传递 self
A.test_2() # 这是test_2方法,它是一个类方法... <class '__main__.A'>
# 类方法和实例方法的区别,实例方法的第一个参数是 self ,而类方法的第一个参数是 cls
# 类方法可以通过类调用也可以通过实例调用
a.test_2() # 这是test_2方法,它是一个类方法... <class '__main__.A'>
# 静态方法不需要指定任何的默认参数,静态方法可以通过类和实例调用
a.test_3() # 这是test_3执行了
A.test_3() # 这是test_3执行了
# 类属性
# 实例属性
# 类方法
# 实例方法
# 静态方法
垃圾回收
# 程序在运行过程中也会产生垃圾
# 在程序中没有被引用的对象就是垃圾
# 将垃圾对象从内存中删除
# python 会自动将这些没有被引用的对象删除,所以我们不用手动处理垃圾
class A:
def __init__(self):
self.name = 'A类'
# del 是一个特殊的方法,它会在对象被垃圾回收前调用
def __del__(self):
print('A()对象被删除了',self)
a = A()
print(a.name) # A类
# 将 a 设置为了 None 此时没有任何的变量对 A() 对象进行引用,它就变成了垃圾
a = None # A()对象被删除了 <__main__.A object at 0x0000022ED37BA400>
input('回车键退出')
特殊方法
# 特殊方法都是使用 __ 开头和结尾的
# 一般不需要我们手动调用,需要在一些特殊情况下自动执行
# 定义一个类
class Person(object):
def __init__(self,name,age):
self.age = age
self.name = name
# 创建两个Person实例
p1 = Person('孙悟空',18)
# 当我们打印一个对象时,实际上打印的时对象中的特殊方法 __str__() 的返回值
print(p1) # <__main__.Person object at 0x00000133A8D1A400>
class Person(object):
def __init__(self,name,age):
self.age = age
self.name = name
# __str__() 这个给特殊方法会在尝试将对象转换为字符串的时候调用
# 它的作用可以用来指定对象转换为字符串的结果 (print 函数)
def __str__(self):
return 'Person [name=%s,age=%d]'%(self.name,self.age)
# __repr__() 对当前对象使用repr函数时调用
# 它的作用是指定对象 在 交互模式 中直接输出的效果
def __repr__(self):
return 'hello'
p2 = Person('猪八戒',20)
print(p2) # Person [name=猪八戒,age=20]
# print(p1 > p2) # TypeError: '>' not supported between instances of 'Person' and 'Person'
'''
object.__lt__(self,other) 小于
object.__le__(self,other) 小于等于
object.__eq__(self,other) 等于
object.__ne__(self,other) 不等于
object.__gt__(self,other) 大于
object.__ge__(self,other) 大于等于
__len__() 获取长度
__bool__() 可以通过它指定对象转换为布尔值
'''
class Person(object):
def __init__(self,name,age):
self.age = age
self.name = name
# __gt__(self, other) 函数会在对象做大于比较的时候被调用,该方法的返回值将会作为比较的结果
# 它需要两个参数,一个self 表示当前对象,other 表示和当前对象比较的对象
# self > other
def __gt__(self, other):
return self.age > other.age
p2 = Person('猪八戒', 20)
p1 = Person('孙悟空',18)
print(p1 > p2) # False
class Person(object):
def __init__(self,name,age):
self.age = age
self.name = name
def __bool__(self):
return self.age >= 18
p2 = Person('猪八戒', 20)
p1 = Person('孙悟空',11)
if p1:
print(p1.name,'已经成年了')
else:
print(p1.name,'还未成年')
模块
# 模块
# 模块化,指将完整的程序分解成一个一个小的模块,通过将模块组合,来搭建一个完整的程序
# 将程序分别编写到多个文件中
# 模块化的优点
# 方便开发与维护
# 模块可以复用
# 模块的创建,在python中一个.py文件就是一个模块
# 注意模块名要符合标识符的规范
# 在一个模块中引入外部模块
# import 模块名(就是python文件的名字)
import test_moudle # test_moudle 是新建的一个.py文件,里面只有一行代码print('我是一个模块')
# 可以引入同一个模块多次,但是模块的实例只会创建一个
print(test_moudle) # <module 'test_moudle' from 'D:\\study\\阿里学习\\test_moudle.py'>
# 引入模块的第二种方式 import 模块名 as 模块别名
import test_moudle as test
print(test) # <module 'test_moudle' from 'D:\\study\\阿里学习\\test_moudle.py'>
# 在每一个模块内部都有一个 __name__这个属性,通过这个属性可以获取到模块的名字
print(test.__name__) # test_moudle
# __name__属性值为__main__的模块是主模块,一个程序只会有一个主模块
print(__name__) # __main__
包
# Package 也是一个模块,当一个模块需要被分解为多个模块时或模块中代码过多时。需要使用包
# 创建一个包 hello
import hello
print(hello.a) # 10
print(hello.b) # 20
hello.test() # test
from hello import hi
print(hi.c) # 30
# __pycache__ 是模块的缓存文件
hello 是一个文件夹 里面包含了 __init__.py hi.py两个文件
__init__.py
a = 10
b = 20
def test():
print('test')
hi.py
c = 30
d = 40
python标准库
# 在这个标准库中有很多模块可以直接使用
# 官方文档中提供了很多模块 python module index
# 例如 sys
import sys
import pprint
# pprint()提供了一个方法,该方法可以用来对打印的数据做简单的格式化
# sys.argv # 执行代码时,命令行中所包含的参数
print(sys.argv) # ['D:/study/阿里学习/模块/python标准库.py']
# sys.modules 获取当前程序中引入的所有模块
print(sys.modules) # 返回的是一个字典,字典的 key 是模块的名,字典的 value 是模块的本身
pprint.pprint(sys.modules)
# sys.path 列表中保存的是模块的搜索路径
pprint.pprint(sys.path)
# sys.platform 表示当前python运行的平台
print(sys.platform)
# sys.esit() 函数用来退出程序
# sys.exit('程序异常结束')
# os 模块让我们可以对操作系统进行访问
import os
print(os.path)
# os.environ
# 通过这个属性可以获取到操作系统的环境变量
print(os.environ['path'])
# os.system() 可以用来执行操作系统的名字
os.system('dir')
os.system('notepad')
异常
# print(a) # NameError: name 'a' is not defined
# 程序在运行过程中,不可避免的会出现一些错误,比如使用未赋值的变量,使用了不存在的变量,除0
# 程序出现异常将会导致程序立即终止
# 处理异常
try:
pass # 可能出现的错误语句
except:
pass # 出错以后处理的方式
else:
pass # 没出错要执行的语句
# 可以将可能储蓄哦的代码块放入到 try 语句,这样如果代码没有错误,则会正常执行。
# 如果出现错误就会执行except子句中的代码,从而通过判断代码来处理异常,避免因为一个异常导致整个程序的停止
print('hello')
try:
print(10/2)
except:
print('出错了')
else:
print('没有错误')
print('你好')
异常对象
print('异常出现之前')
try:
#print(c)
print(10/0)
except NameError:
# 如果 except 不跟任何内容,则它会捕获到所有的异常
# 如果在 except 后跟着一个异常的类,那么它只会捕获该类型的异常
print('出现 NameErro 异常')
except ZeroDivisionError:
print('被除数为0')
print('异常出现之后')
# Exception 所有异常类的父类
# 可以在异常类后面跟一个 as xx 此时 xx就是异常类
try:
print(10/0)
except Exception as e:
print('出现异常',e,type(e))
# 出现异常 division by zero <class 'ZeroDivisionError'>
try:
print(10/0)
except Exception as e:
print('出现异常',e,type(e))
finally:
print('无论是否有异常,都会执行')
try:
print(10/2)
finally:
print('无论是否有异常,都会执行2')
# 自定义异常对象
# 可以使用 rasie 来抛出异常
def add(a,b):
# 如果 a 和 b 中有负数,就像外部调用出抛出异常
if a < 0 or b < 0:
# raise 用于向外部抛出异常,后边可以跟一个异常类或者异常类的实例
# raise Exception
raise Exception('两个参数中不能有负数')
resulet = a+b
return resulet
print(add(-1,2))
'''
Traceback (most recent call last):
File "D:/study/阿里学习/异常和文件/异常对象.py", line 47, in <module>
print(add(-1,2))
File "D:/study/阿里学习/异常和文件/异常对象.py", line 44, in add
raise Exception('两个参数中不能有负数')
Exception: 两个参数中不能有负数
'''
# 自定义类
# 只需要创建一个类继承Exception即可
class MyError(Exception):
pass
异常的传播
# print(10/0)
'''
Traceback (most recent call last):
File "D:/study/阿里学习/异常和文件/异常的传播.py", line 3, in <module>
print(10/0)
ZeroDivisionError: division by zero
'''
def fn():
print('Hello fn')
#print(10 / 0)
'''
Traceback (most recent call last):
File "D:/study/阿里学习/异常和文件/异常的传播.py", line 23, in <module>
fn()
File "D:/study/阿里学习/异常和文件/异常的传播.py", line 12, in fn
print(10 / 0)
ZeroDivisionError: division by zero
Hello fn
'''
fn()
# 当在函数中出现异常时,如果函数中对异常进行了处理,则异常不会再继续传播
def fn():
print('Hello fn')
try:
print(10 / 0)
except:
pass
fn()
# 如果函数中对异常没有进行处理,则异常会继续想函数调用出传播
def fn():
print('hello fn')
#print(10/0)
def fn2():
print('hello fn2')
fn()
def fn3():
print('hello fn3')
fn2()
fn3()
'''
Traceback (most recent call last):
File "D:/study/阿里学习/异常和文件/异常的传播.py", line 44, in <module>
fn3()
File "D:/study/阿里学习/异常和文件/异常的传播.py", line 43, in fn3
fn2()
File "D:/study/阿里学习/异常和文件/异常的传播.py", line 40, in fn2
fn()
File "D:/study/阿里学习/异常和文件/异常的传播.py", line 37, in fn
print(10/0)
ZeroDivisionError: division by zero
'''
# 如果函数调用出处理了异常,则不再传播
def fn():
print('Hello fn')
print(10/0)
try:
fn()
except:
pass
# 异常传播时,实际上就是异常对象抛给了调用处,
print(NameError) # <class 'NameError'>
# 比如:ZeroDivisionError 类的对象,专门用来表示除0的异常。python 中提供了多个异常类的对象
文件
# 操作文件的步骤
# 打开文件
# 对文件进行操作(读写),然后保存
# 关闭文件
# 打开文件(函数在官方文档 Librery Reference - built in function)
# 创建文件 demo.txt
# open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
# 使用 open()函数打开一个文件
# 参数:file 要打开文件的名字(路径)
# 创建一个变量,来保存文件的名字
# 如果目标文件和当前文件在同一及目录下,则直接使用文件名即可。如果不在同一级需要写全部的目录路径
file_name = 'demo.txt'
# 如果目标文件距离当前文件较远,此时可以使用绝对路径
# file_name = r'D:\study\阿里学习\异常和文件\demo.txt'
open(file_name) # 打开 file_name 对应的文件
# open()函数的返回值是一个对象,代表了当前代开的文件
file_obj = open(file_name)
# print(file_obj) # <_io.TextIOWrapper name='demo.txt' mode='r' encoding='cp936'>
# 当我们获取了文件对象以后,所有对文件的操作都应该通过对象来操作
# read()读取文件内容,它会将内容全部保存为一个字符串返回
content = file_obj.read()
print(content)
# 关闭文件
file_obj.close()
# with ... as 语句
with open(file_name) as file_obj:
# 在with语句中可以直接使用 file_obj来操作文件
# 此时这个文件只能在with中使用,一旦with结束时文件会自动关闭
print(file_obj.read())
file_name = 'hello'
try:
with open(file_name) as file_obj:
print(file_obj.read())
except FileNotFoundError:
print(f'{file_name} 文件不存在')
file_name = 'demo2.txt'
try:
# 调用open()来打开一个文件,可以将文件分成两种类型
# 纯文本文件(使用utf-8等编码编写的文本文件)
# 二进制文件(图片,PPT、MP3等这些文件)
# open()打开文件,默认是以文本文件的形式打开的,但是open()默认的编码为None
# 处理文本文件时,必须指定文件编码
with open(file_name,encoding='utf-8') as file_obj:
# 如果直接调用read()它会将文本文件的所有内容全部读取出来,如果文本文件较大,容易导致内存溢出
# content = file_obj.read() # 读取文件返回给content
# help(file_obj.read()) # 查看read()帮助
content = file_obj.read(6) # 读取指定数量的字符,每一次读取都是从上一次读取到的位置开始读取。
print((content)) # 锄禾日当午
except FileNotFoundError:
print(f'{file_name} 文件不存在')
# 读取大文件,分块儿读取,即每一次读取指定数量的字符串,然后保存到一个变量中,
# 最后把每一次读取到的内容拼接起来就是整个完整的文件内容
file_name = 'demo2.txt'
try:
with open(file_name,encoding='utf-8') as file_obj:
# 定义一个变量来保存文件内容
file_content = ''
# 定义一个变量,来指定每次读取的大小
chunk = 6
# 创建一个循环来读取文件内容
while True:
# 读取 chunk 大小的内容
content = file_obj.read(chunk)
# 检查是否读取到了内容
if not content: # 当文件中没有内容读取时,返回为一个空字符串,空字符串会转换为False
# 内容读取完毕
break
# 输出内容
# print(content,end='')
file_content += content
except FileNotFoundError:
print(f'{file_name} 文件不存在')
print(file_content)
print('')
import pprint
file_name = 'demo2.txt'
with open(file_name,encoding='utf-8') as file_obj:
# readline() 可以用来读取一行内容
# print(file_obj.readline())
# print(file_obj.readline(),end='')
# print(file_obj.readline())
# readlines() 该方法用于一行一行的读取内容,它会将一次性读取的内容封装到一个列表中返回
# r = file_obj.readlines()
# pprint.pprint(r) # ['锄禾日当午\n', '汗滴禾下土\n', '谁知盘中餐\n', '粒粒皆辛苦']
# pprint.pprint(r[0]) # '锄禾日当午\n'
# 利用循环读取
for t in file_obj:
print(t)
文件的写入
file_name = 'demo.txt'
# 使用open() 打开文件时必须要制定打开文件所要做的操作
# 如果不指定操作类型,则默认时读取文件,而读取文件时不不能向文件中写入的。
# mode = r 表示读,w表示写,a 表示追加内容
# 使用w来写入文件时,如果文件不存在会创建文件,如果文件存在则会截断文件(删除原来文件中的所有内容)
with open(file_name,mode='wt',encoding='utf-8') as file_obj:
# write() 向文件中写入内容,如果操作的是文本文件,则需要传递一个字符串作为参数
file_obj.write('Hello,How are you\n') # \n 换行
# write() 可以分多次向文件中写入内容
file_obj.write('Hello,How are you')
# 写入完成以后,该方法会返回写入字符的个数
r = file_obj.write('今天天气真好呀')
print(r) # 7
# mode = 'a' 表示追加内容,如果文件存在则追加,不存在则新建文件
with open(file_name,mode='a',encoding='utf-8') as file_obj:
file_obj.write('这是追加的文字')
# mode = 'r+' 表示可读可写,文件不存在会报错
# 读取二进制文件(除了文本文件以外都是二进制文件)
# t 读取文本文件
# b 读取二进制文件
file_name_1 = 'jiuci.mp3'
with open(file_name_1,mode='rb') as file_obj_1:
# 读取文本文件时,size是以字符为单位的,读取二进制文件时,size是以字节为单位的
# print(file_obj_1.read(100))
# 将读取到的内容写出来
# 定义一个新的文件
new_name = 'new_jiuci'
with open(new_name,'wb') as new_obj:
# 定义每次读取的大小
ch = 1024 * 100
while True:
# 读取数据
content = file_obj_1.read(ch)
# 内容读取完毕终止循环
if not content:
break
# 将读取的数据写入到新对象中
new_obj.write(content)
文件的其他操作
# 删除文件
# 重命名文件
# 查看目录
import os # 模块使用方法详见官方文档
from pprint import pprint
# os.listdir() 获取指定目录结构
# 需要一个路径作为参数,回获取到该路径下的目录结构,默认路径为.(当前目录)
# 该方法会返回一个列表,目录中的每一个文件(夹)的名字都是列表中的一个元素
r = os.listdir()
pprint(r)
# os.getcwd() 获取当前所在的目录
r = os.getcwd()
pprint(r)
# os.chdir() 切换当前的目录
os.chdir('..')
r = os.getcwd()
pprint(r)
# 创建目录
os.mkdir('aaa') # 在当前目录下创建一个 aaa 目录
# 删除目录
os.rmdir('aaa')
# 创建文件
open('aaa.txt','w')
# 删除文件
os.remove('aaa.txt')
# 创建一个文件
open('abc.txt',mode='w')
# 重命名文件(两个参数第一个是原来文件所在的路径,第二个是重命名后文件所在路径)
os.rename('abc.txt','cba.txt') # 例如:实现文件移动功能 os.rename('abc.txt','C:\Users\Administrator\Desktop\cba.txt')
os.remove('cba.txt')
seek()tell()
with open('demo.txt','rb') as file_obj:
# print(file_obj.read()[0]) # 72
# print(file_obj.read(5))
# seek() 修改当前读取的位置
file_obj.seek(6) # 从第6个开始读,读5个
print(file_obj.read(5))
# seek() 需要两个参数
# 1、是要切换到的位置
# 2、计算位置:可选值 0(从头计算,默认值);1(从当前位置计算);2(从最后位置开始)
# tell() 方法用来查看当前读取的位置
print('当前读取到了',file_obj.tell())
with open('demo2.txt','rt',encoding='utf-8') as file_obj_1:
file_obj_1.seek(6) # 3个字节为一个汉字
print(file_obj_1.read())
print('当前位置在',file_obj_1.tell())
demo2.txt
锄禾日当午 汗滴禾下土 谁知盘中餐 粒粒皆辛苦
demo.txt
Hello,How are you Hello,How are you
待更......
python 从0-1笔记相关推荐
- Python基础语法学习笔记
Python基础语法学习笔记 想淘宝省钱看我简介,博客www.liangxin.name (一) 一.Print()函数 1.数字可以直接输出,无需加引号 只能理解数字,却读不懂文字.因为数字和数学运 ...
- Python基础教程学习笔记:第一章 基础知识
Python基础教程 第二版 学习笔记 1.python的每一个语句的后面可以添加分号也可以不添加分号:在一行有多条语句的时候,必须使用分号加以区分 2.查看Python版本号,在Dos窗口中输入&q ...
- python数据分析入门学习笔记儿
转载: http://www.cnblogs.com/zzhzhao/p/5269217.html 学习利用python进行数据分析的笔记儿&下星期二内部交流会要讲的内容,一并分享给大家.博主 ...
- Python 数据分析与展示笔记4 -- Pandas 库基础
Python 数据分析与展示笔记4 – Pandas 库基础 Python 数据分析与展示系列笔记是笔者学习.实践Python 数据分析与展示的相关笔记 课程链接: Python 数据分析与展示 参考 ...
- Python 数据分析与展示笔记3 -- Matplotlib 库基础
Python 数据分析与展示笔记3 – Matplotlib 库基础 Python 数据分析与展示系列笔记是笔者学习.实践Python 数据分析与展示的相关笔记 课程链接: Python 数据分析与展 ...
- Python 数据分析与展示笔记2 -- 图像手绘效果
Python 数据分析与展示笔记2 – 图像手绘效果 Python 数据分析与展示系列笔记是笔者学习.实践Python 数据分析与展示的相关笔记 课程链接: Python 数据分析与展示 参考文档: ...
- Python 数据分析与展示笔记1 -- Numpy 基础
Python 数据分析与展示笔记1 – NumPy 基础 Python 数据分析与展示系列笔记是笔者学习.实践Python 数据分析与展示的相关笔记 课程链接: Python 数据分析与展示 参考文档 ...
- Python GUI编程(Tkinter)笔记
Python GUI编程Tkinter笔记 1 显示任意格式图片 2 固定框架Frame大小 3 选择文件夹或文件 4 展示菜单栏 5 展示选择的图片 1 显示任意格式图片 Tkinter只支持显示G ...
- 过拟合解决方法python_《python深度学习》笔记---4.4、过拟合与欠拟合(解决过拟合常见方法)...
<python深度学习>笔记---4.4.过拟合与欠拟合(解决过拟合常见方法) 一.总结 一句话总结: 减小网络大小 添加权重正则化 添加 dropout 正则化 1.机器学习的根本问题? ...
- python基础入门学习笔记 (2)
python基础入门学习笔记 2021年2月8日 1 编译器和解释器的区别 编译器/解释器:高级语言与机器之间的翻译官 2 值传递: print "a = ",a print &q ...
最新文章
- linux 进入单用户模式修改root密码
- Android App压力测试(Monkey和ADB)
- Linux组管理和权限管理
- CSS中clear属性的both、left和right浅析
- Netbeans学习总结
- 【干货】Html与CSS入门学习笔记12-14【完】
- Codeforces Global Round 10
- 酒精测试仪检定设备设计与验证
- Openresty各个阶段的执行次序
- 详细讲解黑客常用的远程控制木马
- Datawhale组队学习周报(第026周)
- Oracle_登录数据库系统
- 求助:大文件mp4恢复
- conda离线安装包
- 【自然语言处理】Gensim中的Word2Vec
- [Vuforia] 详解·高通Vuforia识别追踪3D物体/模型,Unity开发
- MYSQL练习题:连续两天登录的游戏玩家比率
- Mac M1 python 连点器脚本
- matlab中估计丢失的数据,空间计量经济学基本模型的matlab估计
- (附源码)计算机毕业设计SSM智能导诊系统