变量
数据都是临时存储在内存中,为了更快速的查找或使用这个数据,通常我们把这个数据在内存中存储之后定义一个名称,这个名称就是变量。
变量就是一个存储数据的时候当前数据所在的内存地址的名字而已。
定义变量:
变量名 = 值
my_name = 'TOM'
print(my_name)#TOM
数据类型
数据类型
- 整型:int
- 浮点型:float
- 字符串:str
- 布尔型:bool
- 列表:list
- 元组:tuple
- 集合:set
- 字典:dict
检测数据类型的方法:
type()
a = 1
print(type(a)) # <class 'int'> -- 整型
b = 1.1
print(type(b)) # <class 'float'> -- 浮点型
c = True
print(type(c)) # <class 'bool'> -- 布尔型
d = '12345'
print(type(d)) # <class 'str'> -- 字符串
e = [10, 20, 30]
print(type(e)) # <class 'list'> -- 列表
f = (10, 20, 30)
print(type(f)) # <class 'tuple'> -- 元组
h = {10, 20, 30}
print(type(h)) # <class 'set'> -- 集合
g = {'name': 'TOM', 'age': 20}
print(type(g)) # <class 'dict'> -- 字典
输出
格式符号 | 转换 |
---|---|
%s | 字符串 |
%d | 有符号的十进制整数 |
%f | 浮点数 |
%c | 字符 |
%u | 无符号十进制整数 |
%o | 八进制整数 |
%x | 十六进制整数(小写ox) |
%X | 十六进制整数(大写OX) |
%e | 科学计数法(小写’e’) |
%E | 科学计数法(大写’E’) |
%g | %f和%e的简写 |
%G | %f和%E的简写 |
技巧
%06d,表示输出的整数显示位数,不足以0补全,超出当前位数则原样输出
%.2f,表示小数点后显示的小数位数。
格式化字符串除了%s,还可以写为
f'{表达式}'
age = 18 name = 'TOM' weight = 75.5 student_id = 1 # 我的名字是TOM print('我的名字是%s' % name) # 我的学号是0001 print('我的学号是%4d' % student_id) # 我的体重是75.50公斤 print('我的体重是%.2f公斤' % weight) # 我的名字是TOM,明年19岁了 print('我的名字是%s,明年%d岁了' % (name, age + 1)) # 我的名字是TOM,明年19岁了 print(f'我的名字是{name}, 明年{age + 1}岁了')
输入
input("提示信息")
在Python中,input
会把接收到的任意用户输入的数据都当做字符串处理。
password = input('请输入您的密码:')
print(f'您输入的密码是{password}')
# <class 'str'>
print(type(password))
转换数据类型
函数 | 说明 |
---|---|
int(x [,base ]) | 将x转换为一个整数 |
float(x) | 将x转换为一个浮点数 |
complex(real [,imag ]) | 创建一个复数,real为实部,imag为虚部 |
str(x ) | 将对象 x 转换为字符串 |
repr(x ) | 将对象 x 转换为表达式字符串 |
eval(str ) | 用来计算在字符串中的有效Python表达式,并返回一个对象 |
tuple(s ) | 将序列 s 转换为一个元组 |
list(s ) | 将序列 s 转换为一个列表 |
chr(x ) | 将一个整数转换为一个Unicode字符 |
ord(x ) | 将一个字符转换为它的ASCII整数值 |
hex(x ) | 将一个整数转换为一个十六进制字符串 |
oct(x ) | 将一个整数转换为一个八进制字符串 |
bin(x ) | 将一个整数转换为一个二进制字符串 |
# 1. float() -- 转换成浮点型
num1 = 1
print(float(num1))
print(type(float(num1)))
# 2. str() -- 转换成字符串类型
num2 = 10
print(type(str(num2)))
# 3. tuple() -- 将一个序列转换成元组
list1 = [10, 20, 30]
print(tuple(list1))
print(type(tuple(list1)))
# 4. list() -- 将一个序列转换成列表
t1 = (100, 200, 300)
print(list(t1))
print(type(list(t1)))
# 5. eval() -- 将字符串中的数据转换成Python表达式原本类型
str1 = '10'
str2 = '[1, 2, 3]'
str3 = '(1000, 2000, 3000)'
print(type(eval(str1)))
print(type(eval(str2)))
print(type(eval(str3)))
运算符
运算符 | 描述 | 实例 |
---|---|---|
+ | 加 | 1 + 1 输出结果为 2 |
- | 减 | 1-1 输出结果为 0 |
* | 乘 | 2 * 2 输出结果为 4 |
/ | 除 | 10 / 2 输出结果为 5 |
// | 整除 | 9 // 4 输出结果为2 |
% | 取余 | 9 % 4 输出结果为 1 |
** | 指数 | 2 ** 4 输出结果为 16,即 2 * 2 * 2 * 2 |
() | 小括号 | 小括号用来提高运算优先级,即 (1 + 2) * 3 输出结果为 9 |
多个变量赋值
num1, float1, str1 = 10, 0.5, 'hello world'
print(num1)
print(float1)
print(str1)
多变量赋相同值
a = b = 10
print(a)
print(b)
运算符 | 逻辑表达式 | 描述 | 实例 |
---|---|---|---|
and | x and y | 布尔”与”:如果 x 为 False,x and y 返回 False,否则它返回 y 的值。 | True and False, 返回 False。 |
or | x or y | 布尔”或”:如果 x 是 True,它返回 True,否则它返回 y 的值。 | False or True, 返回 True。 |
not | not x | 布尔”非”:如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。 | not True 返回 False, not False 返回 True |
数字之间的逻辑运算
a = 0
b = 1
c = 2
# and运算符,只要有一个值为0,则结果为0,否则结果为最后一个非0数字
print(a and b) # 0
print(b and a) # 0
print(b and c) # 2
print(c and b) # 1
# or运算符,只有所有值为0结果才为0,否则结果为第一个非0数字
print(a or b) # 1
print(a or c) # 2
print(b or c) # 1
if语句
基本使用
语法:
if 条件1:
代码...
......
elif 条件2:
代码
......
......
else:
以上条件都不成立执行执行的代码
实例:
age = int(input('请输入您的年龄:'))
if age < 18:
print(f'您的年龄是{age},童工一枚')
elif (age >= 18) and (age <= 60):
print(f'您的年龄是{age},合法工龄')
elif age > 60:
print(f'您的年龄是{age},可以退休')
猜拳游戏
# 导入random模块
import random
# 计算电脑出拳的随机数字
computer = random.randint(0, 2)
print(computer)
player = int(input('请出拳:0-石头,1-剪刀,2-布:'))
# 玩家胜利 p0:c1 或 p1:c2 或 p2:c0
if (player == 0 and computer == 1) or (player == 1 and computer == 2) or (player == 2 and computer == 0):
print('玩家获胜')
# 平局:玩家 == 电脑
elif player == computer:
print('平局')
else:
print('电脑获胜')
三元运算符
语法:
值1 if 条件 else 值2
a = 1
b = 2
c = a if a > b else b
print(c)
循环
while
while的语法
while 条件:
代码
......
计算1-100累加和:
i = 1
result = 0
while i <= 100:
result += i
i += 1
print(result)#5050
for循环
语法
for 临时变量 in 序列:
代码
......
使用
str1 = 'HelloWorld'
for i in str1:
print(i)
while…else
语法
while 条件:
代码
else:
循环正常结束之后要执行的代码
所谓else指的是循环正常结束之后要执行的代码,即如果是break终止循环的情况,else下方缩进的代码将不执行。
因为continue是退出当前一次循环,继续下一次循环,所以该循环在continue控制下是可以正常结束的,当循环结束后,则执行了else缩进的代码。
for…else
语法
for 临时变量 in 序列:
代码
...
else:
循环正常结束之后要执行的代码
break终止循环不会执行else下方缩进的代码。continue退出循环的方式,执行else下方缩进的代码。
字符串
三引号字符串
name3 = ''' Tom '''
name4 = """ Rose """
a = ''' i am Tom,
nice to meet you! '''
b = """ i am Rose,
nice to meet you! """
注意:三引号形式的字符串支持换行。
切片
注意:字符串下标从0开始。
切片语法
序列[开始位置下标:结束位置下标:步长]
注意:不包含结束位置下标对应的数据, 正负整数均可;步长是选取间隔,正负整数均可,默认步长为1。
name = "abcdefg"
print(name[2:5:1]) # cde
print(name[2:5]) # cde
print(name[:5]) # abcde
print(name[1:]) # bcdefg
print(name[:]) # abcdefg
print(name[::2]) # aceg
print(name[:-1]) # abcdef, 负1表示倒数第一个数据
print(name[-4:-1]) # def
print(name[::-1]) # gfedcba
find
检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则返回-1。
#开始和结束位置下标可以省略,表示在整个字符串序列中查找
字符串序列.find(子串, 开始位置下标, 结束位置下标)
mystr = "hello world and Python"
print(mystr.find('and')) # 12
print(mystr.find('and', 15, 30)) # -1
print(mystr.find('ands')) # -1
rfind()和find()功能相同,但查找方向为右侧开始。
index
检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则报异常。
#开始和结束位置下标可以省略,表示在整个字符串序列中查找。
字符串序列.index(子串, 开始位置下标, 结束位置下标)
mystr = "hello world and Python"
print(mystr.index('and')) # 12
print(mystr.index('ands')) # 报错
rindex()index()功能相同,但查找方向为右侧开始。
count
返回某个子串在字符串中出现的次数。
#开始和结束位置下标可以省略,表示在整个字符串序列中查找。
字符串序列.count(子串, 开始位置下标, 结束位置下标)
mystr = "hello world and Python"
print(mystr.count('and')) # 1
print(mystr.count('ands')) # 0
replace
替换
#替换次数如果查出子串出现次数,则替换次数为该子串出现次数。
字符串序列.replace(旧子串, 新子串, 替换次数)
mystr = "hello world and Python and"
# 结果:hello world he Python he
print(mystr.replace('and', 'he'))
# 结果:hello world he Python he
print(mystr.replace('and', 'he', 10))
# 结果:hello world and Python and
print(mystr)
注意:数据按照是否能直接修改分为可变类型和不可变类型两种。字符串类型的数据修改的时候不能改变原有字符串,属于不能直接修改数据的类型即是不可变类型。
split
按照指定字符分割字符串。
字符串序列.split(分割字符, num)
注意:num表示的是分割字符出现的次数,即将来返回数据个数为num+1个。
mystr = "hello world and Python and it"
# ['hello world ', ' Python ', ' it']
print(mystr.split('and'))
# ['hello world ', ' Python ', ' it']
print(mystr.split('and', 2))
# ['hello', 'world', 'and', 'Python', 'and', 'it']
print(mystr.split(' '))
# ['hello', 'world', 'and Python and it']
print(mystr.split(' ', 2))
注意:如果分割字符是原有字符串中的子串,分割后则丢失该子串。
join
用一个字符或子串合并字符串,即是将多个字符串合并为一个新的字符串。
字符或子串.join(多字符串组成的序列)
list1 = ['mm', 'nn', 'bb', 'vv']
t1 = ('aa', 'b', 'cc', 'ddd')
# 结果:mm_nn_bb_vv
print('_'.join(list1))
# 结果:aa...b...cc...ddd
print('...'.join(t1))
capitalize
将字符串第一个字符转换成大写。
mystr = "hello world and Python and it"
# 结果:Hello world and python and it
print(mystr.capitalize())
注意:capitalize()函数转换后,只字符串第一个字符大写,其他的字符全都小写。
title
将字符串每个单词首字母转换成大写。
mystr = "hello world and Python and it"
# 结果:Hello World And Python And It
print(mystr.title())
lower和upper
lower():将字符串中大写转小写。
mystr = "hello world and Python and it"
# 结果:hello world and python and it
print(mystr.lower())
upper():将字符串中小写转大写。
mystr = "hello world and Python and it"
# 结果:HELLO WORLD AND PYTHON AND IT
print(mystr.upper())
lstrip和rstrip和strip
lstrip():删除字符串左侧空白字符。
rstrip():删除字符串右侧空白字符。
strip():删除字符串两侧空白字符。
ljust和rjust和center
ljust():返回一个原字符串左对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串。
rjust():返回一个原字符串右对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串,语法和ljust()相同。
center():返回一个原字符串居中对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串,语法和ljust()相同。
mystr = "hello world and Python and it"
# 结果:hello world and Python and it.......
print(mystr.ljust(36,'.'))
# 结果:.......hello world and Python and it
print(mystr.rjust(36,'.'))
# 结果:...hello world and Python and it....
print(mystr.center(36,'.'))
startswith和endswith
startswith():检查字符串是否是以指定子串开头,是则返回True,否则返回False。如果设置开始和结束位置下标,则在指定范围内检查。
字符串序列.startswith(子串, 开始位置下标, 结束位置下标)
mystr = "hello world and Python and it"
# 结果:True
print(mystr.startswith('hello'))
# 结果False
print(mystr.startswith('hello', 5, 20))
endswith():检查字符串是否是以指定子串结尾,是则返回True,否则返回False。如果设置开始和结束位置下标,则在指定范围内检查。
字符串序列.endswith(子串, 开始位置下标, 结束位置下标)
mystr = "hello world and Python and it"
# 结果:True
print(mystr.endswith('it'))
# 结果:False
print(mystr.endswith('Python', 2, 20))
isalpha
如果字符串至少有一个字符并且所有字符都是字母则返回True, 否则返回 False。
mystr1 = 'hello'
mystr2 = 'hello12345'
# 结果:True
print(mystr1.isalpha())
# 结果:False
print(mystr2.isalpha())
isdigit
如果字符串只包含数字则返回True否则返回 False。
mystr1 = 'aaa12345'
mystr2 = '12345'
# 结果: False
print(mystr1.isdigit())
# 结果:False
print(mystr2.isdigit())
isalnum
如果字符串至少有一个字符并且所有字符都是字母或数字则返回True,否则返回False。
mystr1 = 'aaa12345'
mystr2 = '12345-'
# 结果:True
print(mystr1.isalnum())
# 结果:False
print(mystr2.isalnum())
isspace
如果字符串中只包含空白,则返回True,否则返回False。
mystr1 = '1 2 3 4 5'
mystr2 = ' '
# 结果:False
print(mystr1.isspace())
# 结果:True
print(mystr2.isspace())
列表
列表可以一次性存储多个数据,且可以为不同数据类型。可以对这些数据进行的操作有:增、删、改、查。
下标
name_list = ['Tom', 'Lily', 'Rose']
print(name_list[0]) # Tom
print(name_list[1]) # Lily
print(name_list[2]) # Rose
index
返回指定数据所在位置的下标 。
列表序列.index(数据, 开始位置下标, 结束位置下标)
name_list = ['Tom', 'Lily', 'Rose']
print(name_list.index('Lily', 0, 2)) # 1
注意:如果查找的数据不存在则报错。
count
统计指定数据在当前列表中出现的次数。
name_list = ['Tom', 'Lily', 'Rose']
print(name_list.count('Lily')) # 1
len
访问列表长度,即列表中数据的个数。
name_list = ['Tom', 'Lily', 'Rose']
print(len(name_list)) # 3
in和not in
in:判断指定数据在某个列表序列,如果在返回True,否则返回False
name_list = ['Tom', 'Lily', 'Rose']
# 结果:True
print('Lily' in name_list)
# 结果:False
print('Lilys' in name_list)
not in:判断指定数据不在某个列表序列,如果不在返回True,否则返回False
name_list = ['Tom', 'Lily', 'Rose']
# 结果:False
print('Lily' not in name_list)
# 结果:True
print('Lilys' not in name_list)
append
列表结尾追加数据。
列表序列.append(数据)
name_list = ['Tom', 'Lily', 'Rose']
name_list.append('xiaoming')
# 结果:['Tom', 'Lily', 'Rose', 'xiaoming']
print(name_list)
列表追加数据的时候,直接在原列表里面追加了指定数据,即修改了原列表,故列表为可变类型数据。
如果append()追加的数据是一个序列,则追加整个序列到列表
name_list = ['Tom', 'Lily', 'Rose']
name_list.append(['xiaoming', 'xiaohong'])
# 结果:['Tom', 'Lily', 'Rose', ['xiaoming', 'xiaohong']]
print(name_list)
extend
列表结尾追加数据,如果数据是一个序列,则将这个序列的数据逐一添加到列表。
列表序列.extend(数据)
#单个数据
name_list = ['Tom', 'Lily', 'Rose']
name_list.extend('xiaoming')
# 结果:['Tom', 'Lily', 'Rose', 'x', 'i', 'a', 'o', 'm', 'i', 'n', 'g']
print(name_list)
#序列数据
name_list = ['Tom', 'Lily', 'Rose']
name_list.extend(['xiaoming', 'xiaohong'])
# 结果:['Tom', 'Lily', 'Rose', 'xiaoming', 'xiaohong']
print(name_list)
insert
指定位置新增数据。
列表序列.insert(位置下标, 数据)
name_list = ['Tom', 'Lily', 'Rose']
name_list.insert(1, 'xiaoming')
# 结果:['Tom', 'xiaoming', 'Lily', 'Rose']
print(name_list)
del
#del 目标
name_list = ['Tom', 'Lily', 'Rose']
# 结果:报错提示:name 'name_list' is not defined
del name_list
print(name_list)
#删除指定数据
name_list = ['Tom', 'Lily', 'Rose']
del name_list[0]
# 结果:['Lily', 'Rose']
print(name_list)
pop
删除指定下标的数据(默认为最后一个),并返回该数据。
#列表序列.pop(下标)
name_list = ['Tom', 'Lily', 'Rose']
del_name = name_list.pop(1)
# 结果:Lily
print(del_name)
# 结果:['Tom', 'Rose']
print(name_list)
remove
移除列表中某个数据的第一个匹配项。
#列表序列.remove(数据)
name_list = ['Tom', 'Lily', 'Rose']
name_list.remove('Rose')
# 结果:['Tom', 'Lily']
print(name_list)
clear
清空列表
name_list = ['Tom', 'Lily', 'Rose']
name_list.clear()
print(name_list) # 结果: []
修改指定下标数据
name_list = ['Tom', 'Lily', 'Rose']
name_list[0] = 'aaa'
# 结果:['aaa', 'Lily', 'Rose']
print(name_list)
逆置reverse
num_list = [1, 5, 2, 3, 6, 8]
num_list.reverse()
# 结果:[8, 6, 3, 2, 5, 1]
print(num_list)
排序sort
列表序列.sort( key=None, reverse=False)
注意:reverse表示排序规则,reverse = True 降序, reverse = False 升序(默认)
num_list = [1, 5, 2, 3, 6, 8]
num_list.sort()
# 结果:[1, 2, 3, 5, 6, 8]
print(num_list)
复制copy
name_list = ['Tom', 'Lily', 'Rose']
name_li2 = name_list.copy()
# 结果:['Tom', 'Lily', 'Rose']
print(name_li2)
while遍历列表
name_list = ['Tom', 'Lily', 'Rose']
i = 0
while i < len(name_list):
print(name_list[i])
i += 1
for遍历列表
name_list = ['Tom', 'Lily', 'Rose']
for i in name_list:
print(i)
元组
一个元组可以存储多个数据,元组内的数据是不能修改的。元组特点:定义元组使用小括号,且逗号隔开各个数据,数据可以是不同的数据类型。
#多个数据元组
t1 = (10, 20, 30)
#单个数据元组
t2 = (10,)
print(type(t2)) # tuple
t3 = (20)
print(type(t3)) # int
注意:如果定义的元组只有一个数据,那么这个数据后面也要添加逗号,否则数据类型为唯一的这个数据的数据类型。
按下标查找数据
tuple1 = ('aa', 'bb', 'cc', 'bb')
print(tuple1[0]) # aa
index():查找某个数据,如果数据存在返回对应的下标,否则报错,语法和列表、字符串的index方法相同。
tuple1 = ('aa', 'bb', 'cc', 'bb')
print(tuple1.index('aa')) # 0
count():统计某个数据在当前元组出现的次数。
tuple1 = ('aa', 'bb', 'cc', 'bb')
print(tuple1.count('bb')) # 2
len():统计元组中数据的个数。
tuple1 = ('aa', 'bb', 'cc', 'bb')
print(len(tuple1)) # 4
注意:元组内的直接数据如果修改则立即报错
但是如果元组里面有列表,修改列表里面的数据则是支持的,故自觉很重要。
tuple2 = (10, 20, ['aa', 'bb', 'cc'], 50, 30)
print(tuple2[2]) # 访问到列表
# 结果:(10, 20, ['aaaaa', 'bb', 'cc'], 50, 30)
tuple2[2][0] = 'aaaaa'
print(tuple2)
字典
字典里面的数据是以键值对形式出现,字典数据和数据顺序没有关系,即字典不支持下标,后期无论数据如何变化,只需要按照对应的键的名字查找数据即可。
字典特点:符号为大括号;数据为键值对形式出现;各个键值对之间用逗号隔开。
# 有数据字典
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
# 空字典
dict2 = {}
一般称冒号前面的为键(key),简称k;冒号后面的为值(value),简称v。
增和改
写法:字典序列[key] = 值
注意:如果key存在则修改这个key对应的值;如果key不存在则新增此键值对。
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
dict1['name'] = 'Rose'
# 结果:{'name': 'Rose', 'age': 20, 'gender': '男'}
print(dict1)
dict1['id'] = 110
# {'name': 'Rose', 'age': 20, 'gender': '男', 'id': 110}
print(dict1)
注意:字典为可变类型。
删
del()/del:删除字典或删除字典中指定键值对。
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
del dict1['gender']
# 结果:{'name': 'Tom', 'age': 20}
print(dict1)
clear():清空字典
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
dict1.clear()
print(dict1) # {}
key值查找
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
print(dict1['name']) # Tom
print(dict1['id']) # 报错
如果当前查找的key存在,则返回对应的值;否则则报错。
get
字典序列.get(key, 默认值)
注意:如果当前查找的key不存在则返回第二个参数(默认值),如果省略第二个参数,则返回None。
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
print(dict1.get('name')) # Tom
print(dict1.get('id', 110)) # 110
print(dict1.get('id')) # None
keys
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
print(dict1.keys()) # dict_keys(['name', 'age', 'gender'])
values
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
print(dict1.values()) # dict_values(['Tom', 20, '男'])
items
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
print(dict1.items()) # dict_items([('name', 'Tom'), ('age', 20), ('gender', '男')])
遍历字典的key
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for key in dict1.keys():
print(key)
遍历字典的value
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for value in dict1.values():
print(value)
遍历字典的元素
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for item in dict1.items():
print(item)
遍历字典的键值对
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}
for key, value in dict1.items():
print(f'{key} = {value}')
集合
创建集合使用{}
或set()
,但是如果要创建空集合只能使用set()
,因为{}
用来创建空字典。
s1 = {10, 20, 30, 40, 50}
print(s1)#{40, 10, 50, 20, 30}
s2 = {10, 30, 20, 10, 30, 40, 30, 50}
print(s2)#{40, 10, 50, 20, 30}
s3 = set('abcdefg')
print(s3)
s4 = set()
print(type(s4)) # set
s5 = {}
print(type(s5)) # dict
特点:集合可以去掉重复数据;集合数据是无序的,故不支持下标。
增加数据
add()
s1 = {10, 20}
s1.add(100)
s1.add(10)
print(s1) # {100, 10, 20}
因为集合有去重功能,所以,当向集合内追加的数据是当前集合已有数据的话,则不进行任何操作。
update(), 追加的数据是序列。
s1 = {10, 20}
# s1.update(100) # 报错
s1.update([100, 200])
s1.update('abc')
print(s1)
删除数据
remove(),删除集合中的指定数据,如果数据不存在则报错。
s1 = {10, 20}
s1.remove(10)
print(s1)
s1.remove(10) # 报错
print(s1)
discard(),删除集合中的指定数据,如果数据不存在也不会报错。
s1 = {10, 20}
s1.discard(10)
print(s1)
s1.discard(10)
print(s1)
pop(),随机删除集合中的某个数据,并返回这个数据。
s1 = {10, 20, 30, 40, 50}
del_num = s1.pop()
print(del_num)
print(s1)
查找数据
in:判断数据在集合序列。not in:判断数据不在集合序列
s1 = {10, 20, 30, 40, 50}
print(10 in s1)
print(10 not in s1)
公共操作
运算符
运算符 | 描述 | 支持的容器类型 |
---|---|---|
+ | 合并 | 字符串、列表、元组 |
* | 复制 | 字符串、列表、元组 |
in | 元素是否存在 | 字符串、列表、元组、字典 |
not in | 元素是否不存在 | 字符串、列表、元组、字典 |
+
:
# 1. 字符串
str1 = 'aa'
str2 = 'bb'
str3 = str1 + str2
print(str3) # aabb
# 2. 列表
list1 = [1, 2]
list2 = [10, 20]
list3 = list1 + list2
print(list3) # [1, 2, 10, 20]
# 3. 元组
t1 = (1, 2)
t2 = (10, 20)
t3 = t1 + t2
print(t3) #(1, 2, 10, 20)
*
:
# 1. 字符串
print('-' * 10) # ----------
# 2. 列表
list1 = ['hello']
print(list1 * 4) # ['hello', 'hello', 'hello', 'hello']
# 3. 元组
t1 = ('world',)
print(t1 * 4) # ('world', 'world', 'world', 'world')
in
或not in
:
# 1. 字符串
print('a' in 'abcd') # True
print('a' not in 'abcd') # False
# 2. 列表
list1 = ['a', 'b', 'c', 'd']
print('a' in list1) # True
print('a' not in list1) # False
# 3. 元组
t1 = ('a', 'b', 'c', 'd')
print('aa' in t1) # False
print('aa' not in t1) # True
公共方法
函数 | 描述 |
---|---|
len() | 计算容器中元素个数 |
del 或 del() | 删除 |
max() | 返回容器中元素最大值 |
min() | 返回容器中元素最小值 |
range(start, end, step) | 生成从start到end的数字,步长为 step,供for循环使用 |
enumerate() | 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。 |
len()
# 1. 字符串
str1 = 'abcdefg'
print(len(str1)) # 7
# 2. 列表
list1 = [10, 20, 30, 40]
print(len(list1)) # 4
# 3. 元组
t1 = (10, 20, 30, 40, 50)
print(len(t1)) # 5
# 4. 集合
s1 = {10, 20, 30}
print(len(s1)) # 3
# 5. 字典
dict1 = {'name': 'Rose', 'age': 18}
print(len(dict1)) # 2
del()
# 1. 字符串
str1 = 'abcdefg'
del str1
print(str1)#error
# 2. 列表
list1 = [10, 20, 30, 40]
del(list1[0])
print(list1) # [20, 30, 40]
max()
# 1. 字符串
str1 = 'abcdefg'
print(max(str1)) # g
# 2. 列表
list1 = [10, 20, 30, 40]
print(max(list1)) # 40
min()
# 1. 字符串
str1 = 'abcdefg'
print(min(str1)) # a
# 2. 列表
list1 = [10, 20, 30, 40]
print(min(list1)) # 10
range()
# 1 2 3 4 5 6 7 8 9
for i in range(1, 10, 1):
print(i)
# 1 3 5 7 9
for i in range(1, 10, 2):
print(i)
# 0 1 2 3 4 5 6 7 8 9
for i in range(10):
print(i)
注意:range()生成的序列不包含end数字。
enumerate()
enumerate(可遍历对象, start=0)
注意:start参数用来设置遍历数据的下标的起始值,默认为0。
list1 = ['a', 'b', 'c', 'd', 'e']
for i in enumerate(list1):
print(i)#(0, 'a')(1, 'b')(2, 'c')(4, 'e')
for index, char in enumerate(list1, start=1):
print(f'下标是{index}, 对应的字符是{char}')#下标是1, 对应的字符是a...
容器类型转换
tuple():将某个序列转换成元组
list1 = [10, 20, 30, 40, 50, 20]
s1 = {100, 200, 300, 400, 500}
print(tuple(list1))#(10, 20, 30, 40, 50, 20)
print(tuple(s1))#(100, 200, 300, 400, 500)
list():将某个序列转换成列表
t1 = ('a', 'b', 'c', 'd', 'e')
s1 = {100, 200, 300, 400, 500}
print(list(t1))#['a', 'b', 'c', 'd', 'e']
print(list(s1))#[100, 200, 300, 400, 500]
set():将某个序列转换成集合
list1 = [10, 20, 30, 40, 50, 20]
t1 = ('a', 'b', 'c', 'd', 'e')
print(set(list1))#{40, 10, 50, 20, 30}
print(set(t1))#{'c', 'd', 'a', 'b', 'e'}
注意:集合可以快速完成列表去重;集合不支持下标
推导式
列表推导式
用一个表达式创建一个有规律的列表或控制一个有规律列表。列表推导式又叫列表生成式。
创建一个0-10的列表。
#while循环实现
# 1. 准备一个空列表
list1 = []
# 2. 书写循环,依次追加数字到空列表list1中
i = 0
while i < 10:
list1.append(i)
i += 1
print(list1)
#for循环实现
list1 = []
for i in range(10):
list1.append(i)
print(list1)
#列表推导式实现
list1 = [i for i in range(10)]
print(list1)
带if的列表推导式
创建0-10的偶数列表:
#range()步长实现
list1 = [i for i in range(0, 10, 2)]
print(list1)
#if实现
list1 = [i for i in range(10) if i % 2 == 0]
print(list1)
多个for循环实现列表推导式
创建列表如下:
[(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
代码如下:
list1 = [(i, j) for i in range(1, 3) for j in range(3)]
print(list1)
字典推导式
如下两个列表,如何快速合并为一个字典?
list1 = ['name', 'age', 'gender']
list2 = ['Tom', 20, 'man']
字典推导式作用:快速合并列表为字典或提取字典中目标数据。
创建一个字典:字典key是1-5数字,value是这个数字的2次方:
dict1 = {i: i**2 for i in range(1, 5)}
print(dict1) # {1: 1, 2: 4, 3: 9, 4: 16}
将两个列表合并为一个字典:
list1 = ['name', 'age', 'gender']
list2 = ['Tom', 20, 'man']
dict1 = {list1[i]: list2[i] for i in range(len(list1))}
print(dict1)
提取字典中目标数据
counts = {'MBP': 268, 'HP': 125, 'DELL': 201, 'Lenovo': 199, 'acer': 99}
# 需求:提取上述电脑数量大于等于200的字典数据
count1 = {key: value for key, value in counts.items() if value >= 200}
print(count1) # {'MBP': 268, 'DELL': 201}
集合推导式
创建一个集合,数据为下方列表的2次方。
list1 = [1, 1, 2]
代码如下:
list1 = [1, 1, 2]
set1 = {i ** 2 for i in list1}
print(set1) # {1, 4}
注意:集合有数据去重功能。
函数基础
函数就是将一段具有独立功能的代码块整合到一个整体并命名,在需要的位置调用这个名称即可完成对应的需求。函数在开发过程中,可以更高效的实现代码重用。
定义函数:
def 函数名(参数):
代码1
代码2
......
调用函数
函数名(参数)
注意:不同的需求,参数可有可无。在Python中,函数必须先定义后使用。一定是先定义函数,后调用函数。
代码
def sum_num(a, b):
return a + b
# 用result变量保存函数返回值
result = sum_num(1, 2)
print(result)
函数的说明文档help(函数名)
def sum_num(a, b):
""" 求和函数 """
return a + b
help(sum_num)
函数提高
变量作用域
变量作用域指的是变量生效的范围,主要分为两类:局部变量和全局变量。
局部变量:定义在函数体内部的变量,即只在函数体内部生效。局部变量的作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量。
全局变量:指的是在函数体内、外都能生效的变量。
a = 100
def testA():
print(a)
def testB():
a = 200
print(a)
testA() # 100
testB() # 200
print(f'全局变量a = {a}') # 全局变量a = 100
在testB
函数内部的a = 200
中的变量a是在修改全局变量a
吗?不是。testB
函数内部的a = 200
是定义了一个局部变量。
如何在函数体内部修改全局变量?
a = 100
def testA():
print(a)
def testB():
# global 关键字声明a是全局变量
global a
a = 200
print(a)
testA() # 100
testB() # 200
print(f'全局变量a = {a}') # 全局变量a = 200
函数的返回值
如果一个函数要有多个返回值,该如何书写代码?
def return_num():
return 1, 2
result = return_num()
print(result) # (1, 2)
注意:
return a, b
写法,返回多个数据的时候,默认是元组类型。return后面可以连接列表、元组或字典,以返回多个值。
参数
位置参数:调用函数时根据函数定义的参数位置来传递参数。
def user_info(name, age, gender):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info('TOM', 20, '男')
注意:传递和定义参数的顺序及个数必须一致。
关键字参数:函数调用,通过“键=值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。
def user_info(name, age, gender):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info('Rose', age=20, gender='女')
user_info('小明', gender='男', age=16)
注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序。
缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)。
def user_info(name, age, gender='男'):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info('TOM', 20)
user_info('Rose', 18, '女')
不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便。
def user_info(*args):
print(args)
# ('TOM',)
user_info('TOM')
# ('TOM', 18)
user_info('TOM', 18)
注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递。
包裹关键字传递
def user_info(**kwargs):
print(kwargs)
# {'name': 'TOM', 'age': 18, 'id': 110}
user_info(name='TOM', age=18, id=110)
综上:无论是包裹位置传递还是包裹关键字传递,都是一个组包的过程。
拆包和交换变量值
拆包:元组
def return_num():
return 100, 200
num1, num2 = return_num()
print(num1) # 100
print(num2) # 200
拆包:字典
dict1 = {'name': 'TOM', 'age': 18}
a, b = dict1
# 对字典进行拆包,取出来的是字典的key
print(a) # name
print(b) # age
print(dict1[a]) # TOM
print(dict1[b]) # 18
交换变量值
交换两个变量的值。借助第三变量存储数据。
# 1. 定义中间变量
c = 0
# 2. 将a的数据存储到c
c = a
# 3. 将b的数据20赋值到a,此时a = 20
a = b
#4. 将之前c的数据10赋值到b,此时b = 10
b = c
print(a) # 20
print(b) # 10
交换两个变量的值。方法二
a, b = 1, 2
a, b = b, a
print(a) # 2
print(b) # 1
引用
在python中,值是靠引用来传递来的。我们可以用id()
来判断两个变量是否为同一个值的引用。 我们可以将id值理解为那块内存的地址标识。
# 1. int类型
a = 1
b = a
print(b) # 1
print(id(a)) # 140708464157520
print(id(b)) # 140708464157520
a = 2
print(b) # 1,说明int类型为不可变类型
print(id(a)) # 140708464157552,此时得到是的数据2的内存地址
print(id(b)) # 140708464157520
# 2. 列表
aa = [10, 20]
bb = aa
print(id(aa)) # 2325297783432
print(id(bb)) # 2325297783432
aa.append(30)
print(bb) # [10, 20, 30], 列表为可变类型
print(id(aa)) # 2325297783432
print(id(bb)) # 2325297783432
引用当做实参,代码如下:
def test1(a):
print(a)
print(id(a))
a += a
print(a)
print(id(a))
# int:计算前后id值不同
b = 100
test1(b)
# 列表:计算前后id值相同
c = [11, 22]
test1(c)
可变和不可变类型
所谓可变类型与不可变类型是指:数据能够直接进行修改,如果能直接修改那么就是可变,否则是不可变。
可变类型:列表、字典、集合。
不可变类型:整型、浮点型、字符串、元组。
递归
3以内数字累加和
# 3 + 2 + 1
def sum_numbers(num):
# 1.如果是1,直接返回1 -- 出口
if num == 1:
return 1
# 2.如果不是1,重复执行累加并返回结果
return num + sum_numbers(num-1)
sum_result = sum_numbers(3)
# 输出结果为6
print(sum_result)
lambda表达式
如果一个函数有一个返回值,并且只有一句代码,可以使用lambda简化。
lambda语法
lambda 参数列表 : 表达式
注意:lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用。lambda表达式能接收任何数量的参数但只能返回一个表达式的值。
# 函数
def fn1():
return 200
print(fn1)
print(fn1())
# lambda表达式,无参数
fn2 = lambda: 100
print(fn2)
print(fn2())
注意:直接打印lambda表达式,输出的是此lambda的内存地址
计算a + b
def add(a, b):
return a + b
result = add(1, 2)
print(result)
#lambda实现,有参数
fn1 = lambda a, b: a + b
print(fn1(1, 2))
lambda的参数形式,默认参数
fn1 = lambda a, b, c=100: a + b + c
print(fn1(10, 20))
可变参数:*args
fn1 = lambda *args: args
print(fn1(10, 20, 30))
注意:这里的可变参数传入到lambda之后,返回值为元组。
可变参数:**kwargs
fn1 = lambda **kwargs: kwargs
print(fn1(name='python', age=20))
lambda的应用,带判断的lambda
fn1 = lambda a, b: a if a > b else b
print(fn1(1000, 500))
lambda的应用,列表数据按字典key的值排序
students = [
{'name': 'TOM', 'age': 20},
{'name': 'ROSE', 'age': 19},
{'name': 'Jack', 'age': 22}
]
# 按name值升序排列
students.sort(key=lambda x: x['name'])
print(students)
# 按name值降序排列
students.sort(key=lambda x: x['name'], reverse=True)
print(students)
# 按age值升序排列
students.sort(key=lambda x: x['age'])
print(students)
高阶函数
把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式。
体验高阶函数:
#数字求绝对值计算
abs(-10) # 10
#数字的四舍五入计算
round(1.2) # 1
round(1.9) # 2
#需求:任意两个数字,按照指定要求整理数字后再进行求和计算。
#方法1
def add_num(a, b):
return abs(a) + abs(b)
result = add_num(-1, 2)
print(result) # 3
#方法2
def sum_num(a, b, f):
return f(a) + f(b)
result = sum_num(-1, 2, abs)
print(result) # 3
注意:两种方法对比之后,发现,方法2的代码会更加简洁,函数灵活性更高。函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快。
内置高阶函数map():map(func, lst),将传入的函数变量func作用到lst变量的每个元素中,并将结果组成新的列表(Python2)/迭代器(Python3)返回。
#计算`list1`序列中各个数字的2次方。
list1 = [1, 2, 3, 4, 5]
def func(x):
return x ** 2
result = map(func, list1)
print(result) # <map object at 0x0000013769653198>
print(list(result)) # [1, 4, 9, 16, 25]
reduce():reduce(func,lst),其中func必须有两个参数。每次func计算的结果继续和序列的下一个元素做累积计算。
#计算`list1`序列中各个数字的累加和。
import functools
list1 = [1, 2, 3, 4, 5]
def func(a, b):
return a + b
result = functools.reduce(func, list1)
print(result) # 15
filter():filter(func, lst)函数用于过滤序列, 过滤掉不符合条件的元素, 返回一个filter对象。如果要转换为列表, 可以使用list()来转换。
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def func(x):
return x % 2 == 0
result = filter(func, list1)
print(result) # <filter object at 0x0000017AF9DC3198>
print(list(result)) # [2, 4, 6, 8, 10]
文件操作
文件操作的作用就是把一些内容(数据)存储存放起来,可以让程序下一次执行的时候直接使用,而不必重新制作一份,省时省力。
关闭文件 f.close()
。
打开一个已经存在的文件,或者创建一个新文件,语法如下:
open(name, mode)
#name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。
#mode:设置打开文件的模式(访问模式):只读、写入、追加等。
打开文件模式
模式 | 描述 |
---|---|
r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 |
r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 |
w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
写:
#语法
对象对象.write('内容')
# 1. 打开文件
f = open('test.txt', 'w')
# 2.文件写入
f.write('hello world')
# 3. 关闭文件
f.close()
注意:
w
和a
模式:如果文件不存在则创建该文件;如果文件存在,w
模式先清空再写入,a
模式直接末尾追加。r
模式:如果文件不存在则报错。
读:
read()
文件对象.read(num)
num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据。
readlines():可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。
f = open('test.txt')
content = f.readlines()
# ['hello world\n', 'abcdefg\n', 'aaa\n', 'bbb\n', 'ccc']
print(content)
# 关闭文件
f.close()
readline()一次读取一行内容。
f = open('test.txt')
content = f.readline()
print(f'第一行:{content}')
content = f.readline()
print(f'第二行:{content}')
seek():用来移动文件指针。
文件对象.seek(偏移量, 起始位置)
#起始位置:0:文件开头;1:当前位置;2:文件结尾
文件备份:用户输入当前目录下任意文件名,程序完成对该文件的备份功能(备份文件名为xx[备份]后缀,例如:test[备份].txt)。
old_name = input('请输入您要备份的文件名:')
# 提取文件后缀点的下标
index = old_name.rfind('.')
# print(index) # 后缀中.的下标
# print(old_name[:index]) # 源文件名(无后缀)
# 组织新文件名 旧文件名 + [备份] + 后缀
new_name = old_name[:index] + '[备份]' + old_name[index:]
# 打印新文件名(带后缀)
# print(new_name)
# 打开文件
old_f = open(old_name, 'rb')
new_f = open(new_name, 'wb')
# 将源文件数据写入备份文件
while True:
con = old_f.read(1024)
if len(con) == 0:
break
new_f.write(con)
# 关闭文件
old_f.close()
new_f.close()
文件和文件夹的操作:在Python中文件和文件夹的操作要借助os模块里面的相关功能,具体步骤如下:
#导入os模块
import os
#使用os模块相关功能
os.函数名()
文件重命名
os.rename(目标文件名, 新文件名)
删除文件
os.remove(目标文件名)
创建文件夹
os.mkdir(文件夹名字)
删除文件夹
os.rmdir(文件夹名字)
获取当前目录
os.getcwd()
改变默认目录
os.chdir(目录)
获取目录列表
os.listdir(目录)
批量修改文件名,既可添加指定字符串,又能删除指定字符串。
import os
# 设置重命名标识:如果为1则添加指定字符,flag取值为2则删除指定字符
flag = 1
# 获取指定目录
dir_name = './'
# 获取指定目录的文件列表
file_list = os.listdir(dir_name)
# print(file_list)
# 遍历文件列表内的文件
for name in file_list:
# 添加指定字符
if flag == 1:
new_name = 'Python-' + name
# 删除指定字符
elif flag == 2:
num = len('Python-')
new_name = name[num:]
# 打印新文件名,测试程序正确性
print(new_name)
# 重命名
os.rename(dir_name+name, dir_name+new_name)
面向对象基础
面向对象就是将编程当成是一个事物,对外界来说,事物是直接使用的,不用去管他内部的情况。而编程就是设置事物能够做什么事。
类和对象的关系:用类去创建一个对象。
定义类:Python2中类分为:经典类 和 新式类。
class 类名():
代码
......
class Washer():
def wash(self):
print('我会洗衣服')
注意:类名要满足标识符命名规则,同时遵循大驼峰命名习惯。
经典类:不由任意内置类型派生出的类,称之为经典类
class 类名:
代码
......
创建对象:对象又名实例。
对象名 = 类名()
# 创建对象
haier1 = Washer()
# <__main__.Washer object at 0x0000018B7B224240>
print(haier1)
# haier对象调用实例方法
haier1.wash()
注意:创建对象的过程也叫实例化对象。
self指的是调用该函数的对象。
# 1. 定义类
class Washer():
def wash(self):
print('我会洗衣服')
# <__main__.Washer object at 0x0000024BA2B34240>
print(self)
# 2. 创建对象
haier1 = Washer()
# <__main__.Washer object at 0x0000018B7B224240>
print(haier1)
# haier1对象调用实例方法
haier1.wash()
haier2 = Washer()
# <__main__.Washer object at 0x0000022005857EF0>
print(haier2)
注意:打印对象和self得到的结果是一致的,都是当前对象的内存中存储地址。
类外面添加对象属性
对象名.属性名 = 值
haier1.width = 500
haier1.height = 800
类外面获取对象属性
对象名.属性名
print(f'haier1洗衣机的宽度是{haier1.width}')
print(f'haier1洗衣机的高度是{haier1.height}')
类里面获取对象属性
self.属性名
# 定义类
class Washer():
def print_info(self):
# 类里面获取实例属性
print(f'haier1洗衣机的宽度是{self.width}')
print(f'haier1洗衣机的高度是{self.height}')
# 创建对象
haier1 = Washer()
# 添加实例属性
haier1.width = 500
haier1.height = 800
haier1.print_info()
魔法方法
在Python中,__xx__()
的函数叫做魔法方法,指的是具有特殊功能的函数。
__init__()
方法的作用:初始化对象。
class Washer():
# 定义初始化功能的函数
def __init__(self):
# 添加实例属性
self.width = 500
self.height = 800
def print_info(self):
# 类里面调用实例属性
print(f'洗衣机的宽度是{self.width}, 高度是{self.height}')
haier1 = Washer()
haier1.print_info()
注意:
__init__()
方法,在创建一个对象时默认被调用,不需要手动调用。__init__(self)
中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去。
带参数的__init__()
:
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height
def print_info(self):
print(f'洗衣机的宽度是{self.width}')
print(f'洗衣机的高度是{self.height}')
haier1 = Washer(10, 20)
haier1.print_info()
haier2 = Washer(30, 40)
haier2.print_info()
__str__()
:当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了__str__
方法,那么就会打印从在这个方法中return的数据。
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height
def __str__(self):
return '这是海尔洗衣机的说明书'
haier1 = Washer(10, 20)
# 这是海尔洗衣机的说明书
print(haier1)
__del__()
:当删除对象时,python解释器也会默认调用__del__()
方法。
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height
def __del__(self):
print(f'{self}对象已经被删除')
haier1 = Washer(10, 20)
# <__main__.Washer object at 0x0000026118223278>对象已经被删除
del haier1
面向对象之继承
经典类或旧式类:不由任意内置类型派生出的类,称之为经典类。
class 类名:
代码
......
新式类
class 类名(object):
代码
Python面向对象的继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法,具体如下:
# 父类A
class A(object):
def __init__(self):
self.num = 1
def info_print(self):
print(self.num)
# 子类B
class B(A):
pass
result = B()
result.info_print() # 1
在Python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。
单继承
# 1. 师父类
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 2. 徒弟类
class Prentice(Master):
pass
# 3. 创建对象daqiu
daqiu = Prentice()
# 4. 对象访问实例属性
print(daqiu.kongfu)
# 5. 对象调用实例方法
daqiu.make_cake()
多继承
所谓多继承意思就是一个类同时继承了多个父类。
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 创建学校类
class School(object):
def __init__(self):
self.kongfu = '[school煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class Prentice(School, Master):
pass
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()
注意:当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法。
子类重写父类同名方法和属性
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
def __init__(self):
self.kongfu = '[school煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 独创配方
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()
print(Prentice.__mro__)
子类和父类具有同名属性和方法,默认使用子类的同名属性和方法。
子类调用父类的同名方法和属性
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
def __init__(self):
self.kongfu = '[school煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
# 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
daqiu = Prentice()
daqiu.make_cake()
daqiu.make_master_cake()
daqiu.make_school_cake()
daqiu.make_cake()
多层继承
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
def __init__(self):
self.kongfu = '[school煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
# 徒孙类
class Tusun(Prentice):
pass
xiaoqiu = Tusun()
xiaoqiu.make_cake()
xiaoqiu.make_school_cake()
xiaoqiu.make_master_cake()
super()调用父类方法
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(Master):
def __init__(self):
self.kongfu = '[school煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 方法2.1
# super(School, self).__init__()
# super(School, self).make_cake()
# 方法2.2
super().__init__()
super().make_cake()
class Prentice(School):
def __init__(self):
self.kongfu = '[独创煎饼果子技术]'
def make_cake(self):
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
# 一次性调用父类的同名属性和方法
def make_old_cake(self):
# 方法一:代码冗余;父类类名如果变化,这里代码需要频繁修改
# Master.__init__(self)
# Master.make_cake(self)
# School.__init__(self)
# School.make_cake(self)
# 方法二: super()
# 方法2.1 super(当前类名, self).函数()
# super(Prentice, self).__init__()
# super(Prentice, self).make_cake()
# 方法2.2 super().函数()
super().__init__()
super().make_cake()
daqiu = Prentice()
daqiu.make_old_cake()
注意:使用super() 可以自动查找父类。调用顺序遵循
__mro__
类属性的顺序。比较适合单继承使用。
私有权限
定义私有属性和方法
在Python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类。
设置私有权限的方法:在属性名和方法名前面加上两个下划线__。
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
def __init__(self):
self.kongfu = '[school煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
# 定义私有属性
self.__money = 2000000
# 定义私有方法
def __info_print(self):
print(self.kongfu)
print(self.__money)
def make_cake(self):
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
# 徒孙类
class Tusun(Prentice):
pass
daqiu = Prentice()
# 对象不能访问私有属性和私有方法
# print(daqiu.__money)
# daqiu.__info_print()
xiaoqiu = Tusun()
# 子类无法继承父类的私有属性和私有方法
# print(xiaoqiu.__money) # 无法访问实例属性__money
# xiaoqiu.__info_print()
注意:私有属性和私有方法只能在类里面访问和修改。
获取和修改私有属性值
在Python中,一般定义函数名get_xx
用来获取私有属性,定义set_xx
用来修改私有属性值。
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(object):
def __init__(self):
self.kongfu = '[school煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
self.__money = 2000000
# 获取私有属性
def get_money(self):
return self.__money
# 修改私有属性
def set_money(self):
self.__money = 500
def __info_print(self):
print(self.kongfu)
print(self.__money)
def make_cake(self):
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
# 徒孙类
class Tusun(Prentice):
pass
daqiu = Prentice()
xiaoqiu = Tusun()
# 调用get_money函数获取私有属性money的值
print(xiaoqiu.get_money())
# 调用set_money函数修改私有属性money的值
xiaoqiu.set_money()
print(xiaoqiu.get_money())
面向对象之其他
面向对象三大特性
封装:将属性和方法书写到类的里面的操作即为封装,封装可以为属性和方法添加私有权限。
继承:子类默认继承父类的所有属性和方法,子类可以重写父类属性和方法。
多态:传入不同的对象,产生不同的结果
多态
多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)。
多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果
class Dog(object):
def work(self): # 父类提供统一的方法,哪怕是空方法
print('指哪打哪...')
class ArmyDog(Dog): # 继承Dog类
def work(self): # 子类重写父类同名方法
print('追击敌人...')
class DrugDog(Dog):
def work(self):
print('追查毒品...')
class Person(object):
def work_with_dog(self, dog): # 传入不同的对象,执行不同的代码,即不同的work函数
dog.work()
ad = ArmyDog()
dd = DrugDog()
daqiu = Person()
daqiu.work_with_dog(ad)
daqiu.work_with_dog(dd)
类属性和实例属性
类属性就是类对象所拥有的属性,它被该类的所有实例对象所共有。类属性可以使用类对象或实例对象访问。
class Dog(object):
tooth = 10
wangcai = Dog()
xiaohei = Dog()
print(Dog.tooth) # 10
print(wangcai.tooth) # 10
print(xiaohei.tooth) # 10
修改类属性
类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了一个实例属性。
class Dog(object):
tooth = 10
wangcai = Dog()
xiaohei = Dog()
# 修改类属性
Dog.tooth = 12
print(Dog.tooth) # 12
print(wangcai.tooth) # 12
print(xiaohei.tooth) # 12
# 不能通过对象修改属性,如果这样操作,实则是创建了一个实例属性
wangcai.tooth = 20
print(Dog.tooth) # 12
print(wangcai.tooth) # 20
print(xiaohei.tooth) # 12
实例属性
class Dog(object):
def __init__(self):
self.age = 5
def info_print(self):
print(self.age)
wangcai = Dog()
print(wangcai.age) # 5
# print(Dog.age) # 报错:实例属性不能通过类访问
wangcai.info_print() # 5
类方法
类方法特点:需要用装饰器@classmethod
来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls
作为第一个参数。
当方法中需要使用类对象(如访问私有类属性等)时,定义类方法。类方法一般和类属性配合使用。
class Dog(object):
__tooth = 10
@classmethod
def get_tooth(cls):
return cls.__tooth
wangcai = Dog()
result = wangcai.get_tooth()
print(result) # 10
静态方法
静态方法特点:需要通过装饰器@staticmethod
来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)。静态方法也能够通过 实例对象 和 类对象 去访问。
当方法中 既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象 (如类属性、类方法、创建实例等)时,定义静态方法。取消不需要的参数传递,有利于减少不必要的内存占用和性能消耗。
class Dog(object):
@staticmethod
def info_print():
print('这是一个狗类,用于创建狗实例....')
wangcai = Dog()
# 静态方法既可以使用对象访问又可以使用类访问
wangcai.info_print()
Dog.info_print()
异常
当检测到一个错误时,解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的”异常”。
例如:以r
方式打开一个不存在的文件。
open('test.txt', 'r')
异常的写法
try:
可能发生错误的代码
except:
如果出现异常执行的代码
需求:尝试以r
模式打开文件,如果文件不存在,则以w
方式打开。
try:
f = open('test.txt', 'r')
except:
f = open('test.txt', 'w')
捕获指定异常
try:
可能发生错误的代码
except 异常类型:
如果捕获到该异常类型执行的代码
捕获多个指定异常:当捕获多个异常时,可以把要捕获的异常类型的名字,放到except 后,并使用元组的方式进行书写。
try:
print(1/0)
except (NameError, ZeroDivisionError):
print('有错误')
捕获异常描述信息
try:
print(num)
except (NameError, ZeroDivisionError) as result:
print(result)
捕获所有异常:Exception是所有程序异常类的父类。
try:
print(num)
except Exception as result:
print(result)
异常的else:else表示的是如果没有异常要执行的代码。
try:
print(1)
except Exception as result:
print(result)
else:
print('我是else,是没有异常的时候执行的代码')
异常的finally:finally表示的是无论是否异常都要执行的代码,例如关闭文件。
try:
f = open('test.txt', 'r')
except Exception as result:
f = open('test.txt', 'w')
else:
print('没有异常,真开心')
finally:
f.close()
自定义异常:在Python中,抛出自定义异常的语法为 raise 异常类对象
。
需求:密码长度不足,则报异常(用户输入密码,如果输入的长度不足3位,则报错,即抛出自定义异常,并捕获该异常)。
# 自定义异常类,继承Exception
class ShortInputError(Exception):
def __init__(self, length, min_len):
self.length = length
self.min_len = min_len
# 设置抛出异常的描述信息
def __str__(self):
return f'你输入的长度是{self.length}, 不能少于{self.min_len}个字符'
def main():
try:
con = input('请输入密码:')
if len(con) < 3:
raise ShortInputError(len(con), 3)
except Exception as result:
print(result)
else:
print('密码已经输入完成')
main()
模块
Python模块(Module),是一个Python文件,以 .py
结尾,包含了 Python 对象定义和Python语句。
模块能定义函数,类和变量,模块里也能包含可执行的代码。
导入模块的方式
- import 模块名
- from 模块名 import 功能名
- from 模块名 import *
- import 模块名 as 别名
- from 模块名 import 功能名 as 别名
import
# 1. 导入模块
import 模块名
import 模块名1, 模块名2...
# 2. 调用功能
模块名.功能名()
# 体验
import math
print(math.sqrt(9)) # 3.0
from..import..
from 模块名 import 功能1, 功能2, 功能3...
# 体验
from math import sqrt
print(sqrt(9))
from .. import *
from 模块名 import *
# 体验
from math import *
print(sqrt(9))
as定义别名
# 模块定义别名
import 模块名 as 别名
# 功能定义别名
from 模块名 import 功能 as 别名
# 体验
# 模块别名
import time as tt
tt.sleep(2)
print('hello')
# 功能别名
from time import sleep as sl
sl(2)
print('hello')
制作模块
制作模块:在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字。也就是说自定义模块名必须要符合标识符命名规则。
新建一个Python文件,命名为my_module1.py
,并定义testA
函数。
def testA(a, b):
print(a + b)
在实际开中,当一个开发人员编写完一个模块后,为了让模块能够在项目中达到想要的效果,这个开发人员会自行在py文件中添加一些测试信息。例如,在my_module1.py
文件中添加测试代码。
def testA(a, b):
print(a + b)
testA(1, 1)
此时,无论是当前文件,还是其他已经导入了该模块的文件,在运行的时候都会自动执行testA
函数的调用。
解决办法如下:
def testA(a, b):
print(a + b)
# 只在当前文件中调用该函数,其他导入的文件内不符合该条件,则不执行testA函数调用
if __name__ == '__main__':
testA(1, 1)
调用模块
import my_module1
my_module1.testA(1, 1)
模块定位顺序
如果使用from .. import ..
或from .. import *
导入多个模块的时候,且模块内有同名功能。当调用这个同名功能的时候,调用到的是后面导入的模块的功能。
# 模块1代码
def my_test(a, b):
print(a + b)
# 模块2代码
def my_test(a, b):
print(a - b)
# 导入模块和调用功能代码
from my_module1 import my_test
from my_module2 import my_test
# my_test函数是模块2中的函数
my_test(1, 1)
当导入一个模块,Python解析器对模块位置的搜索顺序是:
- 当前目录
- 如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。
- 如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/
模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。
- 注意
- 自己的文件名不要和已有模块名重复,否则导致模块功能无法使用
使用from 模块名 import 功能
的时候,如果功能名字重复,调用到的是最后定义或导入的功能。
__all__
如果一个模块文件中有__all__
变量,当使用from xxx import *
导入时,只能导入这个列表中的元素。
# my_module1模块代码
__all__ = ['testA']
def testA():
print('testA')
def testB():
print('testB')
# 导入模块的文件代码
from my_module1 import *
testA()
testB()# 报错
包
包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为__init__.py
文件,那么这个文件夹就称之为包。
制作包:[New] — [Python Package] — 输入包名 — [OK] — 新建功能模块(有联系的模块)。
注意:新建包后,包内部会自动创建__init__.py
文件,这个文件控制着包的导入行为。
新建包mypackage
,新建包内模块:my_module1
和 my_module2
,模块内代码如下
# my_module1
print(1)
def info_print1():
print('my_module1')
# my_module2
print(2)
def info_print2():
print('my_module2')
导入包
# 方法一
import 包名.模块名
包名.模块名.目标
# 体验
import my_package.my_module1
my_package.my_module1.info_print1()
#方法二:必须在`__init__.py`文件中添加`__all__ = []`,控制允许导入的模块列表。
from 包名 import *
模块名.目标
# 体验
from my_package import *
my_module1.info_print1()