python基础

一、认识Python

1、python起源

Python 的创始人为吉多·范罗苏姆(Guido van Rossum),江湖人称“龟叔”。

1991年,第一个Python解释器诞生,它是用C语言实现的,并能够调用C语言的库文件。

1.1、Python的组成

  • Python的语法
  • Python的标准内置库
  • Python的第三方库
  • Python解释器

1.2、解释器

编译器翻译的方式有两种:一个是编译,另外一个是解释。两种方式之间的区别在于翻译时间点的不同。当编译器以解释方式运行的时候,也称之为解释器

  • 编译型语言:程序在执行之前需要一个专门的编译过程,把程序编译成为机器语言的文件,运行时不需要重新翻译,直接使用编译的结果就行了。程序执行效率高,依赖编译器,跨平台性差些。如:C、C++
  • 解释型语言:解释型语言编写的程序不进行预先编译,以文本方式存储程序代码,会将代码一句一句直接运行。在发布程序时,看起来省了道编译工序,但是在运行程序的时候,必须先解释再运行

编译型语言和解释型语言对比

  • 速度 —— 编译型语言比解释型语言执行速度快
  • 跨平台性 —— 解释型语言比编译型语言跨平台性好

2、Python特点

  • Python是完全面向对象的语言

    • 函数、模块、数字、字符串都是对象,在Python中一切皆对象
    • 完全支持继承、多重继承等
  • Python拥有一个强大的标准库,Python语言的核心只包含数字、字符串、列表、字典、文本等常见类型和函数,而由Python标准库提供了系统管理、网络通信、文本处理、数据库接口、图形系统、等额外的功能
  • Python社区提供了大量的第三方模块,使用方式与标准库类似。它们的功能涵盖科学计算、人工智能、机器学习、Web开发、数据库接口、图形系统多个领域

3、Python的优缺点

3.1、优点

  • 简单、易学
  • 免费、开源
  • 面向对象
  • 丰富的库
  • 可扩展性

3.2、缺点

  • 速度慢:Python程序比Java、C、C++等程序的运行效率都要慢
  • 源代码加密困难:不像编译型语言的源程序会被编译成目标程序,Python直接运行源程序,因此对源代码加密比较困难。

二、安装Python

https://blog.csdn.net/weixin_47643553/article/details/108815728

三、第一个Python程序

1、第一个hello world程序

1.1、Python源程序的基本概念

  • Python源程序就是一个特殊格式的文本文件,可以使用任意文本编辑软件做Python的开发
  • Python程序的文件扩展名通常都是.py

1.2、编写程序

  • 新建目录
  • 新建.py文件
  • 编辑.py文件
print("hello world")
print("hello python")
  • 在终端中输入以下命令执行xxx.py
python xxx.py

四、pycharm安装

五、Python的数据类型

Python六个标准的数据类型

  • number(数字)
  • string(字符串)
  • list(列表)
  • tuple(元组)
  • set(集合)
  • dictionary(字典)

5.1、Python变量的声明与使用

  • 变量:作用是存储程序运行中的值,变量的值在程序运行中是可以变化的,变量必须先声明再使用。
  • Python变量的声明:变量名=值
    • 在Python中变量是没有数据类型的,变量的数据类型取决于赋值的类型,这与其他语言不一样。
# 声明一个变量num1,赋值为整数8
num1 = 8
# 查看num1的类型
print(type(num1))
# 使用变量num1
print(num1)# 声明一个变量str1,赋值为字符串hello
str1 = "hello"
# 查看str1的类型
print(type(str1))
# 输出变量str1
print(str1)
# 多个变量同时定义
num2,str2 = 1,"你好"
print(num2,str2)
  • 常量:Python没有常量的概念,Python程序一般通过约定俗成的变量名全大写的形式表示这是一个常量。
# Java中常量举例:声明常量PRICE,赋值为10,声明后这个常量的值就固定为10,不能再对它赋值
final int PRICE = 10;# 如果Python中要定义常量,如下:
PI = 3.14
MONTH = 12

5.2、数值型

Python中的数值型包括:int(整型)、float(浮点型)、complex(复数),在Python2中还有long(长整型)

5.2.1、int

int(整型):表示一个整数,包括正整数、负整数

num1 = 100
print(type(num1))
<class 'int'>

type()函数:type函数的作用是查询变量的数据类型

5.2.2、float

float(浮点型):表示一个小数,但在计算机中float只能表示一个近似值,不能表示精确值,这是因为浮点数的机制决定的(浮点数必须包含一个小数点,否则会被当作int类型处理)

a = 3.11
b = 1.5
print(a-b)
# 1.6099999999999999

如果要表示精确值,可以使用Decimal对象来实现

# 通过实例化Decimal对象来表示精确小数
from decimal import Decimal
print(Decimal("3.11")-Decimal("1.5"))
# 1.61

5.2.3、其他进制的表示与相互转换

常见的进制:二进制、八进制、十进制、十六进制等

  • 二进制(Binary)

    • 由0,1组成,逢二进一
    • 二进制的声明:在数字前加0b表示二进制
# 声明一个变量a,赋值为二进制1001
a = 0b1001
# 输出a的值,输出的是十进制9
print(a)
  • 八进制(Octal)

    • 由0,1,…,7组成,逢八进一
    • 八进制的声明:0o
# 声明一个变量a
a = 0o11
# 输出a
print(a)
  • 十进制(Decimal)

    • 十进制的声明:Python中默认的数值就是十进制的
  • 十六进制(Hexadecimal)

    • 十六进制的声明:在数字前加0x表示十六进制
# 十六进制
a = 0x000F
# 输出a的值,输出的是十进制15
print(a)
  • 进制转换函数
# **进制转换函数**
# - bin():把十进制转成二进制
# - oct():把十进制转成八进制
# - hex():把十进制转成十六进制
# - int(x,base=y):表示把y进制的字符串x转换成十进制的整数
# - 举例:
print(bin(10)) # 十进制转换为二进制
# 0b1010
print(oct(10)) # 十进制转换为八进制
# 0o12
print(hex(17)) # 十进制转换为十六进制
# 0x11
print(int("1000",base=2))#表示把2进制的字符串“1000”转换成十进制的整数
# 8
print(int("1002",base=2))#思考:输出是什么?

5.3、字符串-str

5.3.1、字符串的声明

字符串用引号来声明,字符串是有序的一串字符。

# 字符串的声明str1 = "hello"
str2 = "world"print("str1",type(str1),len(str1))
print(str1)
print("str2",type(str2),len(str2))
print(str2)
print(str1+" "+str2)

5.3.2、字符串的切片

字符串是有序的,字符串中的每个字符是有索引下标的,字符串的索引有两种:

  • 正序索引:0开始,从左到右
  • 倒序索引:-1开始,从右到左

字符串切片语法:

1、str[start : end : step]

2、str[index]

# 字符串的切片str3 = "hello world"# 步长为正
# 取当前位置的值
print(str3[1])
# 步长不输默认为1
print(str3[1:4])
print(str3[:4])
# 终止值不输默认取到最后
print(str3[4:])
print(str3[:])
# 区间左闭右开
print(str3[4:7:1])'''
e
ell
hell
o world
hello world
o w
'''# 步长为负
print(str3[-1:-5])
print(str3[-1:-5:-1])
# 取值区间不在范围内不会报错,返回空字符串
print(str3[-5:-1])
print(str3[-5:-1:-1])'''
dlro
worl'''

5.3.3、字符串的常用函数

pycharm中,代码提示的含义:

Class:类

Method:方法

Function:函数

Field:类属性,域

Variable:变量

Property:python内置函数

Parameter:参数

Element:元素

5.3.3.1、len()函数

作用:计算字符串长度

str1 = 'hello world'
print(len(str1))
# 11
5.3.3.2、ord()函数

作用:返回字符的ASCII码

print(ord('a'))
print(chr(97))
print(ord('A'))
# 97
# a
# 65
5.3.3.3、chr()函数

作用:跟ord()相反,根据ASCII码返回相应的字符

print(chr(99))
# c

5.3.4、字符串的常用方法

5.3.4.1、find()方法

格式:find(self, sub, start=None, end=None)

作用:在字符串中找第一个出现的字符串的下标,如果找不到则返回-1,可以传入start和end在指定的范围内找

str2 = 'nihao,feichanghao'
# 查询第一个a元素的下标索引
print(str2.find('a'))
# 查询下标索引位置从10到17的区间中的第一个a的下标索引
print(str2.find('a',10,17))
5.3.4.2、index()方法

作用:在字符串中找第一个出现的子串的下标,如果找不到抛 ValueError 异常

str2 = 'sdfsduerbdffo45602142'
print(str2.index('e'))
print(str2.index('4'))
# 6
# 13

find()和index()方法的区别 :find()如果在指定字符中没有找到则返回-1;而index则会抛出ValueError 异常

5.3.4.3、rfind()方法

格式:rfind(self,sub,start=None,end=None)

作用:在字符串中找最后一个出现的子串的下标,如果找不到则返回-1

str2 = 'sdfsduerbdffo45602142'
print(str2.rfind('f'))
# 11
5.3.4.4、rindex()方法

格式:rindex(self,sub,start=None,end=None)

作用:在字符串中找最后一个出现的子串的下标,如果找不到则抛ValueError异常

str2 = 'sdfsduerbdffo45602142'
print(str2.rindex('f'))
# 11
5.3.4.5、format()方法

作用:实现字符串的格式化输出

#场景一:format方法中的值按位置替换字符串中的{}
print("我叫{},我来自{},今年{}岁了。".format('jack','成都','10'))
# 我叫jack,我来自成都,今年10岁了。
#场景二:以索引的方式来表示替换参数,{0}位置用传入的第一个变量替换,{1}位置用传入的第二个变量替换,{2}位置用传入的第三发变量替换。可以允许传入的参数比需要的多,但不能比需要的少
print("我叫{0},我来自{1},今年{2}岁了。".format('jack','成都','10'))
print("我叫{1},我来自{1},今年{2}岁了。".format('jack','成都','10'))
print("我叫{0},我来自{1},今年{2}岁了。".format('jack','成都','10','北京'))
print("100+200={0}".format(100+200))
# 我叫jack,我来自成都,今年10岁了。
# 我叫成都,我来自成都,今年10岁了。
# 我叫jack,我来自成都,今年10岁了。
# 100+200=300
#场景三:在大括号中除了用下标之外,还可以用变量名,这种情况下传入的参数顺序就没有关系了。
print("我叫{name},我来自{city},今年{age}岁了。".format(name='jack',city='成都',age='10'))
print("我叫{name},我来自{city},今年{age}岁了。".format(city='成都',age='10',name='jack'))
print(str2)
# 我叫jack,我来自成都,今年10岁了。
# 我叫jack,我来自成都,今年10岁了。
# sdfsduerbdffo45602142

在Python中除了用format方法实现格式化输出之外,还可以使用格式符来实现格式化输出,常用的格式符有如下:

  • %s 字符串
  • %d 十进制整数
  • %f 浮点数
name = "hhm"
age = 23# 如果不使用格式化输出,会多出一个空格
print(name,'今年',age,'岁了')
# hhm 今年 23 岁了# 使用格式化输出
print('%s今年%d岁了'%(name,age))
# hhm今年23岁了# %.2f表示四舍五入保留2位小数输出
print("%.2f"%1.333333)
# 1.33# 也可以使用round函数实现四舍五入,保留n位小数
print(round(1.34565528,4))
# 1.3457
5.3.4.6、count()方法

作用:统计子串出现的次数

str3 = 'sdfkaheighdhgjkfsui'
print(str3.count('a'))
print(str3.count('h'))
print(str3.count('j'))
# 1
# 3
# 1
5.3.4.7、join()方法

作用:传入一个可迭代对象,把可迭代对象中的每个元素通过调用它的字符串来拼接,返回拼接后的字符串。

# 在字符串中拼接“_”,把每个字符分开
str4 = "todayissohappy"
print("_".join(str4))
# t_o_d_a_y_i_s_s_o_h_a_p_p_y# 错误的,join()方法传入的参数必须是迭代对象(包括字符串、列表、元组等)
# print("_".join(100))
# TypeError: can only join an iterable# join方法中传入列表,但列表的元素必须是字符串
print(" ".join(["1","3","5"]))
# 1 3 5#join方法中传入元组,但元组的元素必须是字符串
print(" ".join(("1","3","5")))
# 1 3 5
5.3.4.8、replace()方法

