1.打印输出相关
默认情况下,print 函数打印完毕后会自动换行 如果不传递任何参数给 print 函数,那就相当于 print 函数只起到了换行的作用 \n 有换行的作用 有些编程语言(比如Java、C++等)要求每一条语句都必须以分号( ; )结尾 在Python中,语句尾部的分号( ; )是可有可无的(建议省略 ; ) 如果多条语句写在了同一行,那就必须用分号( ; )将它们隔开,否则运行错误
print("python 好");print("python 就是好")
2.数据类型
基本数据类型可以分为 整数 浮点数 字符串
str 函数可以将其他类型的数据转化为str类型 int 函数可以将其他类型的数据转化为int类型 float 函数可以将其他类型的数据转换成 float 类型
数据类型判断在python中可以使用type() 和 isinstance()判断基本数据类型,对象类型,如果你想获取下类型,可以用type(),如果你想判断一个变量是否属于某种类型,请使用 isinstance(变量, 类型)
运算结果特点
- int 和 float 进行运算的结果是 float
- 不论是整数和整数,还是整数和浮点数,浮点数和浮点数之间的除法运算结果都是 float
- 整除( // ),向下取整(floor) 什么是向下取整?使用最近且较小的那个整数作为结果 int 和 int 进行整除( // ),得到的结果是 int
其他特点
从Python3.6开始,可以在数字的任意中间位置插入下划线,让位数较多的数字更易于阅读
print(1000_000_000)
3.字符串
- Python中的字符串,既可以用单引号( '' )、也可以双引号( "" )包住(推荐使用单引号)
- \ \t \n 等都叫做转义字符
- 在字符串前面加个 r 或 R 意为:原始字符串(raw string) 可以让字符串禁止转义、保持原样
print('\\\\')
print(r'\\\\')
4.可以用3个单引号或3个双引号实现多行显示的字符串
print('''
1
2
3
''')
- 字符串分行编写 有时候字符串的内容会很长,如果在IDE中写成一行,阅读和修改起来不是很方便 可以使用 \ 实现分行编写
print('Python提供了高效的高级数据结构,\
还能简单有效地面向对象编程。\
Python语法和动态类型,以及解释型语言的本质,\
使它成为多数平台上写脚本和快速开发应用的编程语言, \
小码哥MJ随着版本的不断更新和语言新功能的添加,\
逐渐被用于独立的、大型项目的开发。')
注意的是上面的写法 \ 后面不能有任何内容,甚至连1个空格都不能有,否则就语法错误
6.从Python3.6开始,可以使用 f 、F 来往字符串中插入数据,他这个类似于js 中${}模版字符串差不多
print(f'姓名:{name},总成绩:{total}')
print(F'姓名:{name},总成绩:{total}')
原始字符串 r 和 f 是可以一起使用的,谁先谁后都是可以的,就表示个模版字符串,然后以不转义的方式输出,其中这里的是f还是F都是可以的
age = 18
print(rf'D:\tag\t{age}') # D:\tag\t18
print(fr'D:\tag\t{age}') # D:\tag\t18
print(f'D:\tag\t{age}') # D: ag 18
- 转化说明符 转换说明符:用来说明数据将要转换成什么格式
除了上面的写法还可以按照下面的写法来,这个写法又有点类似oc,c语言的字符串,可以前面占位,后面再写真正的变量。格式是 字符串 % 数据
print('姓名:%s,总成绩:%s' % (name, total))
- %d、%i转成整数(int)
- %nd:用n个字符的宽度显示,宽度不足n就在左边用空格填充
- %-nd:用n个字符的宽度显示,宽度不足n就在右边用空格填充
- %s转成字符串(str)
- %f转成浮点数(float)
- %.nf:保留n位小数(四舍五入) 举个例子
name = '小码哥'
age = 18
s = '我的名字是%s,我的年龄是%f岁' % (name, age)
hour = 9
minute = 5
second = 8
# 当前时间是9:5:8
print('当前时间是%d:%d:%d' % (hour, minute, second))
# 当前时间是09:05:08
print('当前时间是%02d:%02d:%02d' % (hour, minute, second))
8.字符串字面量 在相邻的字符串字面量之间插入空格,制表符(tab键)等空白字符,python会认为这些字符串字面量是连续的字符串
name = '小' '码' '哥' 'MJ'
print(name)
4.运算符
python 中运算符的特点:
- 没有其他语言中 && || !,而是用
andornot来代替,效果是一样的。这个是整体与或非,但是有类似的按位与&,按位| - 对于范围的写法,Python可以更简单,比方说 10 < a < 20
if (a > 10 && a < 18) {
// 当 a 大于 10 并且 小于 18 时,执行这里的代码
}
if 10 < a < 18:
- in 和 not in 是判断用来判断某个元素是否存在于一个容器(比如字符串、列表、元组、字典、集合)里面.对于in如果在返回True,否则返回False,对于not in 则相反
is和is not用来判断两个变量是否指向内存中的同一个对象,这里注意要和 == 的区别
`==` 比较的是两个变量的 **“值”** 是否相等(长得一不一样)。
`is` 比较的是两个变量的 **“内存地址”** 是否相同(是不是同一个实体)
# 场景 1:普通列表
list1 = [1, 2, 3]
list2 = [1, 2, 3]
print(list1 == list2) # 输出: True (它们里面的数字一模一样,值相等)
print(list1 is list2) # 输出: False (这是内存中两块不同的列表空间,只是内容恰好一样)
# 场景 2:变量赋值
list3 = list1
print(list1 is list3) # 输出: True (list3 和 list1 指向的是内存中的同一个列表)
- 运算符的优先级搞不清楚加()
- 布尔运算符(bool)有两个值True,False,任何值都可以转换成 bool 类型
- 对于数字来说,任何非0就是真,只有0是假的
- 对于字符串来说,任何长度不为0都是真,只有字符串长度为0(空串)才为假
- bool转其他类型
print(str(True) == 'True') # True
print(str(False) == 'False') # True
print(int(True)) # 1
print(int(False)) # 0
print(float(True)) # 1.0
print(float(False)) # 0.0
- 当bool类型与数字进行运算时
print(10 + True) # 11
print(10 * False) # 0
print(10.0 + True) # 11.0
print(10.0 + False) # 10.0
# 运行错误
# TypeError: can only concatenate str (not "bool") to str
print('10' + True)
模运算
余数的正负性跟随 % 右边的操作数 余数的绝对值必须要小于右边操作数的绝对值
print(10 % 7) # 3
print(10 % -7) # -4
print(-10 % 7) # 4
print(-10 % -7) # -3
在Python中,是不存在自增、自减运算符的
在有些编程语言(比如Java、C、C++等)中,还有自增(++)、自减(--)运算符
p 比如++a等价于a+=1、--a等价于a-=1
在Python中,是不存在自增、自减运算符的
为什么下面的Python代码能运行成功?
a = 10 print(++a) print(--a)
具体原因如下:Python 没有
++或--运算符: Python 不支持这种自增或自减的语法。被解析为了“正负号”(一元运算符) :++a在 Python 中会被理解为+(+(a)),即对a连续取两次正号,所以结果还是10。--a在 Python 中会被理解为-(-(a)),即对a连续取两次负号(负负得正),所以结果也是10。 正确的做法:** 如果你在 Python 中想要实现变量的自增或自减,应该使用+=或-=:
运算符的优先级
当一个表达式中同时使用多个运算符时,会根据运算符的优先级,来决定运算符的执行顺序,优先级越高,越先被执行,如果优先级一样,一般是按照从左至右的顺序去执行
5.选择结构
python 使用根据缩进的行数确定这一行代码是不是一块的,类似于其他语言的{}来表示代码块
if 语句
score = int(input("请输入你的考试成绩:"))
if score >= 60:
print('及格')
print('及格')
print('及格')
print('继续努力')
可以看到只有三行 print('及格')是在if语句中,判断语句后面跟着:,
还有如果if语句中有多行代码,它们的缩进距离需要保持一致
if else
score = int(input('请输入你的考试成绩:'))
if score >= 60:
print('及格')
else:
print('不及格')
条件表达式
条件表示的单行版
其实如果按照正常的理解应该是 if 表达式:代码1 else:代码2 ,这里的其实就是调整了下位置,把代码1提前了,去掉:就改成 代码1(if成立执行的代码) if 表达式1(if的判断条件) else 表达式2(else成立需要执行的语句)
i = 10
print(111); print('奇数') if i % 2 else print('偶数'); print(222)
注意看上面的代码,无论i是奇数还是偶数,上面的 111 都会打印,那是因为条件表达式只能管住前面的一句,而不能是多句,其实上面的语句等同于下面的
i = 10
print(111);
print('奇数') if i % 2 else print('偶数');
print(222)
elif
elif可以理解为else if的简写,和别的语言的else if 没有任何区别
match case
match x:
case a:
语句1
case b:
语句2
case _:
语句3
** 上面类似于switch case ,最后一个_其实是通配符,作用类似于别的语言的default**
match month := 3:
case 1 | 3 | 5 | 7 | 8 | 10 | 12:
print(f"{month}月有31天")
case 4 | 6 | 9 | 11:
print(f"{month}月有30天")
case 2:
print(f"{month}月可能有28天")
case _:
print(f"{month}月有?天")
| 是专门用于模式匹配的操作符,它能把多个常量或者模式组合起来,实现 “或” 逻辑。
6.循环结构
1.while循环
2.for循环
其实其他语言最经典的for循环写法是
const arr = [6, 4, 11, 5, 27, 99];
// 结构:for (初始化; 判断条件; 每次循环后的操作)
for (let i = 0; i < arr.length; i++) {
// i 是索引 (0, 1, 2...)
// 需要通过 arr[i] 来获取具体的数据
console.log(`第 ${i} 个元素是: ${arr[i]}`);
}
而上面的结构使用python中循环就要range函数
range函数
range(i, n, s) 会生成 [i, n - 1] 范围且步长为 s 的整数,特点需要是结束的位置是n-1,就是不包括尾部
# 0 2 4 6 8 10
for i in range(0, 11, 2):
print(i)
- 就那上面的例子来说就是指的是从0开始,到11结束,这个前后的临界值都包含,然后下一个值加2,那就获取的是 0 2 4 6 8 10,如果不设置步长,那步长就是1,不设置第三个参数,步长就是1.
- 如果range 传两个参数就表示在某个范围,还有一种可能就传了一个参数,就表示从【0,这个参数-1】这么一个范围
再会到上面的传统for循环其实在python中我们就可以用range(开始值,结束值)来代替
for i range(开始值,结束值)
循环体
这里说到range 函数,其实random 模块的 randrange 函数的参数和 range 函数一样
import random as r
# 随机返回1个[0, 9]范围内的整数
print(r.randrange(10))
# 随机返回1个[100, 200]范围内的整数
print(r.randrange(100, 201))
# 随机返回1个[2, 100]范围内的偶数
print(r.randrange(2, 101, 2))
_ 在循环体中使用
一般用下划线 _ 表示该变量的值没有在循环体中被使用到,可以认为是开发人员之间约定俗成的一种默契。建议遵守
■ 需要注意的是:_ 变量的值,依然可以在循环体中正常使用
for _ in range(5):
print(_, '小码哥')
# 下面是运行结果
0 小码哥
1 小码哥
2 小码哥
3 小码哥
4 小码哥
一个特殊问题
最后的 i 打印出来是多少?
for i in range(10):
print('---')
print('+++')
print(i)
最后打印出来的 i 是 9。 因为 range(10) 生成的是 0 到 9 的整数,在最后一次循环执行时,i 被赋值为 9。在 Python 中,for 循环里定义的变量不会在循环结束后被销毁(它的作用域会泄漏到外面),所以依然可以访问到它最后一次被赋予的值。
for 语句中的变量,不要拿到外面去使用。(这是为了代码的清晰性和避免潜在的 Bug,尽管 Python 语法允许你这么做)
break 和 continue
break和 continue 语句只用在 while、for 语句中,一个表示结束所在的while,for循环,结束挡在层所在的循环,如果是多层的话,需要一层一层break。continue 是结束这次循环当前后面的代码,当前也只能是当前层的循环,开始下次一个循环处理
while else语句、for else语句
总结下和别的语言相比,python搞出了一个else,他只用在当for,while 循环正常执行完,结束掉执行一次,正常结束就是说你不能break跳出循环结束,这时会额外再执行一下 else的代码。当然循环里面是否使用break没有啥关系
7.列表(list)
1. python中的列表,其实就是别的语言中数组.列表是可迭代对象,可以使用for 循环
scores = [88, 75, 69, 93, 100, 43, 72, 51, 85, 77]
2. list中的元素可以是不同的类型,在很多其他编程语言(比如 C 或 Java)中,数组里的元素通常必须是同一种类型(要么全是数字,要么全是字符串)
# 1. 定义一个布尔值 (Boolean)
d = True
# 2. 创建一个混合类型的列表 s
# 里面包含了:整数、字符串、布尔值(变量d)、另一个列表(嵌套列表)、浮点数(小数)
s = [10, '20', d, [6, 7, 8], 10.5]
# 3. 使用 for 循环遍历这个列表中的每一个元素 (用变量 e 表示)
for e in s:
# 4. 打印每个元素的类型
print(type(e))
循环执行时,
type(e)分别检测出每个元素的真实类型:
10的类型是<class 'int'>(整数)
'20'加了引号,类型是<class 'str'>(字符串)
d是 True,类型是<class 'bool'>(布尔值)
[6, 7, 8]本身也是一个列表,所以类型是<class 'list'>(这叫列表嵌套)
10.5的类型是<class 'float'>(浮点数)
索引
python 不仅有正数索引,还有负数索引,正常索引从左往右数,负数索引从右往左边数.从左往后,最后一个位置的元素负数索引是 -1 ,而正数索引是0,负数索引是从 -1 开始
可以看到图上的 55的正数索引是0,负数是 -5 ,0+ | -5 |= 5 ,正好是list的长度
遍历操作
- 直接遍历元素 (
for i in s:)
s = [55, 44, 33, 22, 11]
for i in s:
print(i)
确定是无法拿到索引
2. range 和 len 函数通过索引遍历 (for i in range(len(s)):)
s = [55, 44, 33, 22, 11]
for i in range(len(s)):
print(i, s[i])
这个写法可以同时获取索引和元素 3. enumerate 提供了一种更好的写法,可以同时获取索引和元素
s = [55, 44, 33, 22, 11]
for i, e in enumerate(s):
print(i, e)
如果我不想从0开始遍历呢该怎么写呢?
for i, e in enumerate(s, 3):
print(i, e)
enumerate 的第二个参数允许你指定索引的初始值。如果不传,默认从0开始;如果传入(例如图片中的 3),则索引会从该数字开始递增。如果不想循环到结束呢?这里其实可以用换种思路,用break提前结束,或者对列表进行切片,就是把列表取出来,其实还有一种思路就是用第二种range方法
空列表
- 使用空方括号
[]:
s1 = []
- 使用**
list()内置函数**
s2 = list()
注意空列表转换成bool值时间是False
加法 乘法
加号 +(列表拼接) : 你可以像做加法一样,把多个列表依次首尾相连,合并成一个新的大列表
s1 = [11, 22]
s2 = [33, 44]
s3 = s1 + s2 + [55]
# 最终得到的新列表 s3 包含所有元素:[11, 22, 33, 44, 55]
乘号 *(列表重复) : 将一个列表与一个整数 N 相乘,就是把这个列表里的全部元素复制并重复 N 次,生成一个新列表。
s4 = [11, 22]
s5 = s4 * 3
# s4 的元素被重复了3遍,得到新列表 s5:[11, 22, 11, 22, 11, 22]
切片
列表的切片:从列表中选取一部分元素,组成一个新的列表
语法是 s[i:j],表示截取从索引 i 开始,一直到索引 j 之前结束的元素。
注意它包含了起始位置 i,但不包含结束位置 j。
比如图片中的 s1[1:4],取出的实际上是索引 1、2、3 对应的元素,也就是 [44, 33, 22]
注意上面的[]里面的 i和j 都可以省略,省略的时间是“贪婪”地选取尽可能多的元素
甚至可以同时省略,但是要注意的是[]里面的 :绝对不能省略,因为省略就成了根据某个索引取值了。如果[] 同时省略就代表重新生成一个和原来一样的列表。
s[i:j:k]参考range(i, j, k)
疑问s[:] 生成的是和原来的是同一个对象吗?怎么判断他们的内存地址是一样不一样?
结果:生成的不是原来的对象,而是一个全新的对象。这在 Python 中被称为浅拷贝。虽然新列表里的元素内容和原来一模一样,但它们在内存中是两个完全独立的列表
几个判断相等的方法
==判断的是数据“内容”是否相等is判断的是“内存地址”是否相等id()函数查看真实的内存地址id()函数会返回该对象在内存中的唯一标识符(一串数字代表的内存地址)。
s = [11, 22, 33]
s_copy = s[:]
print(s == s_copy) # 结果: True (内容确实一模一样)
print(s is s_copy) # 结果: False (地址不一样,它们是两个独立的对象)
print(id(s)) # 例如输出: 4367891200
print(id(s_copy)) # 例如输出: 4367891584
# 打印出的两串数字不同,直观证明了它们地址不一样
s[i:j:k]
修改单个元素,修改某个范围的元素
- 改单个值,直接用索引修改就行
s[1] = 77 # 将正数索引为 1 的元素(原来的 44)修改成了 77
- 修改某个范围的元素,使用切片来修改,修改的格式为 s[切片范围] = 可迭代对象,可以理解将左边的表达式替换为右边的可迭代对象的元素,新生成的元素的长度 = 切片范围之外的元素 + 等式右边可迭代的元素的个数,而和左边的切片范围的元素没关系,相当于把可迭代对象的元素搬到 切片范围。(普通的连续切片,就是步长是1的切片)\
- 如果不是连续切片,就是步长不是1,[切片范围] 就必须和可迭代元素的个数完全相等,不然就会报错
ValueError: attempt to assign sequence of size
s = [55, 44, 33, 22, 11]
s[:] = [88]
print(s) # 结果: [88]
s = [55, 44, 33, 22, 11]
s[0:1] = [88,99,100]
print(s) # 结果: [88, 99, 100, 44, 33, 22, 11]
s = [55, 44, 33, 22, 11]
s[0:3] = [88,99,100]
print(s) # 结果:[88, 99, 100, 22, 11]
s = [66, 55, 44, 33, 22, 11]
s[0:5:2] = [90, 80]
print(s) # 结果:ValueError: attempt to assign sequence of size 2 to extended slice of size 3
s[i:i+1] = [x]等价于s[i] = x
s = [66, 55, 44, 33, 22, 11]
s[2:3] = 88 #错误写法
s[2:3] = [88] #正确写法
s[2] = [88] #错误写法
s[2] = 88 #正确写法
列表推导式(List Comprehension)
这是用“一行代码”快速生成列表的绝招。它比传统的 for 循环配合 append() 写法更加简洁,而且运行速度通常更快。
基础遍历生成
语法:[表达式 for 变量 in 范围] 示例:[i for i in range(5)] 相当于直接循环把 i 塞进列表,结果是 [0, 1, 2, 3, 4]
带运算加工的生成
你可以在前面的“表达式”部分直接对数据做数学运算或固定赋值。
做运算:[i ** 2 for i in range(5)],把取出的每个数算平方,得到 [0, 1, 4, 9, 16]。
固定值:[0 for _ in range(5)],不管循环到几,都塞入数字 0,得到 5个0 的列表。(注:当循环变量用不到时,Python 习惯用下划线 _ 代替变量名作为占位符)。
带 if 条件过滤
[表达式 for 变量 in 范围 if 条件] 示例右侧中间的:[i ** 2 for i in range(10) if i % 2]。 它的执行顺序是:先循环遍历(取出 0-9) 然后做 if 判断(i % 2 意味着只留下奇数),最后执行表达式加工(对筛选出的奇数算平方 i ** 2)。最终得到 [1, 9, 25, 49, 81]。
s = [i for i in range(12, 17)]
# [12, 13, 14, 15, 16]
s = [i for i in range(5)]
# [0, 1, 2, 3, 4]
s = [i ** 2 for i in range(5)]
# [0, 1, 4, 9, 16]
s = [i ** 2 for i in range(10) if i % 2]
# [1, 9, 25, 49, 81]
s = [6 for i in range(5)]
# [6, 6, 6, 6, 6]
s = [0 for _ in range(5)]
# [0, 0, 0, 0, 0]
几种写法
# 正确创建列表的 4 种方法
s1 = [10, 9, 8, 7, 6]
#用 `range` 设定好规则,再用 `list()` 强制转换为列表。
s2 = list(range(10, 5, -1))
#使用列表推导式遍历生成。
s3 = [i for i in range(10, 5, -1)]
# 其实仔细想想,上面的那种和下面这种的差别不就是一个[].一个是list吗?【】就是python提供的语法糖,所以和下面的写法完全等价,使用生成器表达式配合 `list()`(效果同第3种,但平时较少这么写)。
s4 = list(i for i in range(10, 5, -1))
# 错误的写法
s = [range(10, 5, -1)]
# [range(10, 5, -1)] 1
print(s, len(s))
# <class 'range'>
print(type(s[0]))
# 列表s中存放着1个range类型的数据
下面的这种写法结果是啥呢? 结果里面放了一个range对象,然后就这样一个list,而不是【10,9,8,7,6】,仔细检查下他对不上上面列表推导式的任何一种形式
s = [range(10, 5, -1)]
list的其他方法
- all(list):如果可迭代对象x中的所有元素都为真,就返回True,否则返回False
- any(list):只要可迭代对象x中有元素为真,就返回True,否则返回False
- len(list) 函数获取列表的长度(元素的数量)
- sum(list) 函数计算列表中所有元素的总和
- in判断某个元素是否存在于列表中
- 可以用not in判断某个元素是否不在列表中
8.序列操作支持情况
9.str的序列操作
- str 不支持原地修改和原地拼接,是因为str在python中被设计成不可变的对象,就是只能看,不能改 下面是str 的常见操作
s = '小码哥MJ'
# 获取指定索引的元素
print(s[2], s[-4]) # 哥 码
# 获取切片
print(s[1:4]) # 码哥M
e = s[2]
# <class 'str'>
print(type(e))
# 1
print(len(e))
# 修改指定索引的元素
# TypeError: 'str' object does not support item assignment
s[0] = '大'
# 修改指定切片
# TypeError: 'str' object does not support item assignment
s[0:2] = '大大'
s = '小码哥MJ'
# 判断包含关系
print('码哥' in s) # True
print('哥' in s) # True
print('大码哥' not in s) # True
a = 'm'
b = 'vmj'
c = '7vmj'
d = 'mj666'
print(a in b in c not in d)
# 等价于
print(
(a in b) and (b in c) and (c not in d)
)
# True
子串
字符串中任意个连续的字符组成的序列,称为该字符串的子串(substring)
比如字符串 'KMJ' 共7个子串:''、'K'、'M'、'J'、'KM'、'MJ'、'KMJ'
假设 x 是 s 的子串,那么 x in s 的结果一定是 True
- str、list都属于可迭代对象
for i in [55, 44, 33, 22, 11]:
print(i)