python基础


变量


数据都是临时存储在内存中,为了更快速的查找或使用这个数据,通常我们把这个数据在内存中存储之后定义一个名称,这个名称就是变量。

变量就是一个存储数据的时候当前数据所在的内存地址的名字而已。

定义变量:

变量名 = 值

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')

innot 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()

注意:wa模式:如果文件不存在则创建该文件;如果文件存在,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解析器对模块位置的搜索顺序是:

  1. 当前目录
  2. 如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。
  3. 如果都找不到,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_module1my_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()


文章作者:
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 !
  目录