学校本学期开设了python课,因为懂得都懂原因,python入门得很艰难(无奈.jpg)。因此,在学校的python实验课之前,对python进行了一波恶补,这篇博客是对我的现有知识的一个总结,希望能帮到想入门python的你!
【表达式】:形如1 + 2 - 3
表达式的返回值:表达式的结果1 + 2 - 3 = -1
字面值常量(对象):形如 1 2 3
加+ 减- 乘* 除/ 被称为算术运算符
对于表达式:1 + 2 / 3 ,及其返回值1.6666666665python中明确区分整数除法(//)和浮点数除法(/)(对比C语言和Java),而且因为浮点数是有精度超过范围数据会变得不准确
至于为什么不是0.66666666667,编程中一般没有“四舍五入”的概念
(但是C语言的浮点数中好像有,比如说0.857只输出小数点后两位,会输出0.86,编程题遇到、VS测试、还没有翻C语言文档查证)
变量赋值语句的规则:变量名 + 赋值符(=) + 对象
变量命名的硬性规则与软性规则:
硬性:
软性:
使用变量无外乎两种操作:
python中的变量的类型不需要在定义变量时显式声明而是依靠初始化语句的值的类型来确定
在python中能够表示的数据的范围是“无穷”的。
python中的 int 能够根据要表示数据的大小进行自动扩容。
因此,在python中没有 byte, short, long类型
在python中的 float 都是双精度的,等同于C++/Java中的double类型
在python中,没有像C++/Java那样把单个字符作为一个类型,只有字符串这个类型。
字符串是指通过单引号或者双引号把一串字符括起来
内置函数len()测量字符串长度
拼接字符串的两个操作
【1】使用 字符串 + 字符串 操作
【2】使用 字符串 * 整数 操作
【1】类型决定了数据在内存中占据多大的空间
计算机里面使用二进制来表示数据,每个二进制位只能表示 0 或 1
一个二进制位,称为“一个比特”;8个二进制位,称为一个“字节”
【2】类型决定了能够对这个变量进行什么操作
例如:int / float 类型的变量,可以进行加减乘除等操作
而 str 类型的变量,只能进行 + (字符串拼接操作),但是不能进行减乘除操作
【总结】类型系统其实是在变量进行“归并”,相同类型的变量(数据)往往具有相似的特性和使用规划
使用三引号引起来的称为“文档字符串”,也被视为一种注释
加:+ ,减:- ,乘:* ,除:/ ,整除:// ,求余数:% ,乘方:**
注意点1: / 、// 这两个符号都不能以 0 作为除数,否则会抛出异常
注意点2:整数 / 整数 的结果是浮点数;整数 // 整数的结果是整数(舍弃小数部分)
注意点3:整除 // 的 “ 向下取整 ”(向较小值取整)
运算符 | 描述 |
---|---|
== | 比较两个对象是否相等 |
!= | 比较两个对象是否不相等 |
> | 返回x是否大于y |
< | 返回x是否小于y |
>= | 返回x是否大于等于y |
<= | 返回x是否小于等于y |
所有比较运算符返回True表示真,返回Flase表示假。
运算符 | 逻辑表达式 | 描述 |
---|---|---|
and | x and y | 如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。 |
or | x or y | 如果 x 是非 0,它返回 x 的计算值,否则它返回 y 的计算值。 |
not | not x | 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。 |
赋值运算符 | 功能 |
---|---|
= | 赋值,例如a=1+2 |
+= | 加法赋值,例如a+=1等同于a=a+1 |
-= | 减法赋值,例如a-=1等同于a=a-1 |
*= | 乘法赋值,例如a*=1等同于a=a*1 |
/= | 除法赋值,例如a/=1等同于a=a/1 |
**= | 幂运算赋值,例如a**=2等同于a=a**2 |
//= | 整除赋值,例如a//=3等同于a=a//3 |
%= | 取模赋值,例如a%=2等同于a=a%2 |
:= | 海象运算赋值,3.8版本新增运算符 |
range() 是python的一个内置函数
效果:产生一系列的整数
range(0,10) 等价于一个前闭后开区间 [0, 10)
for i in range(0, 10): # 0 1 2 3 4 5 6 7 8 9
print(i)
# 输出:
0
1
2
3
4
5
6
7
8
9
或许你发现了在循环中每次打印一个值都要默认换行,使数据看起来非常难受,那么接下来要介绍输出的一个知识点
【设置一行打印一个循环的数据】
print() 默认打印完数据之后就换行,这其实取决于一个它的一个参数 end
这个参数默认设置为 end = “\n”
所以要手动修改,根据需求手动换行
# 打印 0 1 2 3 4 5 6 7 8 9
for i in range(0, 10):
print(i, end=" ")
# 第三个参数是步长,表示每次循环变量每次更新多少,默认+1
print("\n")
# 打印 0 2 4 6 8
for i in range(0, 10, 2):
print(i, end=" ")
print("\n")
# 打印 1 3 5 7 9
for i in range(1, 10, 2):
print(i, end=" ")
print("\n")
# 步长一定为正数吗?
# 打印 9 8 7 6 5 4 3 2 1
for i in range(9, 0, -1):
print(i, end=" ")
计算机中的函数与数学上的函数虽然同名,但本质不是一回事,可以简单理解成:一段重复使用的代码。
提问:对于重复代码,直接ctrl+c,ctrl+v不就好了吗?
回答:
注意点:
1.函数要经过函数调用才会实行执行函数体的里面的代码语句!
2.函数定义必须要在函数调用之前!
形参实参数量上要一一对应,但类型上可以不用(动态类型)
但这并不意味着随便传入啥类型都可以。而是要保证在传入的参数类型在函数体里有能够支持的逻辑操作才行
通用的编程原则:一个函数只做一件事!
在实际开发中,一般更倾向于这种写法!
一个函数中的多个return语句:
python的优势:一次返回多个值!
每次想要计算区间求和时,只需要改动一下数据尽可,避免工作量且使得函数使得代码更为简洁明了
代码错误 -> 表示你写的代码中出现了实打实的问题,程序无法运行
代码警告 -> 提示你的代码可能存在的问题,但是该行为并不影响程序的运行
def getPoint():
x = 10
y = 20
return x, y
x, y = getPoint()
print(x, y)
函数里面的x,y和函数外部的x,y是同一组变量吗?
答:变量是有作用域的。
一个变量名的有效范围是一定的!只在一个固定的区域内生效。
为了更好的理解这个概念,我们来看下面这张图片:
那么有没有什么方法可以在函数内部访问且改动全局变量呢?
链式访问的概念:一个函数的返回值作为另一个函数的参数
# 判断奇数
def isOdd(num):
if num % 2 == 0:
return False #不是奇数
return Ture #是奇数
print(isOdd(10))
注意点:链式访问的层次不要太深,否则容易影响代码可读性!
函数的嵌套调用的概念:在一个函数体内部调用别的函数。
def test()
print("Hello")
test()
这个就是简单的函数嵌套调用的例子。
在pycharm的左下角能够看到函数之间的“调用栈”,调用栈里面描述了当前这个代码的函数之间的调用关系
每一层的这个调用关系就被称为“函数的栈帧”,每个函数的局部变量就在这个栈帧中体现。
每个函数的局部变量保存于对应的栈帧中。
函数结束后函数栈帧销毁,内存空间还给操作系统,栈帧中的局部变量也会被销毁。
每次递归调用后都要不断朝着递归结束条件逼近,否则走向死递归,栈溢出,程序崩溃。
def add(x, y)
print(f"x = {x}, {y}")
return x + y;
result = add(10, 20)
像**print(f"x = {x}, {y}")**这种在函数内部进行打印信息的操作,对于程序员来说有助于调试。但是我们同时又希望在正式发布的场合不要出现,只出现于调试阶段,这时候我们就要用到带默认值的形参了。
def add(x, y, debug = False)
if debug:
print(f"x = {x}, {y}")
return x + y;
result = add(10, 20)
在第二份代码中,函数形参多增加了一个参数debug并且将其置为False。
这样的操作的好处在于,它对发布版本是没有影响的,如果我们程序员自身想要进行调试的话,可以手动传入第三个参数
result = add(10, 20, Ture)
通过这样的默认值设定,就可以让函数的设计更加灵活。
强调:带有默认值的形参得在形参列表的末尾,不能在中间/前面
按照位置的先后顺序来传参,也称为“位置参数”
这其实就是我们最常用的写法
def add(x, y)
return x + y;
result = add(10, 20)
实参10和形参x对应,实参20与形参y对应
按照形参的名字来进行传参,被称为“关键字传参”
def test(x, y)
print(f"x = {x}")
print(F"y = {y}")
test(x = 10, y = 20)
这样子就可以非常明显的理解参数要传给谁。
另外,这种写法还有一个好处是,可以无视形参和实参的顺序。
test(y = 20, x = 10)
这两种写法是完全等价的。
那么,位置参数和关键字参数能够混合使用吗?
答案是肯定的,只不过要求位置参数在前,关键字参数在后。
补充:
关键字参数一般是搭配默认参数来使用的。对于一个函数,可以提供很多的参数来调整这个函数的内部功能设定,但是为了降低调用者的使用成本,一般把大部分的参数设定为默认值。
因此,当调用者需要调整其中的一部分参数时,就可以搭配关键字参数来进行操作。
在需要处理大量数据时,创建一个个单独的变量就显得非常麻烦,因此,需要一种变量可以一次存放大量的数据,而列表和元组就是这样的变量,类似于其他编程语言中的“数组”。
列表和元组的大部分功能都是差不多的,但是有一个非常明显的区别:
列表是可变的:创建好了之后通过下标访问科随时修改。
元组是不可变的:创建好了之后,没有办法修改,如果想要修改,只能舍弃旧的元组,建一个新的元组。
第一种:直接使用字面值来创建
# [] 表示一个空列表
a = []
不仅仅创建空列表,也可以在创建列表的时候指定列表的初始值
# [] 表示一个空列表
a = [1, 2, 3, 4]
python的列表不像其他语言的数组,要通过循环来格式化输出,列表类型的变量能通过print直接打印
print(a)
第二种:使用**list()**来创建
a = list()
C/C++/Java 里面要求数组只能存放相同类型的变量,但是python里的列表则此限制,放什么类型的数据都可以。
a = [1, "hello", Ture, [4, 5, 6]]
print(a)
列表里面可以通过下标来访问列表中的元素,因此,需要用到下标访问运算符 []
把[]放到一个列表变量的后面,同时[]里写上一个整数,此时他就是下标访问运算符。[]中间写的这个整数,就是”下标“或者说“索引”。
# 使用下标访问列表元素
a = [1, "hello", Ture, [4, 5, 6]]
print(a[2])
# 打印Ture
下标为2,指的是第二个元素吗?
其实不是的,列表中下标是从0开始计数,0->1->2,表示的是第三个元素,即Ture
使用下标可以对列表中的元素进行修改
# 使用下标访问列表元素
a = [1, "hello", Ture, [4, 5, 6]]
print(a[2])# 打印Ture
a[2] = 2
print(a[2])#打印数字 2
如何去获取一个列表的长度 -> len()函数
# 使用len()函数获取列表长度
a = [1, 2, 3, 4]
print(len(a)) # 列表长度为4
下标是有上限的,越界访问程序抛出异常
a = [1, 2, 3, 4]
#列表下标的最大值为len(a)-1,超过这个值就会报错
print(a[100]) #程序抛出异常
但是,下标有下限吗?或者说,下标能为负数吗?
a = [1, 2, 3, 4]
print(a[3]) # 4
print(a[-1]) # 4
# 两次打印结果相同
因此,你可以理解为[-1]访问的是列表的倒数第一个元素。
前面学习的下标访问操作可以一次取出一个元素。
接下来讲的切片操作则可以一次取出一组连续的元素,相当于得到一个子列表
#使用 [:] 的方式进行切片操作
a = [1, 2, 3, 4]
print(a[1:3]) #输出 2, 3
a[1:3]中的1表示起始位置的下标,3表示结束位置的下标,表示的是 [1,3) 这样的一个前闭后开的区间
a = [1, 2, 3, 4]
print(a[1:]) #省略后边界 - 从指定起始位置开始,直到列表结束。
#输出 2, 3, 4
print(a[:3]) #省略前边界 - 从列表起始位置开始,知道指定结束位置。
#输出 1, 2, 3
print(a[:]) #省略前后边界 - 相当于获取整个列表
#输出 1, 2, 3,4
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(a[::]) #不指定步长,采用默认值
#输出 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
print(a[::1]) #指定步长为1
#输出 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
print(a[::2]) #指定步长为2
#输出 0, 2, 4, 6, 8
print(a[1::2]) #指定步长为2,起始位置下标为1
#输出 1, 3, 5, 7, 9
print(a[::-1]) #指定步长为-1
#输出 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
切片操做只是取出了原有列表中的一个部分,而不是“数据拷贝”。
遍历操作:指的是把列表里面的每个元素都依次取出来,并进行某种操作
a = [1, 2, 3, 4, 5]
for element in a:
element += 10
print(element)
print(a[0])
#输出:
# 11
# 12
# 13
# 14
# 15
# 1
element - 表示将列表中元素取出来,并赋值给element
for in 后面要求是一个可迭代对象,列表a符合要求
迭代过程中(循环)把列表中每个值都打印出来
a = [1, 2, 3, 4, 5]
for i in range(0, len(a)):
a[i] = a[i] + 10
print(a)
print(a[0])
#输出:
# 11
# 12
# 13
# 14
# 15
# 11
5.1 和 5.2 中都打印了a[0],但是 5.1 的打印结果是 1,而 5.2 的打印结果是 11。二者对比可以发现,通过下标遍历能够修改列表中的元素,而第一种方法不可以,在实际中,一般是运用下标来遍历列表的
a = [1, 2, 3, 4, 5]
i = 0
while i < len(a):
print(a[i])
i += 1
#输出:
# 1
# 2
# 3
# 4
# 5
a = [1, 2, 3, 4]
a.append(5)
a.append("hello")#一次只能插入一个
print(a)
# 输出 [1, 2, 3, 4, 5, "hello"]
a = [1, 2, 3, 4]
a.insert(1, "hello")
#第一个参数表示插入位置的下标
#第二个参数表示插入的元素
print(a)
# 输出 [1, "hello", 2, 3, 4]
# 1 使用 in 来判定某个元素是否在列表中
a = [1, 2, 3, 4]
print(1 in a) # 输出Ture
print(10 in a) # 输出False
# 2 使用 not in 来判定某个元素是否在列表中
print(1 not in a) # 输出False
print(10 not in a) # 输出Ture
# not in 相当于是对 in 进行逻辑取反
# 使用 index 方法来判定,当前元素在列表中的位置,函数返回值为下标
a = [1, 2, 3, 4]
print(a.index(2)) # 输出 1
print(a.index(16))
# 如果查找的元素不在列表内,程序抛出异常
# 1.使用 pop 删除列表最尾部的元素
a = [1, 2, 3, 4]
a.pop()
print(a)
# 输出[1, 2, 3]
# 2.使用 pop 还能删除任意位置的元素
# 要求是 pop 的参数是列表元素的下标
b = [1, 2, 3, 4]
b.pop(1)
print(b)
# 输出[1, 3, 4]
上面的方法是通过下标来进行删除操作的,下面再来介绍一种通过元素的值来进行删除的方法
# 使用 remove 方法,按照值的形式来删除
a = ["aa", "bb", "cc", "dd"]
a.remove("aa")
print(a)
# 输出 ["bb", "cc", "dd"]
如果列表内含有多个指定值,默认删除第一个
a = ["aa", "aa", "bb", "cc", "dd"]
a.remove("aa")
print(a)
# 输出 ['aa', 'bb', 'cc', 'dd']
注意:
1.此处的 + 的结果会生成一个新的列表,不会影响旧的列表的内容
2. + 左右两边的列表交换会影响到新列表的循序
# 使用 + 连接两个列表
a = [1, 2, 3]
b = [4, 5, 6]
c = a + b
print(a)
print(b)
print(a + b)
print(b + a)
# 输出 [1, 2, 3]
# 输出 [4, 5, 6]
# 输出 [1, 2, 3, 4, 5, 6]
# 输出 [4, 5, 6, 1, 2, 3]
a = [1, 2, 3]
print(a)
b = [4, 5, 6]
a.extend(b)
print(a)
print(b)
# 输出 [1, 2, 3]
# 输出 [1, 2, 3, 4, 5, 6]
# 输出 [4, 5, 6]
另外,extend方法是没有返回值的,如果拿一个变量来接受一个没有返回值的方法的返回值。
最终会输出None(相当于C语言中的NULL)
使用 + 无法对列表a进行修改,但是使用可以 +=
a += b 表示 a = a + b
列表a和列表b拼产生了一个新的更大的列表,然后把新列表交给变量a。
这种方法虽然也能达到extend方法的效果,但是相较与extend方法,它多了三步的消耗。
1 开辟一块新的更大的空间来存放拼接好的列表
2 将拼接好的列表拷贝给变量a
3 垃圾回收机制将旧的列表a的内存释放
第一种方法
a = ()
第二种方法
a = tuple()
a = (1, 2, 3, 4, 5)
元组与列表类似,能够存放不同类型的数据
a = (1, "hello", Ture, [])
下标从0开始,到 len - 1 结束,超过则抛出异常
a = (1, 2, 3, 4, 5)
print(a[1])
print(a[5])
print(a[100]) # 下标 》 4 ,抛出异常
元组的切片操作与列表是相似的,不在过多展开
#使用 [:] 的方式进行切片操作
a = (1, 2, 3, 4)
print(a[1:3]) #输出 2, 3
元组的遍历操作操作与列表是相似的
a = (1, 2, 3, 4, 5)
for element in a:
element += 10
print(element)
但是,元组有一个特点,就是元组是不可修改的
a = (1, 2, 3, 4, 5)
for i in range(0, len(a)):
a[i] = a[i] + 10
print(a[i])
像这种写法是完全不可行的
编译器将会抛出如下异常:
IndentationError: unindent does not match any outer indentation level
元组的查找操作操作与列表是相似的,不在过多展开
# 1 使用 in 来判定某个元素是否在列表中
a = (1, 2, 3, 4)
print(1 in a) # 输出Ture
print(10 in a) # 输出False
# 2 使用 not in 来判定某个元素是否在列表中
print(1 not in a) # 输出False
print(10 not in a) # 输出Ture
# not in 相当于是对 in 进行逻辑取反
元组的拼接方式和列表差不多
但是根据元组特性a.extend()是无法使用的
def getPoint():
x = 10
y = 20
return x, y
x, y = getPoint()
print(type(getPoint()))
# 输出
字典是包含若干键值对的无序、可变序列
”键“和”值“是两个单独的概念
”键“和”值“之间用冒号分隔(如,键 : 值)
”键“可重复;”值“不可重复
所有键值对用大括号 {} 括起来
第一种:
a = {}
第二种:
a = dict()
a = {"id":"12345", "name":"zhangsan", "score":100}
注意:
往字典中添加键值对时,要注意,键是不可重复且是不可变的(比如说常量、元组),值是可重复和可变的。
前面提到在python中字典时无序的,然而我们遍历打印时,输出的结果是按照我们刚开始插入的循序去打印。这是因为python开发者对其做了特殊处理
# 第一种:使用 for 循环遍历字典
a = {
"id": 1,
"name": "lisi",
"score": 60
}
for key in a:
print(key, a[key])
# 输出:
# id 1
# name lisi
# score 60
# 第二种:
# 使用 key 方法能获取到字典中所有的key
# 使用 values 方法能够获取到字典中的所有value
# 使用 items 方法能够获取到字典中所有的键值对
# 三个方法的返回值都是一个自定义类型,可以看作是一个列表
student = {
"id": 1,
"name": 'zhangsan',
"score": 80
}
print (student.keys())
# 输出:dict_keys(['id', 'name', 'score'])
print (student.values())
# 输出:dict_values([1, 'zhangsan', 80])
print (student.items())
# 输出:dict_items([('id', 1), ('name', 'zhangsan'), ('score', 80)])
# 这个较为特殊,返回的列表中的每个元素都是一个包含key和value的元组
for key, value in student.items():
print(key, value)
# 输出:
# id 1
# name zhangsan
# score 80
变量是将数据保存在内存中,如果程序重启/主机重启,内存中的数据就会丢失。
想要把数据持久化保存,就可以把数据存储到硬盘中,也就是在文件中保存。
常见的文件有以下类型:
虽然上述的文件都是文件,但是文件之间存储数据的格式也是差异很大的,
下面将重点放在较为简单的文本文件。
一个文件由三个部分组成:文件路径+文件名+文件后缀
一个文件的既可以使用“正斜杠/”也可以使用“反斜杠\",一般使用“正斜杠/”比较方便,因为"反斜杠\"在python中由特殊含义,“反斜杠\“与一些字符会组成转义字符,比如说,想要在屏幕上打印\,要print(”\\”)
文件在打开、使用完之后,一定要记得关闭!
打开文件其实是在申请一定的系统资源,因此在不使用文件时,资源要及时释放,否则可能因为文件资源泄露,进一步导致代码无法正常运行。
换句话说,一个系统的资源是有限的,因此,一个程序能够打开的文件个数也是有上限的。
8189这个数字其实挺特别的。
8189 + 3 = 8192 = 2 的 13 次方(计算机中的很多数据是按照二进制来存储的)
每个程序运行的时候都会默认打开三个文件:
1 标准输入——从键盘获取数据——input()
2 标准输出——输出到显示器——print()
3 标准错误——输出到显示器——编译器的输出错误信息栏
另外,一个程序打开的文件个数是可以设计的
在计算机中,都是使用”数字“来表示字符;具体那个数字对应哪个汉字,在计算机中,可以有多个版本(如:GBK、UTF8等)
在pycharm中,文件的默认打开编码解析方式为 GBK ,但是,在日常生活中 UTF8 格式的使用更为广泛及常见。
如果你使用的python解释器读取文件失败,请去查看一下文件打开的编码解析方式与文件本身的编码解析方式是否一致。
不一致,请对关键字参数 encoding 进行手动修改
如果,文本文件中有多行文本时,请注意一个容易被忽视的字符 ’ \n ’
它不会明确的表示出来,但是它确实让文本产生了多行的效果
打开文件之后,在代码越复杂的情况下,越容易忘记关闭文件,python提供上下文管理器,辅助程序员关闭文件