格式:replace(self,old,new[,count])

作用:替换旧的字符串成新字符串,count参数可选,表示替换几个

str5 = 'sdfskakjksgjjjsdaaaaaaa'# 把str5中的a替换成A
print(str5.replace('a','A'))
# sdfskAkjksgjjjsdAAAAAAA# 只替换一次
print(str5.replace('a','A',1))
# sdfskAkjksgjjjsdaaaaaaa# 把str2中的第2个a替换成A
print(str5.replace('a','A',2).replace('A','a',1))
# sdfskakjksgjjjsdAaaaaaa
5.3.4.9、split()方法

格式:split(self,sep,maxsplit=-1)

作用:将一个字符串分裂成多个字符串返回列表的方法,详细即通过指定分隔符对字符串进行切片,如果参数maxspllit有指定值,则仅分隔maxsplit个字符串

str6 = "hello"
print(str6.split("l"))
# ['he', '', 'o']print(str6.split("l",1))
# ['he', 'lo']

注意:当分割的子串出现在边界上,或者连续出现分割的子串时,在返回的列表中会出现空字符串。

5.3.4.10、strip()/rstrip()/lstrip()方法

作用:

  • strip()方法是去除字符串两边的空格
  • rstrip()方法是去除字符串右边的空格
  • lstrip()方法是去除字符串左边的空格
str1 = " jkl sdfoi "# 去除开头的空格
print(str1.lstrip())
# jkl sdfoi # 去除结尾的空格
print(str1.rstrip())
#  jkl sdfoi# 去除两边的空格
print(str1.strip())
# jkl sdfoi
5.3.4.11、capitalize()方法

作用:将字符串的首字母大写,其余字母全部小写

str1 = "abdcefghijklmn"print(str1.capitalize())
# Abdcefghijklmnprint("today is wednesday".capitalize())
# Today is wednesday
5.3.4.12、upper()方法

作用:把 字母全部转换为大写

str1 = "abdcefghijklmn"
print(str1.upper())
# ABDCEFGHIJKLMN
5.3.4.13、lower()方法

作用:把字母全部转换为小写

str1 = "ABDCEFGHIJKLMN"
print(str1.lower())
# abdcefghijklmn
5.3.4.14、title()方法

作用:字母的首字母都大写,标题化

str3 = "hello new world"
print(str3.title())
# Hello New World
5.3.4.15、endswith()方法

作用:判断字符串以xx结尾

str1 = "abdcefghijklmn"
print(str1.endswith('f'))
print(str1.endswith('n'))
# False
# True
5.3.4.16、startswith()方法

作用:判断字符串以xx开头

str1 = "abdcefghijklmn"
print(str1.startswith('a'))
print(str1.startswith('b'))
# True
# False
5.3.4.17、以is开头的方法

