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
/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,赋值为整数8num1 = 8# 查看num1的类型print(type(num1))# 使用变量num1print(num1)# 声明一个变量str1,赋值为字符串hellostr1 = "hello"# 查看str1的类型print(type(str1))# 输出变量str1print(str1)# 多个变量同时定义num2,str2 = 1,"你好"print(num2,str2)
常量:Python没有常量的概念,Python程序一般通过约定俗成的变量名全大写的形式表示这是一个常量。
# Java中常量举例:声明常量PRICE,赋值为10,声明后这个常量的值就固定为10,不能再对它赋值final int PRICE = 10;# 如果Python中要定义常量,如下:PI = 3.14MONTH = 12
5.2、数值型
Python中的数值型包括:int(整型)、float(浮点型)、complex(复数),在Python2
中还有long(长整型)
5.2.1、int
int
(整型):表示一个整数,包括正整数、负整数
num1 = 100print(type(num1))<class 'int'>
type()函数:type函数的作用是查询变量的数据类型
5.2.2、float
float
(浮点型):表示一个小数,但在计算机中float只能表示一个近似值,不能表示精确值,这是因为浮点数的机制决定的(浮点数必须包含一个小数点,否则会被当作int类型处理)
a = 3.11b = 1.5print(a-b)# 1.6099999999999999
如果要表示精确值,可以使用Decimal对象来实现
# 通过实例化Decimal对象来表示精确小数from decimal import Decimalprint(Decimal("3.11")-Decimal("1.5"))# 1.61
5.2.3、其他进制的表示与相互转换
常见的进制:二进制、八进制、十进制、十六进制等
二进制(Binary) 由0,1组成,逢二进一二进制的声明:在数字前加0b
表示二进制
# 声明一个变量a,赋值为二进制1001a = 0b1001# 输出a的值,输出的是十进制9print(a)
八进制(Octal) 由0,1,…,7组成,逢八进一八进制的声明:0o
# 声明一个变量aa = 0o11# 输出aprint(a)
十进制(Decimal)
十进制的声明:Python中默认的数值就是十进制的
十六进制(Hexadecimal)
十六进制的声明:在数字前加0x
表示十六进制
# 十六进制a = 0x000F# 输出a的值,输出的是十进制15print(a)
进制转换函数
# **进制转换函数**# - bin():把十进制转成二进制# - oct():把十进制转成八进制# - hex():把十进制转成十六进制# - int(x,base=y):表示把y进制的字符串x转换成十进制的整数# - 举例:print(bin(10)) # 十进制转换为二进制# 0b1010print(oct(10)) # 十进制转换为八进制# 0o12print(hex(17)) # 十进制转换为十六进制# 0x11print(int("1000",base=2))#表示把2进制的字符串“1000”转换成十进制的整数# 8print(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])# 步长不输默认为1print(str3[1:4])print(str3[:4])# 终止值不输默认取到最后print(str3[4:])print(str3[:])# 区间左闭右开print(str3[4:7:1])'''eellhello worldhello worldo w'''# 步长为负print(str3[-1:-5])print(str3[-1:-5:-1])# 取值区间不在范围内不会报错,返回空字符串print(str3[-5:-1])print(str3[-5:-1:-1])'''dlroworl'''
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替换成Aprint(str5.replace('a','A'))# sdfskAkjksgjjjsdAAAAAAA# 只替换一次print(str5.replace('a','A',1))# sdfskAkjksgjjjsdaaaaaaa# 把str2中的第2个a替换成Aprint(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(): 字符串中所有字符都是字母或数字且非空则返回Trueisalpha(): 字符串中所有字符都是字母且非空则返回Trueisdigit(): 字符串中所有字符都是数字且非空则返回Trueisupper(): 字母都为大写且非空返回Trueislower(): 字母都为小写且非空返回Trueistitle(): 单词的首字母都为大写且非空返回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识别成转义字符,这时要在前面再加一个\,如果路径很长,可以在最前面加个rprint("\\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为99list2[2] = 99print(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的位置插入999list1.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()
作用:删除列表中的某个元素:括号中传入要删除的元素值,不返回删除元素,返回Nonelist1 =["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 list1print(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=123str1="你好吗"list1=[1,2,4,5]# print(tuple(num)) # 报错print(tuple(str1))# ('你', '好', '吗')print(tuple(list1))# (1, 2, 4, 5)
声明一个只有一个元素的元组:需要加一个逗号来表明这是一个单元素的元组,否则解释器会理解成在外面加了一个普通的括号,打印类型为单个元素的类型。
5.5.2、元组的作用
可以实现对数据进行保护在操作不定长参数函数时,其参数的类型就是一个元组,所以可以直接将元组进行传入在函数或者方法中返回值可以返回多个值,默认是把多个值以元组的形式返回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开始,终止值默认到最后,步长默认为1print(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 tup1print(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,然后重新赋值,修改的是valuedict2["名称"] = "段誉"print(dict2)# {'名称': '段誉', '年龄': 18, '喜欢': ['阿朱', '阿紫']}
新增键值对-单个
在字典中增加一个元素(键值对),格式:字典名[键名]=键值,如果键名在字典中不存在就会增加,如果已存在就会修改它的键值
dict2={"名称":"乔峰","年龄":18,"喜欢":["阿朱","阿紫"]}dict2["虚竹"] = "憨子"print(dict2)# {'名称': '乔峰', '年龄': 18, '喜欢': ['阿朱', '阿紫'], '虚竹': '憨子'}
新增多个键值对:update()方法作用:在字典中增加多个键值对,相当于字典的拼接,如果键名重复就覆盖原来的键值
dict1={"名称":"乔峰","年龄":18,"喜欢":["阿朱","阿紫"]}dict2={"学历":"高中","毕业时间":,"city":"绵阳"}dict1.update(dict2)print(dict1)# {'名称': '乔峰', '年龄': 18, '喜欢': ['阿朱', '阿紫'], '学历': '高中', '毕业时间': , 'city': '绵阳'}dict1.update({"性别":"Female","公司":"华为"})print(dict1)# {'名称': '乔峰', '年龄': 18, '喜欢': ['阿朱', '阿紫'], '学历': '高中', '毕业时间': , '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 dict1print(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.修改年龄为20dict1["信息"]["年龄"] =20print(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从集合中移除,如果元素不存在,则会发生错误
#removeset1 = {1,2,3,4,5}set1.remove(3) #不会返回删除的值print(set1)
discard(x)方法:
作用:移除集合中的元素,且如果元素不存在,不会发生报错
#discardset1.discard(3) #也不会返回删除的值print(set1)
pop():
作用:随机删除集合中的一个元素
#popset1.pop()#不用传参数,且随机删除一个元素(每次删除的都是集合排序里的第一个元素),并返回删除的元素print("删除前",set1)print(set1.pop())print("删除后",set1)
del关键字 :
作用:删除整个集合
#del,删除整个集合del set1print(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=Trueprint(type(a))print(a+5)print(False*100)print(bool(111)) #Trueprint(bool("fff")) #Trueprint(bool([1,2,4])) #Trueprint(bool(3,)) #Trueprint(bool({"A":1})) #Trueprint(bool({3,'a'})) #Trueprint(bool("")) #Falseprint(bool([])) #Falseprint(bool(())) #Falseprint(bool({})) #Falseprint(bool(set())) #Falseprint(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与其他任何数据类型比较都返回Falsenull为 java 里的空,和None一样,都是没有元素
5.11、数据类型总结
5.11.1、可变和不可变类型(对象)
所谓可变对象,是指对象的内容是可变的,比如修改对象的内存时对象的内存地址不改变,例如 list。而不可变的对象则相反,当改变它的内容时对象的内存地址也会改变。
可变数据类型:List(列表)、Dictionary(字典)、Set(集合)不可变数据类型:Number(数字)、String(字符串)、Tuple(元组)
num1=100print(id(num1))num1=101print(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:
6.2、比较运算符
以下假设变量 a=2,变量 b=3:
注意:<> 在 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、成员运算符
innot 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:
num_1 = 5print(num_2 := num_1 + 5)print(num_2)#输出:1010#在这个示例中,赋值表达式可以避免调用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”,否则输出等于10num1=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=1while i<=10: #1.条件限制print(i)i+=1 #2.条件,递增else:print("打印完毕")#实现1+2+3+...+100,并输出计算结果num1=0i=1while i<=100:num1+=ii+=1else:print(num1)#思考:1*2*3*...*100 ?
当布尔表达的值为True的时候,就执行循环体的代码,直到布尔表达的值为False的时候或者被break;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}#遍历字典,默认取到的是字典的keyfor i in dict1:print(i)#遍历字典的keyfor i in dict1.keys():print(i)#遍历字典的valuefor 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 = 2while (i < 10):j = 2while (j <= (i / j)):if not (i % j):print("能除尽",i,j)j = j + 1else:print("不满足条件",i,j)i = i + 1print("算完")
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语句
continuebreakpass7.2.4.1、continue语句
作用:continue的作用是结束本次循环(在某一次循环中遇到continue语句时,直接结束本次循环,不执行continue后面的代码,而开始执行下一次循环)。
# 在0到10的数字中打印所有奇数,不是奇数的就不打印出来a = 0while 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 = 0while 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.方法1for b in range(1,8,2):print("*"*b)#2.方法二b = 5for b in range(1,b+1):print("*"*(2*b-1))# 金字塔cengshu = 7for 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])# 列表推导式不加ifprint([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))
九、函数
定义:函数就是完成特定功能的一个语句组,这组语句可以作为一个单位使用,并且取一个名字,这个名字叫做函数名
函数的作用:
可以通过函数名在程序不同的地方多次调用,这样就不用在不同的地方重复编写这些语句函数是实现特定功能的一段代码,通过函数可以方便地重复使用代码,让程序的结构更清晰,方便代码的走读。函数能提高应用的模块性,和代码的重复利用率
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的值,如果都不满足,则返回Nonedef 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+yprint(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*…*ndef f1(n):# print(n)if n == 1:return 1return n*f1(n-1)print(f1(10))#举例2:通过递归实现求和运算,实现声明一个函数,传入参数n,实现1+2+...+ndef 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=0def get_sum(list):for i in list:if type(i)==int:global sum1sum1+=ielse:print("不满足条件的数据",i)return sum1print(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关键字用来在函数或其他局部作用域中使用全局变量。
如果局部要对全局变量进行修改,而不使用global关键字。
count = 0def global_test():count += 1print(count)global_test()# 输出:UnboundLocalError: cannot access local variable 'count' where it is not associated with a value
如果局部要对全局变量修改,应在局部声明该全局变量。
count = 0def global_test():global countcount += 1print(count)global_test()print(count)# 输出:11
如果局部不声明全局变量,并且不修改全局变量,则可以正常使用。
count = 0def global_test():print(count)global_test()# 输出0
十、迭代、可迭代对象、迭代器、生成器
10.1、迭代iteration
迭代Iteration:所谓迭代就是重复运行一段代码语句块的能力,就好比在一个容器中进行一层一层遍历数据,在应用过程中for循环最为突出。迭代就是从某个容器对象中逐个地读取元素,直到容器中没有元素为止。迭代迭代,更新换代,在上一次基础上更新成新的东西
for i in "hello world":print(i,end="\t")
10.2、可迭代对象iterable
用 dir() 函数来查询是否包含iter() 方法;对象.方法的方式去调用看有没有iter方法;通过内置的实例对象函数 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,Iteratorprint(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__())
迭代器的特点是: 迭代器一定是可迭代对象;迭代器通过next()函数或者next() 方法取值,每迭代一次取一个值,只能往前取不能后退;当取完最后一个值的时候,再执行next()函数或者next() 方法会报 StopIteration 异常,表示取完了。 判断一个对象是迭代器还是迭代对象,可以使用以下两种方法: 通过对象包含iter() 和next() 方法决定;需要判定是迭代器还是迭代对象可以通过实例对象函数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+...+100000000print(sum(list(range(1,100001))))print(sum(iter(range(1,100001))))
迭代器的优缺点:
迭代器优点:节省内存,迭代器在内存中相当于只占一个数据的空间,因为每次取值都会把上一条数据在内存中释放,加载当前的此条数据。迭代器的缺点,不能直观的查看里面的数据。取值时不走回头路,只能一直向下取值。
10.4、生成器Generator
生成器Generator:在 Python 中,生成器的本质就是一个迭代器,使用了yield 的函数被称为生成器(generator)。
10.4.1、return和yield的区别
return的作用: 给调用者返回值;执行遇到第一个return语句时就结束函数。 yield的作用: 给调用者返回值;yield把函数变成了生成器;生成器运行时遇到yield后先返回再挂起。10.4.2、生成器怎么创建
创建生成器的方法:
通过关键字yield把函数变成生成器;通过生成器推导式创建生成器:(结果 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 的函数执行过程比较特别:
调用该函数的时候不会立即执行代码,而是返回了一个生成器对象;当使用 next()作用于返回的生成器对象时 (在 for 循环中会自动调用 next() ) ,函数开始执行,在遇到 yield 的时候会『暂停』,并返回当前的迭代值;当再次使用 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 3gt = generator()print(next(gt))print(next(gt))# 使用for循环执行生成器for i in generator():print(i)
10.4.4、send()方法
通过send()方法也可以执行生成器,同时可以向生成器传入值。
send()方法与next()函数的区别:
send() 方法与 next() 函数都用来执行生成器;send()方法会将传入的值赋给上次中断时yield语句的执行结果,然后再执行生成器,从而实现与生成器方法的交互;在执行生成器时,如果第一次执行使用 send() 方法,因为没有挂起的yield语句来接收传入的值,所以会报 TypeError 异常。简单地说, send() 方法就是 next() 函数的功能,加上传值给 yield 。
# 例1:第一次使用send()方法执行生成器def generator1():yield 1yield 2yield 3gt1=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 cgt2=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,返回efgprint(gt2.send('efg'))
10.4.5、生成器与迭代器的区别
生成器: 生成器本身是一种特殊的迭代器,也就是说生成器就是迭代器。生成器会自动实现迭代器协议,也就是说只要我们yield后,自动就生成了next对象包括StopIteration等结构。生成器使用yield语句返回一个值。yield语句挂起该生成器函数的状态,保留足够的信息。对生成器函数的第二次(或第n次)调用,跳转到函数上一次挂起的位置。生成器不仅“记住”了它的数据状态,生成还记住了程序执行的位置。 迭代器: 迭代器是一种支持next()操作的对象。它包含了一组元素,当执行 next() 操作时,返回其中一个元素;当所有元素都被返回后,再执行 next() 报异常 StopIteration ;生成器一定是可迭代的,也一定是迭代器对象。 它们的区别: 迭代器是访问容器的一种方式,也就是说容器已经出现。我们是从已有元素拓印出一份副本,只为我们此次迭代使用。而生成器则是,而生成器则是自己生成元素的。也就是前者是从有到有的复制,而后者则是从无到有的生成。在用法上生成器只需要简单函数写法,配合yield就能实现。而迭代器真正开发中很难使用到。我们可以把生成器看做,python给我们提供的特殊接口实现的迭代器。十一、高阶函数
11.1、map()函数
map() 函数语法: map(function,iterable)
作用:map()是 Python 内置的高阶函数,它接收一个函数 function 和一个 iterable ,并通过把函数function依次作用在 iterable 的每个元素上,并返回一个新的迭代器;map()函数也可以接收多个iterable。
# 传入一个序列的例子def f(x):return x*xlist1 = [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,得到15print(sum1)# reduce()还可以接收第3个可选参数,作为计算的初始值。如果把初始值设为1000sum2 = reduce(add, [1,2,3,4,5], 1000) # 相当于计算1000+1+2+3+4+5,得到1015print(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()方法的区别?
sort()方法是应用在list对象上的方法,sorted()函数可以对所有可迭代的对象进行排序操作;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、属性与方法
属性和方法统称类的成员。 属性:类的静态特征叫属性,比如学生类的姓名、性别、年龄等特征就是静态特征,用变量来表示;方法:类的动态特征叫方法,比如学生类的吃饭、睡觉、吃鸡等特征就是动态特征,用函数来表示;# 定义一个类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、继承的概念
继承是类与类之间的一种关系,子类继承父类。 子类:需要继承的类父类:被继承的类 继承的特点: 父类拥有的属性和方法,则子类一定有(私有的属性和方法可以通过 子类对象._父类__方法 间接调用);父类拥有的属性和方法,子类可以修改;父类没有的属性和方法,子类可以新增。 核心:当一个子类继承父类时,必然会先创建父类对象,然后再创建子类对象,这样子类对象中才拥有所有父类的属性和方法。
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#定义一个子类,集成父类Peopleclass 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#定义一个子类,集成父类Peopleclass 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#定义一个子类,继承父类Peopleclass 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超类调用父类方法有两种写法:
super().父类的方法(参数)super(子类名称,self).父类的方法(参数)
super超类的一个最常见用法就是在子类中调用父类的构造方法,Python继承情况下写构造方法的3种典型场景:
如果子类没有显式声明init() 方法,不管父类有没有显式地声明init() 方法,都不需要在子类中手动地调用父类的init() 方法,系统会实现自动调用;如果子类显式声明了init() 方法,但父类没有显式声明init() 方法,同样不需要在子类中手动地调用父类的init() 方法,系统会实现自动调用;如果子类和父类都显式声明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#定义一个子类,集成父类Peopleclass 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#定义一个子类,集成父类Peopleclass 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)