学习要点:
- 弱语法,重原理。语法是表现,只有了解深层原理,才能灵活运用。需要深入内存,剖析原理,才能看清语法。
- 重思想,重设计。思想是解决问题的思路,设计是指导程序结构的过程。
- 学习方法:
(1)知识点必须理解(定义/作用/适用性/语法)
(2)整理笔记(三合一)
(3)当天联系独立完成 - 学习过程:
记:解决问题的思想 - 靠实战训练
忘:细枝末节一些东西 - 查找资料获取具体的解决
执行过程
- 编译型: C ,优点:执行快;缺点:开发效率低,不能跨平台
- 解释型:Javascript, 优点:开发效率高,能跨平台;缺点:效率低
-
Python: 既有编译,也有解释(字节码),拥有上面两种优点
pycharm 快捷键
- 行首: Home
- 行尾:End
- 注释/取消注释: Ctrl + /
- 复制一行: Ctrl + d
- 选择多列: Alt + 鼠标点点点
- 上下移动行: Ctrl + Shift + 上下箭头
- 代码整理: Ctrl + Alt + L
数据基本运算
变量
- name = "ABC" : 变量 = 表达式
-
语义
(1)变量名:存储真正内存地址的别名
(2)赋值号:把右边对象的地址赋值给左边的内存
- 多个变量赋值: b01,b02 = "apple", "banana" ,这种语法既可以用于多个变量赋值,也可以用于“交换变量”:例如 b01,b02 = b02, b01
核心数据类型 (对象数据)
-
None 占位或解除变量地址绑定
a01 = None 变量 a01 暂时没有绑定数据地址
b01 = "苏大强"
b01= None 解除 b01 的内存地址绑定(解除与对象的关联)
整形 int (正数、0、负数)
二进制 0b 开头,后面跟 0 或 1
八进制 0o 开头,后面跟 0 ~ 7
十六进制 0x 开头, 后面跟 0~9 a ~ f A~F浮点型 float 1.23 - 1.23
科学计算法:用于太小或太大的数 0.000000001 1e8字符串 string "" 用双引号
数值可以用于计算,字符串只能用于显示。-
del 删除变量,同时解除与变量的关联,如果可能释放对象。
del a,b 删除多个变量
c = None
当对象被标记引用数为 0 时,内存即为可回收。
-
id : 身份运算符,可获取变量存储对象的地址
a=1000
b=800
id(a) : 11112112
id(b) : 555455444
a is b : False
池
小整数对象池 || 文件式对象可能存储在同一地址池中
小整数对象池范围: -5 ~ 256
例如:
a = 1000 b = 1000
a is b // TRUE
数据类型转换
int() 、float()、 str()、 bool()
算术运算符
+ : 加
- :减
* : 乘
// : 地板除 5 // 2 = 2
/ : 除 5 / 2 = 2.5
%: 余 5 % 2 = 1
% 取余用法,例如取一个3位数的个位数值: 275 % 10 = 5
** : 幂 5 ** 2 = 5 * 5
加强运算符
num += 1
num -= 1
.........
优先级
先算 - 后比较 - 再逻辑
语句
- 括号隐藏式换行 + 反斜杠 \ 显示换行
a = (1
+2
+ 3
)
b = 1 + 2 \
+3 + 4
-
if elif else
if else 真值与条件表达式
- 真值
if 100:
print("真值")
等同于:
if bool(100):
print("真值")'
- 条件表达式
语法:变量 = 结果1 if 条件 else 结果2
while
- while 语法
count = 0
while 条件
满足条件一直执行
count += 1 # 计数器
break # 打断循环
else:
不满足条件执行一次
- 跳转语句 break
for
- for 语法
for item in 可迭代对象:
item # 可迭代对象中的一个成员
while 合适有判断条件的循环
for 合适罗列可迭代对象
range 整数生成器
range(开始值,结束值,步调) range(1,10,1) : 1~9
range(10) : 0~9
可以只传结束值,结束值不包括在生成的范围内
"""
练习24:for else
如果 for 里面有 “中断” 操作,如 break、exit; 则 else 不执行;否则执行
"""
for item in range(3):
print(item)
break # break \ exit()
else:
print("else 不会被执行")
函数
- 输入函数 input()
- 输出函数 print()
- 转换函数 int()
容器类型
字符串 Str
- 定义
通俗理解:双引号或单引号;字符串实际存储的是“字符”对应的“不可变”“编码值”。不可以对一个字符串变量进行多次的累加,占内存空间。“序列”,字符都是紧挨着的 - 编码
-
字节: B 、KB、MB、GB、TB (联想:字节跳动),1 字节 (B) = 8 位 (bit)
2.字符:单个数字、文字与符号
3.字符集:存储字符与二进制序列对应的关系表,俗称“码表”。
4.编码:将字符转换成对应的二进制序列过程
5.解码:将二进制序列转换成对应的字符过程
6.编码方式:
(1)ASCII 码,美国,英文字母+数字,每个字符1字节
(2)GBK 码,中国,21003个汉字 + ASCII,英文 1 字节, 中文 2 字节
(3)Unicode 码,万国码,国际统一编码,旧字符 2 字节, 新字符 4 字节
(4)UTF-8,Unicode 的存储与传输方式,英文 1 字节, 中文 3 字节
- 双引号和单引号在 python 语言没有区别
- 三引号作用:所见即所得
- 转义字符 \
url = "C:\nike\bibi"
#第一种转义:
url = "C:\\nike\\bibi"
#第二种转义:字符串前面加字母 r 表示原始字符串,没有转义
url = r"C:\nike\bibi"
- 字符串格式化
%s | %d | %f | %.2f
a = 1
b = 2
name = "请输入 %s+%s=?" % (a, b)
string = "请输入 %s" % a #只有一个变量情况下,就不用再用括号了
容器类通用操作
- 部分算术运算符可以操作字符串
str_1 = "apple"
str_2 = "pear"
str_3 = str_1 + str_2 # "applepear"
str_4 *= 2 # appleapple
len = str_1 / 2 # 这种执行不了
- 成员操作符
str = "apple is my love"
print("apple" in str) # True
- 切片,具有字符串截取+翻转功能
message = input("请输入一个字符:")
# 打印第一个字符
print(message[0])
# 打印最后一个字符
print(message[-1])
# 打印倒数第三个字符
print(message[-3])
# 打印前面两个字符
print(message[0:2])
# 倒序打印字符串
print(message[::-1])
# 如果字符串长度为奇数,则打印中间字符
if (len(message) % 2) != 0:
print(message[len(message) // 2])
小球弹起距离计算
"""
练习30:求小球运动轨迹
(扩展)一个小球从 100m 高度落下
每次弹回原来高度一半。
计算:总共弹起来多少次(最小弹起高度0.01m)
总共走了多少米
"""
count, height, total = 0, 100, 100 # 只做一次下落运动
while height / 2 > 0.01: # 这里应该判断最小其他高度,while 循环体都做了上下运动
count += 1
height /= 2
total += height * 2
print("总共弹起来%d次,总共走了%.2f米" % (count, total))
列表 list
列表存储的是可变的“存储变量” “序列”,因为列表存储的是“变量”,所以列表可以存储各种类型的数据。
- 创建空列表和默认值列表的方式
"""
练习31:list 列表
"""
# 1.创建空列表
list01 = []
list02 = list()
print(list01)
print(list02)
# 创建有默认值列表
list02 = ["apple", True, 888]
# 下面的方式不可取
# list02 = list("apple", True, 888)
print(list02)
- 定位: 通过“索引”和“切片方式”
lists = ["apple", True, 887]
lists[1] # True ,直接通过索引的方式查找数据
从列表中获取一片元素组成新列表
变量 = 列表[切片]
修改一片元素
列表[切片] = 变量
lists = ["apple", True, 1888]
name = lists[:] # 从列表中获取一片元素组成新列表
lists[:] = [123] # 修改列表元素
- 添加元素 append() 和 插入(在指定位置插入)
lists.append("八戒") # 在列表末尾插入元素
lists.insert(2, "牛魔王") #在索引为 2 位置插入元素
- 删除列表:
(1)通过元素删除, lists02.remove("apple")
(2)根据位置删除, del list02[0]
"""
练习34:在列表中[9, 25, 12, 8],删除大于10的数
按顺序删除,会重置列表内存存储空间,
结论:删除需要倒着删
"""
lists = [9, 25, 12, 12, 12, 8]
for i in range(len(lists) - 1, -1, -1):
if lists[i] > 10:
del lists[i]
print(lists)
- 定位元素:目的,可以增删改查元素
(1)切片删除 del lists[1:3]
(2)删除列表变量 lists[1:3] = []
(3)修改列表 lists[1,3] = ["apple","pear"] - 列表倒序遍历
lists = ["apple", "pear", "banana", "mango"]
# 3 , 2, 1, 0 从大倒小 index
for i in range(len(lists) -1, -1, -1):
# -1, -2, -3, -4
for i in range(-1, -len(lists) -1, -1):
列表内存图
(1)简单变量赋值:
(2)修改列表第一个元素
list02[0] = "无忌"
(3)直接重置第一个变量
(4)切片意味着复制多一个新列表(仅仅拷贝变量,不拷贝变量值)
(5)切片复制是“浅拷贝”
切片只拷贝 [:] 里面的东西,里面的东西是什么?是变量
(6)深拷贝
(7)for 循环内存图
求出列表中的最大值
思想是:假设第一个变量是最大的,其他的变量再和第一个变量进行比较、交换。
列表与字符串对比
- 在 python 中 字符串是不可变更的。。拼接字符串会导致产生一个新的变量存储空间,浪费内存
这时应该改用"列表"做法
"""
练习36:拼接字符串
在 python 中 字符串是不可变更的。。拼接字符串会导致产生一个新的变量存储空间,浪费内存
这时应该改用"列表"做法
练习:在屏幕中输入,遇到空字符则停止
最后打印所有输入字符串
"""
lists = []
while True:
msg = input("请输入字符串:")
if msg == "":
break
lists.append(msg)
result = "-".join(lists)
print(result)
列表推导式
"""
练习40:列表推导式
"""
list01 = [1, 2, 3, 4]
list02 = [item + 1 for item in list01]
print(list02)
list01 = [1, 5, 8, 9, 4]
list02 = [item + 2 for item in list01 if item % 2 == 0]
print(list02)
列表扩容原理 - 预留空间
元组 tuple - 按需分配
定义:由一系列变量组成的不可变序列容器,一旦创建,不可以再增加、修改、删除元素。
"""
练习41: 元组
"""
# 创建元组
tuple01 = (100, 200, 300)
print(tuple01) # (100, 200, 300)
print(type(tuple01)) # tuple
# 元组与列表相互转换,只能通过关键字 tuple() \ list()
tuple02 = tuple([100, 200, 300])
print(tuple02) # 列表转元组
lists = list((1, 2, 3))
print(lists) # [1,2,3] 元组转列表
# 单个元组
tuple03 = (100,)
# 获取元组
tuple03 = (1, 2, 3)
print(tuple03[0]) # 1
tuple04 = tuple03[-2:]
print(tuple04) # (2,3) 元组切片得到的还是元组,列表切片得到的还是列表,字符串切片得到的还是字符串。
tuple05 = (100, 200)
a, b = tuple05
print(a) # 100
print(b) # 200
a, b = "ab"
print(a) # "a"
print(b) # "b"
字典 dict
- 定义
字典存储:可变 存储键值对 散列 - 使用
# 空字典
dict01 = {}
# 有默认值
dict02 = {'xiaoming': 100, 'age': 18}
#增加、修改
dict02['sex'] = 'M'
dict02['sex'] = 'F'
#读取
for key in dict01
print(key )
for value in dict01.values()
print(vaule)
for key, value in dict01.items()
print(key)
print(vaule)
# 删除
del dict01['key']
- 列表变字典
lists = ["无忌", "赵敏", "周芷若"]
result = {item: len(item) for item in lists}
print(result) # {'无忌': 2, '赵敏': 2, '周芷若': 3}
集合 set
集合,可以看做没有值,只有键的 "字典", 不可重复,不可变,无序,变量组成。
集合的应用
天然的去重(例如列表转集合)和 “集合运算”
-
交集:返回两个集合中的相同元素 &
-
并集:返回两个集合中的不重复的元素 |
-
并集: 返回两个集合中的不相同元素 ^
- 集合基本操作
# 创建空元素
set01 = set() # 貌似空集合也没多大用处
set02 = {} # 这个可不是空集合,是字典
print(set01, set02) # set() {}
# 创建具有默认值的集合
lists = {"a", "b", "c"}
set03 = set(lists)
set04 = set("ABC")
set05 = {1, 2, 3}
print(set03, set04, set05) # {'a', 'b', 'c'} {'B', 'A', 'C'} {1, 2, 3}
# 添加集合
print(id(set05)) # 1903291334944
set05.add(4)
print(set05) # {1, 2, 3, 4}
print(id(set05)) # 1903291334944 说明添加修改后还是同一个集合,内存空间没有变
# 删除元素
set05.remove(1)
print(set05) # {2, 3, 4}
# 获取所有元素
for item in set05:
print(item)
# 数学运算
set06 = {1, 2, 3}
set07 = {2, 3, 4}
set08 = {1, 2}
print(set06 & set07) # {2, 3}
print(set06 | set07) # {1, 2, 3, 4}
print(set06 ^ set07) # {1, 4} 补集,找不同的
print(set06 - set07) # {1} 补集,找一边不同
print(set08 < set06) # True 子集
print(set06 > set08) # True 超集
嵌套 for 循环练习
"""
练习55: 嵌套 for 循环练习
"""
for j in range(4):
for i in range(6):
print("*" if i % 2 == 0 else "#", end=" ") # end=" " 下一行输出跟着上一行后面
print("") # 输出 “”, 并且下一行打印另起一行
* # * # * #
* # * # * #
* # * # * #
* # * # * #
函数 def
- 定义:封装一定的功能,决定了函数具有通用性。做一个功能得考虑好哪些部分是公用的,封装得好,事半功倍。
def print_list(lists) # lists 这里是"形式参数",假设这里有一个参数 lists。
lists = [1,2,3]
print_list(lists) # 这里的 lists 是实实际际存在的,因此也称为“实际参数”
- 下面一段代码很真实的体现了 python “容器变量” 内存地址是如何真实运行的。相同的写法 PHP 可是做不到一样的效果
result = []
for c in range(len(list01[0])):
line = [] # 已经声明为一个列表地址空间,后面的列表操作 line 即可影响到 result[line[]]
result.append(line) # 列表操作不在乎顺序,在乎内存地址关联性
for r in range(len(list01)):
line.append(list01[r][c])
- 函数内存图
在“方法区存储函数,不执行函数体”,
因为调用函数,所以开辟一块内存空间,叫“栈帧”
用于存储在函数内部定义的变量(包含参数)
执行完毕后栈帧立即释放(所创建的变量立即销毁)
def fun01(a):
# 改变的是传入的不可变对象
a = 100
a = 1
fun01(a)
print(a) # 1
def fun02(a):
# 改变的是传入的可变对象
a[0] = 100
list01 = [1]
fun02(list01)
print(list01[0]) # 100
def fun03(a):
# 改变的是 fun03 栈帧中变量 a 的指向
a = 100
list01 = [1]
fun03(list01)
print(list01[0]) # 1
** 特别注意函数内部修改的是“传入的可变对象” 还是修改“栈帧变量”**
总结:
可变、不可变类型在传参时的区别
- 不可变参数类型
数值型(整数、浮点数、复数)
布尔值
None
字符串 str
元组 tuple
固定集合 frozenset - 可变参数类型
列表 list
字典 dict
集合 set
不可变类型的数据在传参时,函数内部不会改变原数据的值
可变类型的数据在传参时,函数内部可以改变原数据的值
作用域
- 什么是作用域?
变量作用的范围 - Local 函数内部, Global 全局作用域
# 全局变量
g01 = "OK"
def fun01():
# 局部变量:在函数内部定义的变量
# 在函数内部可以读取全局变量,但是不能修改全局变量
l01 = 100
print(l01)
# 局部作用域,可以调用全局变量
# print(g01) # 下边 g01 定义为全局了, 这里不能再调用了
# 这里胡 g01 只椒函数栈帧内部定义的变量
# g01 = "No"
# 先定义后使用, g01 提升到外部作为全局变量
global g01
g01 = "No"
print(g01)
fun01()
-
作用域内存图
函数的形参与实参
- 实参传递方式
- 形参传递方式
"""
练习66: 函数参数
"""
def fun01(a, b, c, d):
print(a)
print(b)
print(c)
print(d)
# 位置实参: 实参与形参的位置依次对应
fun01(1, 2, 3, 4)
# 序列实参(有序:list、str、tuple) 星序-散开
# 星号将序列散开
# 如果参数很多,可以存储在序列(字符串、列表、元组)中,
# 再通过 * 拆分,直接传入函数。
list01 = ["a", "b", "c", "d"]
fun01(*list01)
# 关键字实参:实参与形参根据名称进行对应
fun01(b=2, d=4, c=3, a=1)
# 字典实参:双星号将字典才分后按名称与形参进行对应
# 如果参数很多,可以存储在字典中,
# 再通过 ** 拆分,直接传入函数。
dict01 = {"a": 1, "c": 3, "b": 2, "d": 4}
fun01(**dict01)
# 缺省(默认)参数: 如果实参不提供,可以使用默认值
def fun02(a=0, b=0, c=0, d=0):
print(a)
print(b)
print(c)
print(d)
# 关键字实参 + 缺省形参: 调用者可以随意传递参数
fun02(b=2, c=3)
# 星号元组形参: * 将所有实参合成一个元组
# 作用:让实参个数无限
def fun03(*args):
print(args) # (1, 2, 3)
fun03(1, 2, 3)
# 关键字形参: 在星号元组形参后的位置必须使用关键字实参
def fun04(a, *args, b):
print(a) # 1
print(args) # (2, 3, 4)
print(b) # 5
fun04(1, 2, 3, 4, b=5)
# 双星号字典形参
def fun06(**kwargs):
print(kwargs) # {'m': 1, 'n': 2}
fun06(m=1, n=2)
# 前面任意,name 必填
def func07(*, name, **kwargs):
print(name) # 111
print(kwargs) # {'first': 888, 'a': 1}
func07(first=888, name=111, a=1)