所有is开头的方法返回结果都是布尔值(True或者False

  • isalnum(): 字符串中所有字符都是字母或数字且非空则返回True
  • isalpha(): 字符串中所有字符都是字母且非空则返回True
  • isdigit(): 字符串中所有字符都是数字且非空则返回True
  • isupper(): 字母都为大写且非空返回True
  • islower(): 字母都为小写且非空返回True
  • istitle(): 单词的首字母都为大写且非空返回True
print("we123".isalnum())
print("".isalnum())
print("%^*".isalnum())
print("we123".isalpha())
# True
# False
# False
# False

举例:从键盘输入密码,判断密码是否是由数字组成,如果是返回输入正确,否则返回输入错误

str1 = input("请输入密码:")
if str1.isdigit():print("输入正确")
else:print("输入错误")# 请输入密码:123156
# 输入正确# 请输入密码:sdfsd
# 输入错误

5.3.5、字符串的驻留机制

在编程语言中,=表示赋值,==表示等于,is表示判断两个对象是否是同一个对象(内存地址),==与is的区别是:==比较的是值,is比较的是内存地址

字符串的驻留机制:在存放两个相同的字符串时,是否申请新的内存空间来分别存放取决于字符串的复杂程度(有多种类型的字符,如果只有一种即便很长那也不算复杂)

str1="helloworldnihao"
str2="helloworldnihao"
str3="monday%^ sunday"
str4="monday%^ sunday"print(str1==str2)
# Trueprint(str1 is str2)
# Trueprint(id(str1))
# 2433156314160print(id(str2))
# 2433156314160print(str3==str4)
# Trueprint(str3 is str4)
# Falseprint(id(str3))
# 2433156279920print(id(str4))
# 2433161895664

5.3.6、转义字符

在编程语言中,定义了一些特殊字符来表示特定的含义,这被称为转义字符,之所以叫转义是因为字符原本的含义发生了改变。比如:

# \' :表示单引号,在单引中输出单引时需要用这个转义符
# \" :表示双引号,在双引中输出双引时需要用这个转义符
# \""" :表示三引号,在三引中输出三引时需要用这个转义符
# \\ :表示反斜线,在输出反斜线的时候需要用到
# \t :表示水平制表符,作用类似于tab健,在输出需要有间隔时使用
# \n :换行符,在输出时,需要换行时使用
#  ' :单引号,双引号里面可以直接使用单引号
print("i'm a boy")
# i'm a boy
#  " :双引号,单引号里面可以直接使用双引号
# \ :反斜杠\,如果刚好遇到"\test"这种,系统会把\t识别成转义字符,这时要在前面再加一个\,如果路径很长,可以在最前面加个r
print("\\test")
print(r"c:\test\rh.txt")
# \test
# c:\test\rh.txt
#  \x :表示后面的字符是十六进制数

Python 字符串前面加r, b, f的含义

r:字符串前加 r

  • 去掉反斜杠的转移机制。

例:r"\n\n” # 表示一个普通生字符串 \n\n,而不表示换行了。
b: b" " 前缀表示:字符串是 bytes 类型。

  • 网络编程中,服务器和浏览器只认bytes 类型数据。

f:字符串前加 f

  • 以 f 开头表示在字符串内支持大括号内的python 表达式

5.4、列表-list

5.4.1、列表的声明

  • 列表是一组有序的元素,它里面的元素可以是数字、字符串、甚至可以是列表,元素跟元素之间用逗号分隔。
  • 列表的声明:通过[]或list()或列表推导式来声明(一维列表、多维列表)
  • 声明一个列表:
# 声明一个空列表
list1 = []
print(type(list1),len(list1))
# <class 'list'> 0# 声明一个非空列表
list2 = ['a',1,5,'hello',[2,4,6,'world']]
print(type(list2),len(list2))
# <class 'list'> 5# 通过创建list对象来声明一个列表
list1 = list("hello")
print(list1)
# ['h', 'e', 'l', 'l', 'o']num = 23314
# print(list(num)) # 错误的,不能转换
# TypeError: 'int' object is not iterable#通过列表推导式来声明一个列表
print([i for i in range(1,101) if i%2==0])
# [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100]
  • 一维列表和二维列表

    • 一维列表:[1,2,3]
    • 二维列表:[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
  • 修改列表中的元素

list2=['a',1,5,'hello',[2,4,6,'world']]
print(list2) # 修改前
# ['a', 1, 5, 'hello', [2, 4, 6, 'world']]# 修改列表中的5为99
list2[2] = 99
print(list2) # 修改后
# ['a', 1, 99, 'hello', [2, 4, 6, 'world']]

5.4.2、列表的切片

  • 列表的切片:规则与字符串的切片类似,但它返回的是一个列表
list1 = [1,3,4,5,6,7,8,9,0,123,4566,888,[345,567,999],"hello,中国"]print(list1[1]) # 取下标索引为1的元素
# 3print(list1[:6]) # 取下标索引默认从0开始到6结束步长默认为1的元素
# [1, 3, 4, 5, 6, 7]print(list1[::]) # 全部默认,取整个列表
# [1, 3, 4, 5, 6, 7, 8, 9, 0, 123, 4566, 888, [345, 567, 999], 'hello,中国']print(list1[::-1]) # 全部默认,取整个列表的倒序
# ['hello,中国', [345, 567, 999], 888, 4566, 123, 0, 9, 8, 7, 6, 5, 4, 3, 1]print(list1[12][1]) # 取列表中的列表里的元素
# 567print(list1[13][1]) # 取列表中的字符串里的元素
# e

5.4.3、列表的常用函数

  • len(list)

    • 作用:计算列表的长度,即计算列表中的元素个数
list1 = [1,2,3,4,"niaoogho","你好","a","z","A"]
print(len(list1))
# 9
  • max(list)

    • 作用:取列表中的最大值
# 字母排序是根据ASCII码排序
# 汉字排序是根据编码格式来排序
list1 = ["niaoogho","你好","a","z","A"]
print("最大值是:",max(list1))
# 最大值是: 你好
  • min(list)

    • 作用:取列表中的最小值
# 字母排序是根据ASCII码排序
# 汉字排序是根据编码格式来排序
list1 = ["niaoogho","你好","a","z","A"]
print("最大值是:",min(list1))
# 最大值是: A
  • sorted(list,reverse=False)

    • 作用:对列表的元素排序,返回排序后的新列表,默认是升序
list1=[1,5,2,-1]
# 升序排列
print(sorted(list1))
# [-1, 1, 2, 5]# 降序排列
print(sorted(list1,reverse=True))
# [5, 2, 1, -1]

5.4.4、列表的常用方法

5.4.4.1、append()
  • 作用:在列表的末尾增加一个元素
list1 = [1,2,4,5,65,"真的"]
print(list1)
# [1, 2, 4, 5, 65, '真的']list1.append(300)
print(list1)
# [1, 2, 4, 5, 65, '真的', 300]list1.append([400,500])
print(list1)
# [1, 2, 4, 5, 65, '真的', 300, [400, 500]]
5.4.4.2、insert()
  • 格式:insert(self,index,value)
  • 作用:在列表中下标为index的位置插入元素value(操作之后元素value的下标为index)添加单个元素
list1 = [1,2,4,5,65,"真的"]# 在元素下标为3的位置插入999
list1.insert(3,999)
print(list1)
# [1, 2, 4, 999, 5, 65, '真的']# 在超出索引位置添加?- 会添加在列表的最后
list1.insert(8,88)
print(list1)
# [1, 2, 4, 999, 5, 65, '真的', 88]
5.4.4.3、extend()
  • 格式:extend(可迭代对象)

  • 作用:列表的拼接,添加多个元素

list1 = ["你好"]
list2=[111,222,333]list1.extend(list2)
print(list1)
# ['你好', 111, 222, 333]print("两个列表相加:",list1+list2)
# 两个列表相加: ['你好', 111, 222, 333, 111, 222, 333]print("两个列表逗号拼接:",list1,list2)
# 两个列表逗号拼接: ['你好', 111, 222, 333] [111, 222, 333]
5.4.4.4、index()
  • 作用:从列表中找出某个值,第一个匹配项的索引位置
list1 = [1,2,3,5,7,"zheng","很好"]print(list1.index(2)) # 返回2的下标索引位置
# 1
# 如果查询的不在列表内?-报错:ValueError: 8 is not in list
5.4.4.5、count()
  • 作用:计算元素出现的次数
list1 = [1,2,3,1,7,"zheng","很好"]
print(list1.count(1))
# 2
5.4.4.6、remove()
  • 作用:删除列表中的某个元素:括号中传入要删除的元素值,不返回删除元素,返回None
list1 =["a","b","d","c"]print("删除前",list1)
# 删除前 ['a', 'b', 'd', 'c']print(list1.remove('a')) # 打印删除时是否返回
# Noneprint("删除后",list1)
# 删除后 ['b', 'd', 'c']
5.4.4.7、pop()方法
  • 作用:传输要删除元素的下标,pop方法会返回删除的元素,如果不传默认删除最后一个
list1 = ["a","b","c","d","efg"]print(list1.pop(2))
# cprint(list1)
# ['a', 'b', 'd', 'efg']
5.4.4.8、del list[index]
  • 作用:删除列表或列表中的数据
list1 = [[2,4,6,"hello"],"happy",5,3]# 根据下标索引删除单个元素
# del list1[0]
print(list1)
# ['happy', 5, 3]# 根据下标删除区间
# del list1[1:3]
print(list1)
# [[2, 4, 6, 'hello'], 3]# 删除整个列表
del list1
print(list1)
# NameError: name 'list1' is not defined
5.4.4.9、clear()
  • 作用:清空列表,得到一个空列表
list1 = [[2,4,6,"hello"],"happy",5,3]list1.clear()print(list1)
# []
5.4.4.10、copy()
  • 作用:复制列表
list1 = [1,233,4,5]
print(list1)
# [1, 233, 4, 5]list2 = list1.copy()
print(list2)
# [1, 233, 4, 5]

赋值,copy,deepcopy的区别?

  • 直接赋值:其实就是对象的引用(别名)。

  • copy 模块的 copy 方法,拷贝父对象,不会拷贝对象的内部的子对象。

  • copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象。

5.4.4.11、sort()
  • 作用:对列表的元素排序
  • 通过reverse参数来控制排序是升序还是降序,reverse只能传布尔值True或False,默认是False(升序),所以如果不传入任何参数,表示默认升序排列,数字从小到大,字符根据ASCII码来排列;
  • 数值跟列表以及字符串之间不能一起排序;
  • 通过key参数来控制排序的权重,即根据第几个字符来排序,如果有元素排序的条件相同,则最终排序结果跟存储的顺序保持一致。
list1 = [1,2,3,4,5]
list2 = ["a","b","A","B","a"]
list3 = ["中国","你好","加油"]list1.sort()
print(list1)
# [1, 2, 3, 4, 5]list2.sort()
print(list2)
# ['A', 'B', 'a', 'a', 'b']list3.sort()
print(list3)
# ['中国', '你好', '加油']list1.sort(reverse=True)
print(list1)
# [5, 4, 3, 2, 1]
5.4.4.12、sorted()
  • 作用:sorted是内置函数,可对所有可迭代的对象进行排序操作,返回新的list。sorted函数与sort方法的区别是sorted函数会返回排序后的新列表,而sort方法不会返回。
list1 = [7,8,4,6,33,1,3]
list2 = sorted(list1)
print(list2)
# [1, 3, 4, 6, 7, 8, 33]
5.4.4.13、reverse()
  • 作用:反向列表中的元素,reverse()方法和列表[::-1]的区别是前者会改变列表中的元素顺序,而后者不会改变顺序,只会把列表的元素反着取出来。
list1 = ["1","a","9","你好","heog"]
list1.reverse()
print(list1)
# ['heog', '你好', '9', 'a', '1']print(list1[::-1])
# ['1', 'a', '9', '你好', 'heog']print(list1)
# ['heog', '你好', '9', 'a', '1']
  • 列表与元素之间的转换

    • 通过字符串的join方法可以实现列表中的元素转字符串,通过创建list类的对象可以实现字符串的元素转列表
list1=['w', 'e', 'a' ,'r', 'e', 'g', 'o', 'o', 'd', 's', 't', 'u', 'd','e', 'n', 't', 's']
print(type("".join(list1))) #列表转字符串,打印类型
# <class 'str'>print("".join(list1))
# wearegoodstudentsprint(list("135"))
# ['1', '3', '5']

5.5、元组-tuple

5.5.1、元组的声明

  • 元组通过()或tuple()来声明
  • 元组是一组有序的数,用小括号()来表示,元组的元素跟元素之间用英文逗号隔开,元组跟列表的最大区别是:元组中的单个元素不能增删改。元组通常用于保护数据而存在
#空元组
tupl0=()
print(type(tupl0),len(tupl0))
# <class 'tuple'> 0#非空元组
tup1=(1,2,5)
print(type(tup1),len(tup1))
# <class 'tuple'> 3#用tuple实例化对象来声明元组
num=123
str1="你好吗"
list1=[1,2,4,5]
# print(tuple(num)) # 报错
print(tuple(str1))
# ('你', '好', '吗')print(tuple(list1))
# (1, 2, 4, 5)
  • 声明一个只有一个元素的元组:需要加一个逗号来表明这是一个单元素的元组,否则解释器会理解成在外面加了一个普通的括号,打印类型为单个元素的类型。

5.5.2、元组的作用

  1. 可以实现对数据进行保护
  2. 在操作不定长参数函数时,其参数的类型就是一个元组,所以可以直接将元组进行传入
  3. 在函数或者方法中返回值可以返回多个值,默认是把多个值以元组的形式返回

5.5.3、元组和列表的区别(面试问题)

列表中的元素是可变的,可以对元素进行增删改操作;元组中的元素是不可改变的,不能对元素进行增删改操作。

5.5.4、元组的切片

  • 元组的切片(有序的,可以使用下标索引),切片出来的数据还是保存在元组里的规则跟字符串、列表一致
tup1=(1,2,(1,2,3),5,999,'fgjgjfs',[1,2,3])
# 不在范围内
print(tup1[1111:])
# ()# 取下标为2的元素
print(tup1[2])
# (1, 2, 3)# 取下标为1开始,终止值默认到最后,步长默认为1
print(tup1[1:])
# (2, (1, 2, 3), 5, 999, 'fgjgjfs', [1, 2, 3])# 倒序?
# 取元组中的元组里的数据

5.5.5、元组的常用操作

  • 元组的修改(不是修改,实际是形成了一个新的元组)

    • 转成列表间接使用列表的方法来操作,最后再转成元组

    • tup1=(1,2,(1,2,3),5,999,'fgjgjfs',[1,2,3])#  转成列表间接使用列表的方法来操作,最后再转成元组
      print(tuple([1,2,3]))
      # (1, 2, 3)print(tuple("youseeyou"))
      # ('y', 'o', 'u', 's', 'e', 'e', 'y', 'o', 'u')list1 = list(tup1)
      list1.insert(list1.index(5)+1,100)
      tup1 = tuple(list1)
      print(tup1)
      # (1, 2, (1, 2, 3), 5, 100, 999, 'fgjgjfs', [1, 2, 3])
      
    • 也可以通过切片再拼接的方式实现。注意对字符串、列表、元组都可以用+来实现拼接操作。

    • print(tup1[:4]+(100,)+tup1[4:])
      # (1, 2, (1, 2, 3), 5, 100, 100, 999, 'fgjgjfs', [1, 2, 3])
      
  • 元组的删除

    • 元组只能用del来删除整个元组

    • # 元组的删除
      tup1 = (1,2,(1,2,3),5,999,'fgjgjfs',[1,2,3])
      del tup1
      print(tup1)
      # NameError: name 'tup1' is not defined
      

5.5.6、元组的常用函数

  • len()
  • max()
  • min()

其中max()和min()两个函数要保证比较的元素类型一致

5.6、字典dict

5.6.1、字典的声明

  • 声明方式:通过{}或dict()或字典推导式来声明
  • 字典的特点:
    • 字典是无序的,由键key和对应的值value组成;
    • 字典的键必须是唯一的,值可以不唯一;
    • 每个键与值之间用英文的冒号:隔开,两个键值对之间用英文逗号,隔开
# 字典的声明
# 创建空字典
dict1 = {}
print(type(dict1),len(dict1))
# <class 'dict'> 0# 创建非空字典
dict2={"名称":"乔峰","年龄":18}
print(dict2,type(dict2),len(dict2))
# {'名称': '乔峰', '年龄': 18} <class 'dict'> 2# 键重复的例子
# dict3={"名称":"乔峰","年龄":18,"年龄":22}#通过dict来实例化对象(转字典)
dict4 = dict(name="xiaoming",age=8,like1="篮球")
print(dict4)
# {'name': 'xiaoming', 'age': 8, 'like1': '篮球'}#通过字典推导式声明{结果 for 变量 in 迭代对象} 或者 {结果 for 变量 in 迭代对象 if 布尔表达式};
people = [('小红', 18), ('小明', 45), ('小王', 22)]
dict3 = {k:v for k,v in people}
print(dict3)
# {'小红': 18, '小明': 45, '小王': 22}

5.6.2、根据key取value

方法1:需要根据键名去取,格式:字典名[键名],注意这里一定是传入键名根据键名去取键值。

方法2:通过get方法取键值。

区别:方法1,如果key不存在,报KeyError;方法2则返回None。

# 通过key值取
dict2 = {"名称":"乔峰","年龄":18,"喜欢":["阿朱","阿紫"]}
print(dict2["名称"])
# 乔峰print(dict2["喜欢"][0])
# 阿朱# 通过get方法去取键值
print(dict2.get("年龄"))
# 18

5.6.3、获取字典的所有键,值,以及键值对

  • keys():获取字典的所有键,返回一个可迭代序列
  • values():获取字典的所有值,返回一个可迭代序列
  • items():获取字典的所有键值对,返回一个可迭代序列

注意:以上函数返回的是一个可迭代序列,而不是列表,但可以转成列表

5.6.4、修改字典

  • 修改已存在的值
# 修改已存在的值
dict2 = {"名称":"乔峰","年龄":18,"喜欢":["阿朱","阿紫"]}
#找到已在的key,然后重新赋值,修改的是value
dict2["名称"] = "段誉"
print(dict2)
# {'名称': '段誉', '年龄': 18, '喜欢': ['阿朱', '阿紫']}
  • 新增键值对-单个

在字典中增加一个元素(键值对),格式:字典名[键名]=键值,如果键名在字典中不存在就会增加,如果已存在就会修改它的键值

dict2={"名称":"乔峰","年龄":18,"喜欢":["阿朱","阿紫"]}
dict2["虚竹"] = "憨子"
print(dict2)
# {'名称': '乔峰', '年龄': 18, '喜欢': ['阿朱', '阿紫'], '虚竹': '憨子'}
  • 新增多个键值对:update()方法
  • 作用:在字典中增加多个键值对,相当于字典的拼接,如果键名重复就覆盖原来的键值
dict1={"名称":"乔峰","年龄":18,"喜欢":["阿朱","阿紫"]}
dict2={"学历":"高中","毕业时间":2010,"city":"绵阳"}
dict1.update(dict2)
print(dict1)
# {'名称': '乔峰', '年龄': 18, '喜欢': ['阿朱', '阿紫'], '学历': '高中', '毕业时间': 2010, 'city': '绵阳'}dict1.update({"性别":"Female","公司":"华为"})
print(dict1)
# {'名称': '乔峰', '年龄': 18, '喜欢': ['阿朱', '阿紫'], '学历': '高中', '毕业时间': 2010, 'city': '绵阳', '性别': 'Female', '公司': '华为'}# 字典相加不能用+
print(dict1+dict2)
# TypeError: unsupported operand type(s) for +: 'dict' and 'dict'

5.6.5、字典的删除

5.6.5.1、del关键字

作用:删除整个字典或者根据键删除指定的键值对

dict1={"名称":"乔峰","年龄":18,"喜欢":["阿朱","阿紫"]}
#删除某个键值对-用del 字典名[键名]的方式来删除指定的键值对
del dict1["名称"]
print(dict1)
# {'年龄': 18, '喜欢': ['阿朱', '阿紫']}del dict1
print(dict1)
# NameError: name 'dict1' is not defined
5.6.5.2、pop()

作用:pop方法根据键名删除键值对,并返回键值,如果找不到键名就返回传入的default参数或者KeyError

dict1={"名称":"乔峰","年龄":18,"喜欢":["阿朱","阿紫"]}
print(dict1.pop("年龄"))
# 18print("删除后:",dict1)
# 删除后: {'名称': '乔峰', '喜欢': ['阿朱', '阿紫']}
5.6.5.3、popitem()

作用:删除并返回字典的最后一个键值对,以元组返回。

dict1={"名称":"乔峰","年龄":18,"喜欢":["阿朱","阿紫"]}
print(dict1.popitem())
# ('喜欢', ['阿朱', '阿紫'])print("删除后:",dict1)
# 删除后: {'名称': '乔峰', '年龄': 18}
5.6.5.4、clear()

作用:清空字典

dict1={"名称":"乔峰","年龄":18,"喜欢":["阿朱","阿紫"]}
dict1.clear()
print(dict1)
# {}
5.6.5.5、copy()

作用:复制字典

dict1={"名称":"乔峰","年龄":18,"喜欢":["阿朱","阿紫"]}
dict2=dict1.copy()
print(dict1)
# {'名称': '乔峰', '年龄': 18, '喜欢': ['阿朱', '阿紫']}print(dict2)
# {'名称': '乔峰', '年龄': 18, '喜欢': ['阿朱', '阿紫']}

获取k值和value值、获取keys、values
for k,v in dict2.items()
获取key值和value值后交换

5.6.6、字典的嵌套

字典中的key可以是数值型,字符串,元组(不可变数据类型),不能是list和dict;value可以是数值型,字符串,元组,列表或者另一个字典(可以是任何数据类型)。

dict1={"信息":{"名称":"乔峰","年龄":18,"喜欢":["阿朱","阿紫"]},"级别":[1,2,4],"排名":(1,2,3)}
#1.求年龄
print(dict1["信息"]["年龄"])
# 18#2.求"阿朱"
print(dict1["信息"]["喜欢"][0])
# 阿朱#3.修改年龄为20
dict1["信息"]["年龄"] =20
print(dict1)
# {'信息': {'名称': '乔峰', '年龄': 20, '喜欢': ['阿朱', '阿紫']}, '级别': [1, 2, 4], '排名': (1, 2, 3)}

5.6.7、在格式化输出中传入字典

#字符串
print("小明喜欢%s,今年%d岁了"%("小花",9))
# 小明喜欢小花,今年9岁了#1.字典(类型要对应)
print("小明喜欢%(name)s,今年%(age)d岁了"%{"name":"小花","age":9})
# 小明喜欢小花,今年9岁了##format -这里传参时,*表示是元组,**表示字典,这里传的是字典,是一个整体,需要用**来解包,把字典解包为单个键值对,才能取到
print("小明喜欢{name},今年{age}岁了".format(**{"name":"小花","age":9}))
# 小明喜欢小花,今年9岁了dict1={"name":"小花","age":9}
print("小明喜欢{name},今年{age}岁了".format(**dict1))
# 小明喜欢小花,今年9岁了

5.7、集合set

5.7.1、集合的声明

  • 集合的声明:集合通过{}或set()或集合推导式来声明。
  • 集合的特点:集合是一个无序的不重复元素序列,集合中的元素可以是任意不可变的数据类型
#定义空集合
set1 = set()
set2 = {}# 会表示字典类型
print(type(set1),len(set1))
# <class 'set'> 0#定义非空集合
set1={9,1,5,6,5,1,2,2}
set2 = {"k","k","k","khjj"}
print(type(set1),len(set1))
# <class 'set'> 5
  • 利用集合中的元素不可重复的特点对列表、元组、字符串去重
list1=[1,1,1,2,3,2]
print(type(set(list1))) #得到的是一个集合
# <class 'set'>#列表转换成集合
print(set(list1))
# {1, 2, 3}#集合转换成列表
print(list(set(list1)))
# [1, 2, 3]tup1=(1,1,1,3,3,3)
#元组转换成集合
print(set(tup1))
# {1, 3}#集合转换成元组
print(tuple(set(tup1)))
# (1, 3)str1 = "aaaaffffcccc"
print("".join(set(str1)))
# cafprint((set(str1)))
# {'c', 'a', 'f'}

5.7.2、集合的运算

集合的运算:交集、并集、差集、对称差集

  • 交集:取两个集合的公共部分,也就是同时存在两个集合中的元素
set1={9,1,5,6,5,1,2,2}
set2={1,6,2,20,50}# 运算符
print(set1&set2)
# {1, 2, 6}# 方法
print(set1.intersection(set2))
# {1, 2, 6}
  • 并集:两个集合中的所有元素,重复的元素只算一次
#运算符
print(set1|set2)
# {1, 2, 5, 6, 9, 50, 20}#方法
print(set1.union(set2))
# {1, 2, 5, 6, 9, 50, 20}
  • 差集: set1-set2 的结果存在于 set1 中但不存在于 set2 中的元素( set1减去set1和set2的交集 )
#运算符
print(set1-set2)
# {9, 5}#方法
print(set1.difference(set2))
# {9, 5}
  • 对称差集:取两个集合的交集,然后根据交集取两个集合的补集,最后将补集取并集(并集减去交集),即去除两个集合的交集,各自剩下的元素组成一个新的集合
#运算符
print(set1^set2)
# {50, 20, 5, 9}#方法
print(set1.symmetric_difference(set2))
# {50, 20, 5, 9}

举例:利用集合来判断两个字典的差异。

expect={"name":"张三","age":20,"sex":"男"}
actual={"name":"李四","heigh":170,"sex":"男"}
#实现断言:如果预期和实际不一致,要打印出它们的差异,输出:预期是{"name":"张三","age":20}实际是{"name":"李四","heigh":170}
set_expect=set(expect.items())
set_actual=set(actual.items())
print(set_expect)
print(set_actual)
print("预期是{}实际是{}".format(dict(set_expect-set_actual),dict(set_actual-set_expect)))

5.7.3、集合的常用方法

  • add(x):

    • 作用:将元素x添加到集合中,如果元素已存在,则不进行任何操作

    • set1 = {1,2,3,4,5}
      set1.add("nihao") #不能添加列表和字典
      print(set1)
      
  • update(x):

    • 作用:可以添加元素,且参数可以是列表,元组,字典等,除了数值型

    • set1 = {1,2,3,4,5}
      set1.update([1,6,7])#要添加可迭代的对象,添加字典时,只添加key值
      print(set1)
      
  • remove(x)方法:

    • 作用:将元素x从集合中移除,如果元素不存在,则会发生错误

    • #remove
      set1 = {1,2,3,4,5}
      set1.remove(3) #不会返回删除的值
      print(set1)
      
  • discard(x)方法:

    • 作用:移除集合中的元素,且如果元素不存在,不会发生报错

    • #discard
      set1.discard(3) #也不会返回删除的值
      print(set1)
      
  • pop():

    • 作用:随机删除集合中的一个元素

    • #pop
      set1.pop()#不用传参数,且随机删除一个元素(每次删除的都是集合排序里的第一个元素),并
      返回删除的元素
      print("删除前",set1)
      print(set1.pop())
      print("删除后",set1)
      
  • del关键字 :

    • 作用:删除整个集合

    • #del,删除整个集合
      del set1
      print(set1) # 删除后打印会报错
      
  • len()函数:

    • 作用:计算集合s元素的个数

    • set1 = {1,2,(2,3),"hello"}
      print(len(set1))
      
  • copy():

    • 作用:复制集合

    • set1 = {1,2,(2,3),"hello"}
      set2 = set1.copy()
      print(set1,set2)
      
  • clear():

    • 作用:清空集合

    • set1 ={1,2,4}
      set1.clear()
      print(set1) # 清空过后为空集合set()
      

5.8、range序列

  • range是不可变的序列,元素为int类型,通常和for循环结合起来使用
  • range(起始值=0,终止值,步长=1):表示以指定的步长从起始值取到终止值-1,取值为左闭右开
    • 如果只传一个值,则表示终止值:range(3)
    • 如果传两个值,则表示,起始和终止值:range(1,3)
    • 如果传三个值,则表示起始,终止值和步长:range(1,10,2)
for i in range(5):
print(i)
for i in range(1,5):
print(i)
for i in range(1,5,2):
print(i)

5.9、布尔型bool

  • 布尔型 bool :布尔型只有两个结果即True和False,在python中,布尔型跟数值型参与运算时,
    True相当于1,False相当于0
  • 可以用实例化 bool 类的对象把一个对象转成布尔值,在python中,空字符串、空列表、空元组、
    空字典、空集合都被当做是False;非空即True
a=True
print(type(a))
print(a+5)
print(False*100)
print(bool(111)) #True
print(bool("fff")) #True
print(bool([1,2,4])) #True
print(bool(3,)) #True
print(bool({"A":1})) #True
print(bool({3,'a'})) #True
print(bool("")) #False
print(bool([])) #False
print(bool(())) #False
print(bool({})) #False
print(bool(set())) #False
print(type({}))
print(type(set()))

5.10、特殊类型None

  • None:是python中的一个特殊的数据类型,在函数没有返回值的时候,输出函数的执行结果得到
    的就是None。
print(type(None))
list1=["nihao",2,3]
print(list1.remove(2)) #删除函数,这个只是删除数据没有返回数据,所以打印的是None
  • None与0,null,空字符串,空列表不同

    • None与其他任何数据类型比较都返回False
    • null为 java 里的空,和None一样,都是没有元素

5.11、数据类型总结

5.11.1、可变和不可变类型(对象)

所谓可变对象,是指对象的内容是可变的,比如修改对象的内存时对象的内存地址不改变,例如 list。而不可变的对象则相反,当改变它的内容时对象的内存地址也会改变。

  • 可变数据类型:List(列表)、Dictionary(字典)、Set(集合)
  • 不可变数据类型:Number(数字)、String(字符串)、Tuple(元组)
num1=100
print(id(num1))
num1=101
print(id(num1))
list1=[1,2]
print(id(list1))
list1.append(3)
print(list1)
print(id(list1))

5.11.2、可迭代和不可迭代的类型(对象)

  • 可迭代即可以重复的取出数据,存在 iter() 方法的,就是可迭代的对象

    • 可迭代:List(列表)、Dictionary(字典)、Set(集合)、String(字符串)、Tuple(元
      组)
    • 不可迭代:Number(数字)、 bool (布尔类型)
#数据类型,后面能有__iter__()方法,就是可迭代的
[].__iter__()
"".__iter__()
{2,1}.__iter__()
{"name":"小明","age":18}.__iter__()

5.11.3、有序的和无序的类型(对象)

  • 所谓序列,指的是一块可存放多个值的连续内存空间,这些值按一定顺序排列,可通过每个值所在位置的编号(称为索引)访问它们。

    • 有序:List(列表)、String(字符串)、Tuple(元组)
    • 无序:Dictionary(字典)、Set(集合)
      • 字典在3.6之前的版本是无序的,从3.6版本开始,字典是有序的,字典的顺序就是元素存入的顺序

5.11.4、值类型和引用类型

Python数据类型分为值类型和引用类型, 下面我们看下它们的区别:

  • 值类型:int、float、str、tuple,本身不允许被修改
  • 引用类型:list、set、dict,本身允许被修改

六、Python运算符

  • 算数运算符
  • 比较运算符
  • 逻辑运算符
  • 三目运算符
  • 身份运算符
  • 成员运算符
  • 赋值运算符

6.1、算数运算符

以下假设变量 a=2,变量 b=3:

运算符 描述 实例
+ 加 - 两个对象相加 a + b 输出结果5
- 减 - 得到负数或是一个数减去另一个数 a - b 输出结果 -1
* 乘 - 两个数相乘或是返回一个被重复若干次的字符串 a * b 输出结果 6
/ 除 - x除以y b / a 输出结果 1.5
% 取模 - 返回除法的余数(取余) b % a 输出结果 1
** 幂 - 返回x的y次幂 a**b 为2的3次方为8
// 取整除 - 向下取接近商的整数 9//2结果为4,-9//2结果为-5

6.2、比较运算符

以下假设变量 a=2,变量 b=3:

运算符 描述 实例
== 等于 - 比较对象是否相等 (a == b)返回False。
!= 不等于 - 比较两个对象是否不相等 (a != b) 返回 True。
> 大于 - 返回x是否大于y (a > b) 返回False。
< 小于 - 返回x是否小于y。所有比较运算符返回1表示真,返回0表示假。
这分别与特殊的变量True和False等价。
注意,这些变量名的大写。
(a < b) 返回 True。
>= 大于等于 - 返回x是否大于等于y。 (a >= b)返回False。
<= 小于等于 - 返回x是否小于等于y。 (a <= b)返回True。

注意:<> 在 python2.x 中这个也表示不等于,在 python3.x 中不支持这个符合

6.3、逻辑运算符

  • and:逻辑与,表示两个条件同时满足
  • or:逻辑或,表示两个条件满足其中一个
  • not:逻辑非,表示取反

优先级:括号 > not > and > or

6.4、身份运算符

  • is:判断两个对象是同一个对象
  • is not:判断两个对象不是同一个对象

is比较的是两个变量的内存地址,is not和is相反。运算结果是布尔值。

a="hello world"
b="hello world"
print(id(a),id(b))
print(a is b)

is与==的区别: is比较的是内存地址,是判断两个对象是否是同一个对象,==比较的是值,是判断两个对象的值是否相等。

6.5、成员运算符

  • in
  • not in

格式:a in b,表示判断a是否是b的成员

if 'a' in 'hashdaskak':print("在的")
if "b" not in 'hashdaskak':print("不在")
#in经常用在for循环中,遍历元素
for i in [1,2,3,4,5,6,7,8]:print(i)
#判断某个值是否在字典的value中
dict1={"name":"张三","age":20}
if "张三" in dict1.values():print("在里面")

6.6、赋值运算符

以下假设变量a为2,变量b为3:

运算符 描述 实例
= 简单的赋值运算符 c = a + b 将 a + b 的运算结果赋值为 c
+= 加法赋值运算符 c += a 等效于 c = c + a
-= 减法赋值运算符 c -= a 等效于 c = c - a
*= 乘法赋值运算符 c *= a 等效于 c = c * a
/= 除法赋值运算符 c /= a 等效于 c = c / a
%= 取模赋值运算符 c %= a 等效于 c = c % a
**= 幂赋值运算符 c = a 等效于 c = c a
//= 取整除赋值运算符 c //= a 等效于 c = c // a
:= 海象运算符,可在表达式内部为变量赋值。 Python3.8
版本新增的运算符。
num_1 = 5
print(num_2 := num_1 + 5)
print(num_2)#输出:
10
10#在这个示例中,赋值表达式可以避免调用len()两次
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
if (n := len(a)) > 10:print(f"List is too long ({n} elements, expected <= 10)")

6.7、三元运算符

语法: 变量名= 结果值1 if bool表达式 else 结果值2

#用if...else...语句实现
year1 = int(input("请输入年份:"))
if year1%2 ==0:print("偶数")
else:print("奇数")#三元运算符格式
year1 = int(input("请输入年份:"))
print("偶数" if year%2==0 else "奇数")

七、流程控制

  • 条件判断
  • 循环

7.1、条件判断

条件判断用if语句实现,if语句的几种格式:

  • if… 表示满足条件,则执行相应的操作,否则什么都不执行;
  • if…else… 表示如果满足条件则执行if后面的操作,否则执行else后面的操作;
  • if…elif…elif…else… 表示多条件判断,如果满足第一个条件就执行第一个操作,如果满足第二个条件就执行第二个操作,…,如果都不满足就执行else后面的操作。

7.1.1、if

作用:如果if后面的布尔表达式值为True就执行if下的代码块,如果为False就不执行

#从键盘输入一个数字,如果大于10就输出“大于10”
num1=int(input("请输入一个数字:"))
if num1>10:print("大于10")#结合布尔值(为True则执行,为False则不打印
if 8:print("你好")
if "不为空":print("真的")#结合成员运算符(in、not)-满足条件执行print,不满足则不执行
str1 = "adgcgag"
if "ad" in str1:print("在里面")

7.1.2、if…else…

作用:如果if后面的布尔表达式值为True就执行if下的代码块,如果为False就执行else下的代码块。

#从键盘输入一个数字,如果大于10就输出“大于10”,如果不大于10就输出“不大于10”
num1=int(input("请输入一个数字:"))
if num1>10:print("大于10")
else:print("不大于10")
#从键盘输入一个整数,如果整数是奇数,就打印奇数,如果不是奇数,就打印偶数
third=int(input("请输入一个整数:"))
if third%2==1:print("奇数")
else:print("偶数")
#注意if和else是同级的,应该对齐。

7.1.3、if…elif…elif…else…

作用:从第一个条件开始逐一判断,遇到第一个满足的条件就执行它下面的语句,并结束判断不再往下判断。

#从键盘输入一个数字,如果大于10就输出“大于10”,如果小于10就输出“小于10”,否则输出等于10
num1=int(input("请输入一个数字:"))
if num1>10:print("大于10")
elif num1<10:print("小于10")
else:print("等于10")
#举例:当遇到某个条件满足时就不会再往下判断
forth=int(input("请输入一个整数:"))
if forth<10:print("小于10")
elif forth>=10:print("大于10")
elif forth>=20:print("大于20")
else:print("其它")

7.2、循环

  • while循环
  • for循环

7.2.1、while循环

while循环:当满足循环条件时就执行循环体里的代码,直到循环条件不满足为止。中括号表示else是可选的,如果有else,那么else后面的代码会在循环正常结束后执行。使用while循环一定要有修改循环条件的语句,否则会造成死循环(在某条件下,一直执行语句,直到条件为False)。

# 不带else语句
i=1 #给个初始值
while i<=10: #1.条件限制print(i)i+=1 #2.条件,递增
#两个条件要结合,如果不限制,会导致死循环#带else语句
i=1
while i<=10: #1.条件限制print(i)i+=1 #2.条件,递增
else:print("打印完毕")#实现1+2+3+...+100,并输出计算结果
num1=0
i=1
while i<=100:num1+=ii+=1
else:print(num1)
#思考:1*2*3*...*100 ?
  1. 当布尔表达的值为True的时候,就执行循环体的代码,直到布尔表达的值为False的时候或者被break;
  2. else 语句是可选的,如果有else语句,当循环正常结束(不是被break语句结束的情况)后会执行else后面的语句,如果循环是被break掉,就不会执行else后面的操作。

7.2.2、for循环

迭代(Iteration):指重复执行某个操作,迭代最常用的表现就是遍历,经常用for循环来遍历可迭代对象( Iterable ),常见的可迭代对象包括字符串、列表、元组、集合和字典等。

#1.将字符串"helloworld"遍历出来添加到列表list1中
list1=[]
for i in "helloworld":list1.append(i)
print(list1)#2.遍历元组中的元素
tuple1 = (1,3,5,6,7)
for i in tuple1:print(i)
else:print("遍历完成")#3.用for循环遍历字典
dict1={"姓名":"张三","性别":"男","年龄":20}
#遍历字典,默认取到的是字典的key
for i in dict1:print(i)
#遍历字典的key
for i in dict1.keys():print(i)
#遍历字典的value
for i in dict1.values():print(i)
#遍历字典的键值对
for i,j in dict1.items():if i=="年龄":print(i,j)#4. 用for循环实现1+2+3+...+100,并输出计算结果

while循环和for循环的区别:while循环执行前,循环次数是不确定的;for循环在循环前执行次数是已经确定的。

7.2.3、循环的嵌套

7.2.3.1、while中套while循环
# 在10中找两个数i和j,满足条件j <= (i / j)时,如果i能除尽j则打印“能除尽”并打印i和j的值,如果
不满足则打印“不满足条件”并打印不满足条件的i和j的值
i = 2
while (i < 10):j = 2while (j <= (i / j)):if not (i % j):print("能除尽",i,j)j = j + 1else:print("不满足条件",i,j)i = i + 1
print("算完")
7.2.3.2、for循环中套for循环
# 九九乘法表
for i in range(1,10): # 依次取数1到9for j in range(1,i+1): # 根据i的取值来取值,i取1时,j的范围也是1print("{} x {} = {}\t".format(j,i,i*j),end="") # 根据上面两个循环取出的书打印格式化数据。print()# 把一次循环的数据打印完成后换行
7.2.3.3、冒泡排序
arr = [64, 34, 25, 12, 22, 11, 90]
# 遍历所有数组元素
for i in range(len(arr)):for j in range(0, len(arr) - i - 1):if arr[j] > arr[j + 1]:arr[j], arr[j + 1] = arr[j + 1], arr[j]
else:print(arr)

7.2.4、循环中的continue/break/pass语句

  • continue
  • break
  • pass
7.2.4.1、continue语句

作用:continue的作用是结束本次循环(在某一次循环中遇到continue语句时,直接结束本次循环,不执行continue后面的代码,而开始执行下一次循环)。

# 在0到10的数字中打印所有奇数,不是奇数的就不打印出来
a = 0
while a < 10:a += 1if a%2 ==0:continue # 跳过本次循环,进入下一次循环print("奇数",a)
else:print("没有奇数了")#3、输出0到100之间被3整除的整数,如果这个数能被5整除则不输出
for i in range(101):if i%3==0:if i%5==0:continueprint(i)
7.2.4.2、break语句

作用:是结束本层循环,可以跳出for和while的循环体(所有循环),任何对应的循环else块将不执行。

# 整数0到10中,取能被2整除的数,取到第一个数就结束循环,不执行后面的代码
a = 0
while a < 10:a += 1if a%2 ==0:break # 满足上面条件了,直接结束本层所有循环,不执行后面的语句print("奇数",a)
else:print("没有奇数了")
7.2.4.3、pass语句

作用:是空语句,是为了保持程序结构的完整性。不做任何事情,一般用做占位语句

# 输出 Python 的每个字母
for str1 in 'Python':if str1 == 'h':pass # 占位,不做任何操作print(str1)
# 每层不同的*数量,依次递增(差一)
for a in range(6):print("*"*a)# 每层不同,递增差二
#1.方法1
for b in range(1,8,2):print("*"*b)#2.方法二
b = 5
for b in range(1,b+1):print("*"*(2*b-1))# 金字塔
cengshu = 7
for b in range(1,cengshu+1):print(" "*(cengshu-b),"*"*(2*b-1))# 金字塔,中间为空
for i in range(6): #循环6次打印6行for j in range(5-i): #打印空格每次循环递减print(' ',end='')for q in range(2*i+1): #打印星星if q==0 or q==2*i: #判断打印星星位置,在开头,结尾和最后一行打印星星print('*',end='')else:print(' ',end='')print() #每行循环结束后换行

八、推导式

  • 列表推导式
  • 字典推导式
  • 集合推导式
  • 生成器推导式

8.1、列表推导式

列表推导式的语法:[结果 for 变量 in 可迭代对象] 或者 [结果 for 变量 in 可迭代对象 if 布尔表达式]

# 列表推导式
# 普通形式
list1 = []
for i in range(1,101):if i%2==0:list1.append(i)
print(list1)
# 列表推导式完成
print([i for i in range(1,101) if i%2==0])
# 列表推导式不加if
print([i for i in range(2,101,2)])
#统计字符串中只出现一次的字符,以列表返回字符串
str1 = "helloworld"
print([i for i in str1 if str1.count(i)==1])

8.2、字典推导式

语法:{结果 for 变量 in 迭代对象} 或者 {结果 for 变量 in 迭代对象 if 布尔表达式};注意字典推导式的结果是键值对,即 key:value

# 字典推导式
tupl1 = (("姓名", "张三"), ("年龄", 20), ("体重", 190), ("身高", 180))
print({i: j for i, j in tupl1})
# 交换key和value的位置
print({j:i for i,j in tupl1})
# 加判断条件
print({i:j for i,j in tupl1 if j != 190})
# 统计字符串中每个字符出现的次数,以字典返回
str1 = "helloworld"
print({i:str1.count(i) for i in str1})
# 统计字符串中只出现一个的字符,以字典返回字符及出现次数
str1 = "helloworld"
print({i:str1.count(i) for i in str1 if str1.count(i)==1})
print({i for i in str1 if str1.count(i)==1})

8.3、集合推导式

语法:{结果 for 变量 in 迭代对象} 或者 {结果 for 变量 in 迭代对象 if 布尔表达式};集合推导式跟字典推导式的区别是:字典推导式的结果是键对,集合推导式的结果是单个结果

# 集合推导式
dict1 = {"姓名":"张三","年龄":20,"体重":180,"身高":180}
print({x for x in dict1.keys()})
print({x for x in dict1.values()})
# 加if判断,只取int类型的数据
print({x for x in dict1.values() if type(x)==int})

8.4、生成器推导式

语法:(结果 for 变量 in 可迭代对象)或者(结果 for 变量 in 可迭代对象 if 布尔表达式)

# 生成器推导式
d = (a**2 for a in range(1,10))
# 用元组形式展示数据
print(tuple(d))

九、函数

定义:函数就是完成特定功能的一个语句组,这组语句可以作为一个单位使用,并且取一个名字,这个名字叫做函数名

函数的作用:

  1. 可以通过函数名在程序不同的地方多次调用,这样就不用在不同的地方重复编写这些语句
  2. 函数是实现特定功能的一段代码,通过函数可以方便地重复使用代码,让程序的结构更清晰,方便代码的走读。
  3. 函数能提高应用的模块性,和代码的重复利用率

9.1、内置函数(内建函数)

系统内置函数,比如: len()/max()/min()/print()/input()/ord()/chr()/… ;内置函数也叫内建函数。

num = input("请输入密码:")
print(type(num)) # 打印输入信息的数据类型

9.2、自定义函数

9.2.1、函数的声明与调用

定义函数的语法:

# 定义函数
def 函数名(参数列表):语句体
# 调用函数
函数名()

说明:

  • 函数代码块以def关键字开头,后接函数名称和圆括号(),圆括号中间放传入的参数,也可以不传入参数,()后面加一个英文的冒号;
  • 函数的第一行语句可以选择性地添加注释,用来解释函数的作用、参数、返回值等;
  • return语句结束函数,选择性地返回一个值给调用方。不带return语句就相当于返回None。
# 定义函数
def speak():name = "小明"print("你好!{}".format(name))
# 调用函数
speak()

9.2.2、return语句

return语句用于结束函数,选择性的向调用方返回一个表达式或者一个值。不带参数值得return语句返回None

  • 情况一:同级的多个return只返回第一个return的值,因为函数执行时遇到第一个return返回后就结束了
  • 情况二:条件判断中,只返回第一个满足条件的第一个return的值,如果都不满足,则返回None
# 情况一:同级的多个return只返回第一个return的值
def add(a,b):print(a)print(b)return a+breturn a-bprint(add(1,2))# 条件判断中,只返回第一个满足条件的第一个return的值,如果都不满足,则返回None
def add(a,b):if a>b:return a-bif a<b:return a+bprint(add(3,4))
print(add(4,3))

9.2.3、函数的说明与注释

函数的说明举例:

def f1(a,b):"""传入两个int类型的参数,返回它们的差:param a:第一个int类型参数:param b:第二个int类型参数:return:返回a-b:rtype:int类型"""return a-b# 使用__doc__属性来查看函数的说明
print(f1.__doc__)

函数的注释举例:

def f2(a:list , b:list)->list:a.append(b)return a# 通过__annotations__属性来查看函数的注释
print(f2.__annotations__)

9.2.4、函数的参数

9.2.4.1、形参和实参
  • 形参:在定义声明时所传入的参数
  • 实参:在调用函数时所传入的参数
# name,age为形参定义时
def speak(name,age):print(name)print(age)# 中间的值为实参,即调用时传入的值为实参
speak("小河",24)
9.2.4.2、位置参数

在调用函数时,必须以形参的顺序传入实参,调用时的数量必须和声明时的一样,不能传多也不能传少。这种传入参数的方式叫位置参数。

def speak(name,age,like):print(f"小明的女朋友{name},今年{age},喜欢{like}")# 调用函数
speak("小牛",25,"包包")
9.2.4.3、关键字参数

函数调用时指定形参名称来传入实参,传入的实参顺序可以与声明的形参顺序不一致,但不能传多也不能传少,这种方式叫关键字参数。( Python 解释器能够用参数名匹配参数值)

#声明一个函数
def speak(name,age,like):print("小明的女朋友{},今年{},喜欢{}".format(name,age,like))
#调用函数
speak(name="小茵",age=18,like="逛街")
speak(like="逛街",name="小茵",age=18)
9.2.4.4、默认参数
  • 默认参数就是在声明函数的时候,给参数一个默认值,在调用时如果不对这个参数传值,就使用默认值,如果对这个参数传值,就使用实际传入的值;
  • 如果在声明函数的时候,有默认参数,需要把默认参数放到位置参数之后。
def speak(name,age,like="看电影"):print("小明的女朋友{},今年{},喜欢{}".format(name,age,like))
speak("小茵",18,"逛街") #可改默认参数的值
speak("小茵",18)
9.2.4.5、不定长参数

不定长参数包括不定长位置参数和不定长关键字参数两种形式,分别在形参前加*和**来表示。不定长参数在实际调用时,可以传入0个、1个或多个实参。(你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述 2 种参数不同,声明时不会命名。加了星号 * 的参数在调用时会以元组(tuple)的形式导入,存放所有未命名的变量参数)

  • 不定长位置参数:形参前加*,可以接收任意多个实参,接收的实参以元组的形式参与函数内的运算。
# 声明一个不定长参数函数
def f1(*args):print(args)return sum(args)#方法一:调用不定长参数的函数,可以传入0个、1个或多个参数,传入的参数是按元组参与函数运算
print(f1(1))
print(f1(1,2,3))#方法二:调用不定长参数的函数,将多个参数放到列表、元组或集合中传入,但需要在列表、元组或集合前加*来对列表或元组解包,把列表中的元素作为多个参数一一传给函数print(f1(*[1,2,3]))
print(f1(*(1,2,3)))
  • 不定长关键字参数:形参前加**,可以接收任意多个实参,接收的实参以字典的形式参与函数内的运算。
# 声明一个不定长关键字参数函数
def f1(**kwargs):return kwargs# 方法一:调用不定长参数函数,可以传入0个、1个或多个参数,必须以关键字参数的形式传入,传入的参数是按字典的形式参与函数运算
print(f1())
print(f1(name = "张三"))
print(f1(name = "张三",age = 24))
print(f1(name = "张三",age = 24,sex = "男"))# 方法二:调用不定长参数函数,将多个参数放到字典中传入,但需要在字典前加**
print(f1(**{"name":"张三"}))
print(f1(**{"name":"张三","age":20}))
print(f1(**{"name":"张三","age":20,"sex":"男"}))

注意:在函数内同时使用不定长位置参数(*)以及不定长关键字参数(**)时,不定长位置参数必须在不定长关键字参数之前。

9.2.4.6、位置参数、默认参数以及不定长参数 同时使用

如果在声明和使用函数时,同时存在位置参数、默认参数以及不定长参数,必须遵守以下顺序:1.位置参数;2.不定长位置参数;3.默认参数;4.不定长关键字参数。

# 格式化字符串-混合传值
def person(a, *tuple1, like="篮球", **dict1):print(a)print(dict1)print("{name}今年{age}岁了,每隔{}天打{}次{}".format(a, *tuple1, like, **dict1))# 调用函数
person(1, *(3,), "足球", **{"name": "小王", "age": 30})  #调用函数并传参

9.2.5、匿名函数(lambda)

  • 又称之为高效函数,一次性函数,丢弃函数,也叫lambda函数(没有函数名的函数);因为在声明的时候可以直接调用(不需要先声明(定义)然后再调用)。而普通函数是先定义后再进行调用进行输出,比如是def 函数名():后面用的时候才进行调用。
  • 匿名函数的定义语法:lambda 变量名… : 语句表达式
  • 匿名函数的调用:直接用括号把匿名函数括起来,在后面再用括号传参
# 求两个数的和
# 普通的函数
def f1(x,y):return x+y
print(f1(3,7))# 匿名函数
print((lambda x,y:x+y)(3,7))

匿名函数举例:

# 例1:传入两个整数参数,以列表返回两个整数之间所有整数
x = int(input("输入x:"))
y = int(input("输入y:"))
print((lambda x,y:list(range(x,y+1)) if x<y else list(range(y,x+1)))(x,y))# 例2:传入两个整数参数,求该列表中的所有数的和
x=int(input("输入x:"))
y=int(input("输入y:"))
print(sum((lambda x,y:list(range(x,y+1)) if x<y else list(range(y,x+1)))(x,y)))

9.2.6、函数的递归

  • 函数内部可以调用其他函数,当然在函数内部也可以调用自己,在函数内部调用自己叫着函数的递归
  • 函数内部的代码是相同的,只是针对参数不同,处理的结果不同,当参数满足一个条件时,函数不再执行。这个非常重要,通常被称为递归的出口,否则会出现死循环。
#举例1:通过递归实现阶乘,声明一个函数,传入参数n,实现1*2*…*n
def f1(n):# print(n)if n == 1:return 1return n*f1(n-1)print(f1(10))#举例2:通过递归实现求和运算,实现声明一个函数,传入参数n,实现1+2+...+n
def f2(n):if n == 1:return 1return n+f2(n-1)print(f2(10))#举例3:通过递归实现取出一个列表中的所有数字,并返回一个列表
list2 = []
def get_num(list):for i in list:global list2if type(i)==int:# print("i=%d"%i)list2.append(i)else:print("不满足条件的数据:",i)return "满足条件的数据:{}".format(list2)
print(get_num([10,3,8,9,6,8,"hello",(5,7,11),[99,98],{888,777}]))##举例4:通过递归实现列表中的所有数字求和
sum1=0
def get_sum(list):for i in list:if type(i)==int:global sum1sum1+=ielse:print("不满足条件的数据",i)return sum1
print(get_sum([10,3,8,9,6,8,"hello",(5,7,11),[99,98],{888,777}]))

9.2.7、函数的全局变量和局部变量

9.2.7.1、全局变量与局部变量的概念
  • 全局变量:在函数的外面定义的变量就叫全局变量,所有函数可以调用;
  • 局部变量:在函数的内部定义的变量叫局部变量,局部变量只能当前函数内调用。
# 全局变量
a = 1def f1():# 局部变量bb = 2# 在函数f1中调用全局变量a和局部变量b都可以成功print(a)print(b)def f2():# 在函数f2中调用全部变量a可以成功,但调用局部变量b不成功print(a)# 报错,nameerror,b未定义print(b)f1()
f2()
9.2.7.2、global关键字

global关键字用来在函数或其他局部作用域中使用全局变量。

  1. 如果局部要对全局变量进行修改,而不使用global关键字。
count = 0
def global_test():count += 1print(count)
global_test()# 输出:
UnboundLocalError: cannot access local variable 'count' where it is not associated with a value
  1. 如果局部要对全局变量修改,应在局部声明该全局变量。
count = 0
def global_test():global countcount += 1print(count)
global_test()
print(count)# 输出:
1
1
  1. 如果局部不声明全局变量,并且不修改全局变量,则可以正常使用。
count = 0
def global_test():print(count)
global_test()# 输出
0

十、迭代、可迭代对象、迭代器、生成器

10.1、迭代iteration

迭代Iteration:所谓迭代就是重复运行一段代码语句块的能力,就好比在一个容器中进行一层一层遍历数据,在应用过程中for循环最为突出。迭代就是从某个容器对象中逐个地读取元素,直到容器中没有元素为止。迭代迭代,更新换代,在上一次基础上更新成新的东西

for i in "hello world":print(i,end="\t")

10.2、可迭代对象iterable

  1. 用 dir() 函数来查询是否包含 iter() 方法;
  2. 对象.方法的方式去调用看有没有 iter 方法;
  3. 通过内置的实例对象函数 isinstance 判断,可迭代对象是 Iterable 类的实例,返回True就说明是可迭代对象,False则表示不是可迭代对象。
#用dir()函数打印数据的全部方法,看看是否包含__iter__()方法
# print(dir(list1))#查看某个元素或序列是否有.__iter__()方法,有就是可迭代的对象
"hello world".__iter__()
[2].__iter__()
(1,).__iter__()
{"name":"jack"}.__iter__()
{"name":"jack"}.keys().__iter__()
range(11).__iter__()
list1 = []
a = 9#通过内置的实例对象函数isinstance判断
from collections.abc import Iterable,Iterator
print(isinstance(list1,Iterable))
print(isinstance(a,Iterable))

10.3、迭代器iterator

  • 迭代器 Iterator :迭代器一定是可迭代对象,迭代器中有两个特殊的方法是 iter() 和__next__() 方法
  • 创建迭代器的方法:使用内置的 iter() 函数或者 iter 方法来创建迭代器
# 将列表转换为迭代器
list1 = [1,3,5,7,9]
it1 = iter(list1)
it2 = list1.__iter__()
print(type(it1))
print(type(it2))
# 打印迭代器中的数据,每次只能打印一个元素,有多少元素就需要打印多少次
print(next(it1))
print(it1.__next__())
print(it1.__next__())
print(it1.__next__())
print(it1.__next__())
# print(it1.__next__())
  • 迭代器的特点是:
  1. 迭代器一定是可迭代对象;
  2. 迭代器通过next()函数或者 next() 方法取值,每迭代一次取一个值,只能往前取不能后退;
  3. 当取完最后一个值的时候,再执行next()函数或者 next() 方法会报 StopIteration 异常,表示取完了。
  • 判断一个对象是迭代器还是迭代对象,可以使用以下两种方法:
  1. 通过对象包含 iter() 和 next() 方法决定;
  2. 需要判定是迭代器还是迭代对象可以通过实例对象函数isinstance()进行判断,迭代器和可迭代对象的对象类型分别是 Iterator 和 Iterable (都是 collections.abc 模块下)
from collections.abc import Iterable,Iterator
# Iterable是判断是否是迭代器
# Iterator是判断是否是可迭代对象
print(isinstance(list1,Iterable))
print(isinstance(list1,Iterator))
print(isinstance(iter(list1),Iterator))
print(isinstance(it1,Iterable))
print(isinstance(it1,Iterator))# 计算1+2+3+...+100000000
print(sum(list(range(1,100001))))
print(sum(iter(range(1,100001))))

迭代器的优缺点:

  1. 迭代器优点:节省内存,迭代器在内存中相当于只占一个数据的空间,因为每次取值都会把上一条数据在内存中释放,加载当前的此条数据。
  2. 迭代器的缺点,不能直观的查看里面的数据。取值时不走回头路,只能一直向下取值。

10.4、生成器Generator

生成器Generator:在 Python 中,生成器的本质就是一个迭代器,使用了yield 的函数被称为生成器(generator)。

10.4.1、return和yield的区别

  • return的作用:
  1. 给调用者返回值;
  2. 执行遇到第一个return语句时就结束函数。
  • yield的作用:
  1. 给调用者返回值;
  2. yield把函数变成了生成器;
  3. 生成器运行时遇到yield后先返回再挂起。

10.4.2、生成器怎么创建

创建生成器的方法:

  1. 通过关键字yield把函数变成生成器;
  2. 通过生成器推导式创建生成器:(结果 for 变量 in 可迭代对象)
# 例1:使用yield关键字把函数变成装饰器
def generator():yield 1yield 2yield 3# 例2:通过生成器推导式创建生成器
print(type((i for i in range(11))))
print((i for i in range(11)))

10.4.3、生成器的运行

通过调用next()函数或者__next__()方法来运行生成器,next()函数实际也是调用__next__()方法。
带有 yield 的函数执行过程比较特别:

  1. 调用该函数的时候不会立即执行代码,而是返回了一个生成器对象;
  2. 当使用 next()作用于返回的生成器对象时 (在 for 循环中会自动调用 next() ) ,函数开始执行,在遇到 yield 的时候会『暂停』,并返回当前的迭代值;
  3. 当再次使用 next() 的时候,函数会从原来『暂停』的地方继续执行,直到遇到 yield语句,如果没有 yield 语句,则抛出异常;
# 在定义函数时,使用yield来返回值
def generator():yield 1yield 2yield 3# 直接这个函数的调用结果,得不到返回的值
print(generator())# 使用next()函数或者__next__()方法来运行该函数,但如下每次执行时都返回第一个值,因为每次调用的时候都会创建一个生成器
print(next(generator()))
print(next(generator()))
print(generator().__next__())# 可以调用一次函数,对返回结果赋值给一个变量,这样可以获取生成器所有返回的值
def generator():yield 1yield 2yield 3
gt = generator()
print(next(gt))
print(next(gt))# 使用for循环执行生成器
for i in generator():print(i)

10.4.4、send()方法

通过send()方法也可以执行生成器,同时可以向生成器传入值。

send()方法与next()函数的区别:

  1. send() 方法与 next() 函数都用来执行生成器;
  2. send()方法会将传入的值赋给上次中断时yield语句的执行结果,然后再执行生成器,从而实现与生成器方法的交互;
  3. 在执行生成器时,如果第一次执行使用 send() 方法,因为没有挂起的yield语句来接收传入的值,所以会报 TypeError 异常。
  4. 简单地说, send() 方法就是 next() 函数的功能,加上传值给 yield 。
# 例1:第一次使用send()方法执行生成器
def generator1():yield 1yield 2yield 3
gt1=generator1()
# print(gt1.send(100)) # 报错,需要先执行next()
# print(gt1.send(200))
# 例2:第一次使用next()执行生成器,第二次开始使用send()执行生成器并传入值
def generator2():a=yield 1b=yield ayield bc=yield 2print(c)yield c
gt2=generator2()
print(next(gt2))
# 传入100给yield 1的执行结果,也就是a,然后再执行yield a,返回100,再挂起
print(gt2.send(100))
# 传入2.5给yield a的执行结果,也就是b,然后再执行yield b,返回2.5,再挂起
print(gt2.send(2.5))
# 传入'abc'给yield b的执行结果,但并没有引用他,然后执行yield 2,返回2,再挂起
print(gt2.send('abc'))
# 传入efg给yield 2的执行结果,也就是c,然后再打印c,最后再执行yield c,返回efg
print(gt2.send('efg'))

10.4.5、生成器与迭代器的区别

  • 生成器:
  1. 生成器本身是一种特殊的迭代器,也就是说生成器就是迭代器。
  2. 生成器会自动实现迭代器协议,也就是说只要我们yield后,自动就生成了next对象包括StopIteration等结构。
  3. 生成器使用yield语句返回一个值。yield语句挂起该生成器函数的状态,保留足够的信息。对生成器函数的第二次(或第n次)调用,跳转到函数上一次挂起的位置。生成器不仅“记住”了它的数据状态,生成还记住了程序执行的位置。
  • 迭代器:
  1. 迭代器是一种支持next()操作的对象。它包含了一组元素,当执行 next() 操作时,返回其中一个元素;
  2. 当所有元素都被返回后,再执行 next() 报异常 StopIteration ;
  3. 生成器一定是可迭代的,也一定是迭代器对象。
  • 它们的区别:
  1. 迭代器是访问容器的一种方式,也就是说容器已经出现。我们是从已有元素拓印出一份副本,只为我们此次迭代使用。而生成器则是,而生成器则是自己生成元素的。也就是前者是从有到有的复制,而后者则是从无到有的生成。
  2. 在用法上生成器只需要简单函数写法,配合yield就能实现。而迭代器真正开发中很难使用到。我们可以把生成器看做,python给我们提供的特殊接口实现的迭代器。

十一、高阶函数

11.1、map()函数

map() 函数语法: map(function,iterable)

作用:map()是 Python 内置的高阶函数,它接收一个函数 function 和一个 iterable ,并通过把函数function依次作用在 iterable 的每个元素上,并返回一个新的迭代器;map()函数也可以接收多个iterable。

# 传入一个序列的例子
def f(x):return x*x
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]for i in map(f, list1):print(i)
# 传入多个序列的例子
def f(x, y):return x*ylist1 = [1, 2, 3]
list2 = [4, 5, 6]
for i in map(f, list1, list2):print(i, end="\t")

注意:map()函数不改变原有的迭代器,而是返回一个新的迭代器。

11.2、reduce()函数

reduce()函数语法:reduce(function, iterable[, initializer])

作用: reduce() 函数也是Python内置的一个高阶函数, reduce() 函数接收的参数和 map() 类似,一个函数 function ,一个 iterable ,但行为和 map() 不同,reduce()函数的作用是用传给 reduce 中的function函数先对 iterable 中的第 1、2 个元素进行运算,得到的结果再与第3个数据用 function 函数运算,最后返回运算的结果。

def add(x, y):print("x=%d,y=%d" % (x, y))return x + ysum1 = reduce(add, [1,2,3,4,5]) # 相当于计算1+2+3+4+5,得到15
print(sum1)
# reduce()还可以接收第3个可选参数,作为计算的初始值。如果把初始值设为1000
sum2 = reduce(add, [1,2,3,4,5], 1000) # 相当于计算1000+1+2+3+4+5,得到1015
print(sum2)

11.3、filter()函数

filter()函数语法: filter(function, iterable)

作用:filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换。该函数接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新的迭代器对象中。

def is_odd(n):return n%2 == 0odd = filter(is_odd, [1,2,3,4,5,100])
print(list(odd))

11.4、sorted()函数

sorted函数语法:sorted(iterable, reverse=False)

作用:sorted() 函数对所有可迭代的对象进行排序操作。

面试常问题:sorted()函数与sort()方法的区别?

  1. sort()方法是应用在list对象上的方法,sorted()函数可以对所有可迭代的对象进行排序操作;
  2. list对象的sort()方法是对已经存在的列表进行操作,没有返回值,而sorted()函数返回的是一个新的list对象,而不是在原来的基础上进行的操作。
list1 = [5, 7, 6, 3, 4, 1, 2]
list2 = sorted(list1)
print(list1) # 原来的列表顺序不变
print(list2) # 新生成了一个列表

十二、面向对象

12.1、面向对象的基本概念

  • 怎么理解面向对象?

面向对象是一种编程思想,就是把要解决的问题抽象成一个一个的类,在类里面定义属性和方法(这个过程叫封装),在使用的时候创建类的对象来调用这些属性和方法,解决具体的问题

  • 类class和对象object:

类class:类是抽象的,类具有事物的描述(属性,静态的特征)和操作(方法,动态的特征);比如学生类,它具备的属性有姓名、年龄、身高、体重等,它具备的方法有学习、吃饭、睡觉、打闹等等。
对象object:对象是具体的事物,它具有特定事物的描述和操作,类相当于一个模板,对象就是根据这个模板创建出来的具体个体。

**怎么理解类和对象?**类是一类事物的统称,相当于一个模板;对象是类的一个个体,通过类来创建对象,一个类可以创建多个对象根据类创建出来的对象,也具备类一样的属性和方法,可以根据类去创建多个对象。

12.2、类的声明与实例化

类是对客观世界中事物得抽象描述,而对象是类实例化后的实体。

12.2.1、类的声明

  • 使用class关键字定义一个类,类名一般用大驼峰法表示,比如DemoClass

  • 类的声明语法:

# 定义一个类
class People:#类的属性:用变量来表示type="高等生物"#类的方法:用函数来表示,但注意方法和函数两个概念有区别def eat(self):return "用筷子吃饭!

12.2.2、属性与方法

  • 属性和方法统称类的成员。
  1. 属性:类的静态特征叫属性,比如学生类的姓名、性别、年龄等特征就是静态特征,用变量来表示;
  2. 方法:类的动态特征叫方法,比如学生类的吃饭、睡觉、吃鸡等特征就是动态特征,用函数来表示;
# 定义一个类
class Students():#类的属性:用变量来表示type="学生"#类的方法:用函数来表示,但注意方法和函数两个概念有区别def study(self):return "学习软件测试技术!"

12.2.3、类的实例化(创建对象)

  • 根据类创建对象的过程,就是类的实例化;一个类可以创建多个对象;创建的对象带有类的属性和方法。
# 定义一个类
class Students:#类的属性:用变量来表示type="学生"#类的方法:用函数来表示,但注意方法和函数两个概念有区别def study(self):return "学习软件测试技术!"#实例化对象
Students()
print(id(Students()))#实例化一个对象,并赋值给变量stu1,那么stu1就相当于对象的引用
stu1=Students()
print(id(stu1))
print(id(stu1))#实例化另一个对象
stu2=Students()
print(id(stu2))

12.2.4、属性和方法的调用

  • 因为类的对象有类的所有属性和方法,所以可以通过对象来调用类的属性和方法
# 定义一个类
class Students():#类的属性:用变量来表示type="学生"#类的方法:用函数来表示,但注意方法和函数两个概念有区别def study(self):return "学习软件测试技术!"#实例化一个对象
stu1=Students()
#调用属性
print(stu1.type)
#调用方法
print(stu1.study())

12.2.5、对self的理解

  • 方法中至少有1个参数self,并且self形参必须在第一个位置,但调用方法时又不需要给self参数传参。self表示对象本身。
# 定义一个类
class Students():#类的方法:用函数来表示,但注意方法和函数两个概念有区别def change_type(self,type):#如下表示调用对象的type属性进行操作,通过self.type实现调用self.type=typereturn self.type#实例化一个对象
stu1=Students()
#调用方法
print(stu1.change_type("小学生"))
#实例化一个对象
stu2=Students()
print(stu2.change_type("中学生"))

12.2.6、构造方法和析构方法

魔法方法:在Python中,所有以 __ 双下划线包起来的方法,都统称为“Magic Method”,中文称『魔术方法』,例如类的初始化方法 init 。这里介绍两个魔法方法: init() 和 del()

构造方法: init()

  • init 是构造方法,在声明类的时候构造方法是可选的(也叫魔法方法——python自带的方法)
  • init 在类中的作用是:创建对象,初始化对象
  • 当类中没有显式地声明构造方法的时候,系统会使用一个默认的不带参的构造方法来实现对象的创建,当我们需要对对象初始化的时候,就可以显式地声明一个带参(也可以不带参)的构造方法。

析构方法: del()

  • del() 是析构方法,作用是在一个对象调用完成后,会将对象释放掉,不再使用
# 定义一个类
class Students():#类的属性:用变量来表示type="学生"def __init__(self,name,age):#实例的属性self.Name=nameself.Age=age#类的方法:用函数来表示,但注意方法和函数两个概念有区别def study(self):return "学习软件测试技术!"def get_name(self):return self.Name#实例化一个对象
stu1=Students("张三",20)
#调用属性
print(stu1.type)
print(stu1.Name)
print(stu1.Age)
#调用方法
print(stu1.study())
print(stu1.get_name())

12.4、类的继承

12.4.1、继承的概念

  • 继承是类与类之间的一种关系,子类继承父类。

    • 子类:需要继承的类
    • 父类:被继承的类
  • 继承的特点:
    1. 父类拥有的属性和方法,则子类一定有(私有的属性和方法可以通过 子类对象._父类__方法 间
      接调用);
    2. 父类拥有的属性和方法,子类可以修改;
    3. 父类没有的属性和方法,子类可以新增。
  • 核心:当一个子类继承父类时,必然会先创建父类对象,然后再创建子类对象,这样子类对象中才拥有所有父类的属性和方法。

12.4.2、继承的写法

在声明一个类的时候,如果这个类继承了父类,在类名后加括号来指定父类的名称。

# 定义一个父类
class People:type="高等生物"def get_type(self):return self.typedef __study(self):return "学习软件测试"#定义一个子类,继承父类Peopleclass Students(People):pass# 创建子类对象,调用父类的属性和方法
s1=Students()
print(s1.type)
print(s1.get_type())
print(s1._People__study())

12.4.3、子类继承父类的属性和方法

# 定义一个父类
class People:type="高等生物"def get_type(self):return self.type
#定义一个子类,集成父类People
class Students(People):pass
#创建Students类的对象
stu1=Students()
#子类对象可以调用父类的属性和方法,因为继承过来了
print(stu1.type)
print(stu1.get_type())

12.4.4、子类新增父类没有的属性和方法

# 定义一个父类
class People:type="高等生物"def get_type(self):return self.type
#定义一个子类,集成父类People
class Students(People):
#子类的属性type2 ="小学生"
#子类的方法def get_type2(self):return self.type2
#创建Students类的对象
stu1=Students()
#子类对象可以调用父类的属性和方法,因为继承过来了
print(stu1.type)
print(stu1.get_type())

12.4.5、子类重写父类的属性和方法

重写父类中的方法的原因:父类中的方法不能满足子类的需要,但是子类又想保留这个方法名。

#把适用于自己的父类方法写成自己的方法
# 定义一个父类
class People:type="高等生物"def get_type(self):return self.type
#定义一个子类,继承父类People
class Students(People):type ="小学生"def get_type(self):return self.type
#创建Students类的对象
stu1=Students()
#子类对象可以调用父类的属性和方法,因为继承过来了
print(stu1.type)
print(stu1.get_type())

12.4.6、super超类的使用

super超类
super 超类的作用是调用父类的方法,当在子类中调用父类的同名的方法时,需要通过 super 超类来调用。不同名的方法可以直接通过self来调用。
在 python3.x 中通过super超类调用父类方法有两种写法:

  1. super().父类的方法(参数)
  2. super(子类名称,self).父类的方法(参数)

super超类的一个最常见用法就是在子类中调用父类的构造方法,Python继承情况下写构造方法的3种典型场景:

  1. 如果子类没有显式声明 init() 方法,不管父类有没有显式地声明 init() 方法,都不需要在子类中手动地调用父类的 init() 方法,系统会实现自动调用;
  2. 如果子类显式声明了 init() 方法,但父类没有显式声明 init() 方法,同样不需要在子类中手动地调用父类的 init() 方法,系统会实现自动调用;
  3. 如果子类和父类都显式声明 init() 方法,则必须在子类的 init() 方法中用super对象手动地调用父类的 init() 方法创建父类的对象(调用父类的 init() 方法时不需要传入self参数)。
class People:type = "人类"# 构造方法def __init__(self, name, age):# 定义属性self.name = nameself.age = agedef get_type(self):return self.typeclass Students(People):pass# 创建Students类的对象,需要传入父类构造方法需要的参数,当子类没有显式地声明__init__方法的时候,在创建子类对象之前,系统会自动调用父类的__init__方法来完成父类对象的创建
stu1 = Students("张三", 30)
print(stu1.name)
print(stu1.age)
print(stu1.type)
class People:type = "高等生物"#构造方法# def __init__(self, name, age):# # self表示对象本身# # 定义属性# self.name = name# self.age = agedef get_type(self):return self.type#定义一个子类,集成父类People
class Students(People):def __init__(self, sex, school):self.sex = sexself.school = school#创建Students类的对象,因为父类没有显式地声明__init__方法,当子类显式地声明__init__方法的时候,在创建子类对象之前,系统会自动调用父类的默认的不带参的__init__方法来完成父类对象的创建
stu1 = Students("男", "成都职业技术学院")
print(stu1.sex)
print(stu1.school)
class People:type = "高等生物"#构造方法
def __init__(self, name, age):# self表示对象本身# 定义属性self.name = nameself.age = agedef get_type(self):return self.type#定义一个子类,集成父类People
class Students(People):def __init__(self, sex, school, name, age):#当父类和子类中都显式地声明了__init__方法时,需要在子类中用super对象来调用父类的__init__ 方法,以完成父类对象的创建,这样才能实现子类继承父类。此时子类的__init__方法的形参包括父类 __init__方法的形参super().__init__(name, age)self.sex = sexself.school = school
class People:type = "高等生物"def get_type(self, ):return self.type#定义一个子类,集成父类Peopleclass Students(People):type1 = "小学生"def get_type(self):return self.type1def super_get_type(self):  # 重新父类的方法后用作调用父类的方法return super().get_type()#创建Students类的对象
stu1 = Students()
#子类重新父类的方法后再调用父类的方法
print(stu1.super_get_type())

12.4.7、多继承

多继承:子类可以拥有多个父类,并且具有所有父类的属性和方法。例如:孩子会继承自己父亲和母亲的特性。

class A:def __init__(self):print("初始化A类对象")class B(A):def __init__(self):# super().__init__()super(B, self).__init__()print("初始化B类对象")class C(A):def __init__(self):super(C, self).__init__()print("初始化C类对象")class D(B, C):def __init__(self):super(D, self).__init__()print("初始化D类对象")b = B()
print("----------------")
d = D()
# 通过mro来查看调用顺序
print(D.__mro__)
class A:def __init__(self):self.n = 2def add(self, m):print("A 类中self为:", self)self.n += mclass B(A):def __init__(self):self.n = 3def add(self, m):print("B 类中self为:", self)super().add(m)self.n += 3class C(A):def __init__(self):self.n = 4def add(self, m):print("C 类中self为:", self)super().add(m)self.n += 4class D(B, C):def __init__(self):self.n = 5def add(self, m):print("D 类中self为:", self)super().add(m)self.n += 5d = D()
print(d.n)
print(D.mro())
d.add(2)
print(d.n)

python 基础(数据类型、运算符、流程控制、推导式、函数等...更新中)相关推荐

  1. python开发基本流程_第一阶段:Python开发基础 day06  Python基础语法入门--流程控制(二)...

    一.上节课内容回顾 三种格式化输出 占位符 format格式化 f-String格式化 基本运算符 算术运算符 比较运算符 逻辑运算符 赋值运算符 身份运算符 运算符的优先级 流程控制之if判断 单分 ...

  2. python基础和第三方库 笔记(python基础完结包括高级用法,第三方库持续更新中...)

    python基础 注:本笔记面向有一定基础的人 本笔记是本人快速复习python过程中记录的,不适合零基础的人学习python的主工具,可以作为辅工具,本笔记记录了入门阶段常用操作,如有错误的地方,希 ...

  3. Java码农进阶之路~基本数据类型运算符流程控制-分支三目

    基本数据类型 首先先说下字节:字节(byte)是计算机信息技术用于计量存储容量的一种计量单位 通常情况下一字节由8个二进制位表示 0000 0000; 一个字节的取值范围为-128~127. 大家有兴 ...

  4. C++:C++语言入门级基础知识考察点回顾之基本数据类型、流程控制

    C++:C++语言入门级基础知识考察点回顾之基本数据类型.流程控制 目录 C++的基本数据类型 0.return 的两种实现

  5. Python基础——数据类型—集合

    Python基础--数据类型-集合 Python基础--数据类型-集合 创建集合 快速查看元素是否在集合内 两个集合间的运算 集合a中包含,而集合b中不包含的元素 集合a或集合b中包含的所有元素 集合 ...

  6. Python基础数据类型之字符串(一)

    Python基础数据类型之字符串(一) 一.字符串格式化 1.字符串占位符 2.字符串格式化操作 二.f-string格式化 三.字符串的索引 四.字符串的切片 1.常规切片使用方法 3.步长的介绍 ...

  7. Java基础篇3——流程控制

    Java基础篇3--流程控制 1.顺序结构 正常代码的流程即是顺序流程 2.分支结构 2.1.if-else分支 if(条件表达式) {语句块1; } if(条件表达式) {语句块1; } else ...

  8. Python基础——数据类型—元组

    Python基础--数据类型-元组 Python基础--数据类型-元组 元组的创建 访问元组 元组的拼接 元组中的元素是不允许进行修改和删除的,但是可以删除整个元组 元组的运算符 打印元组元素 元组的 ...

  9. C#面向对象程序设计课程实验一:实验名称:C#语言基础、程序流程控制

    C#面向对象程序设计课程实验一:实验名称:C#语言基础.程序流程控制 实验内容:C#语言基础.程序流程控制 一. 实验目的 二.实验环境 三.实验内容 四.实验总结 实验内容:C#语言基础.程序流程控 ...

  10. 小白的Python 学习笔记(八)推导式详解

    什么是推导式 大家好,今天我总结一下Python的推导式,首先让我们来看定义 推导式(comprehensions)是Python的一种独有特性,是可以从一个数据序列构建另一个新的数据序列的结构体.一 ...

最新文章

  1. 转发:某些函数需要将其一个或多个实参连同类型不变地转发给其他函数
  2. qt解析html的数据,windows下用QTwebkit解析html
  3. android 标题栏进度圈使用方法,Android 自定义标题栏 显示网页加载进度的方法实例...
  4. MySQL 字段默认值该如何设置
  5. Linux进阶之路———— RPM 与 YUM 包管理
  6. ios 可以为空声明_iOS开发中使用OC和swift的对比(2)
  7. 查询排序_MySQL查询性能优化
  8. 1个已知CVE,7步,找到一个高质量RCE并获奖金
  9. java 中的string_Java中String揭秘
  10. 【超详细】| 使用Vmware 安装win7虚拟机
  11. com.alibaba.android,钉钉(com.alibaba.android.rimet) - 6.0.17 - 应用 - 酷安
  12. 微信小程序使用weui设计界面
  13. C++特征码查找 附加案例
  14. matlab逆变换法产生随机数_用matlab产生随机数
  15. The specified target project directory 项目名\src\main\resources does not exist 问题解决
  16. 亚洲一些物流软件航空争抢货机投放
  17. V部落-微信小程序版博客
  18. ubuntu状态栏消失
  19. shell命令之ln
  20. Python实现批量修改图片名称并存入新文件夹

热门文章

  1. javascript 常用的时间函数
  2. 分布式框架(一):分布式协议
  3. 美的热水器面板php代码,美的空气能热水器控制面板如何设置啊
  4. IP服务-2-RARP和BOOTP
  5. 软考信息安全工程师专业英语题
  6. 永磁同步电机的SPWM控制
  7. tomcat部署vue项目(成功版)
  8. 微信小程序用云开发实现多人聊天2020/05/21
  9. 磁珠纯化技术研究丨G-Biosciences 羧基磁珠方案
  10. java jframe 卡死_java - JFrame的无响应KeyListener