Python基础语法(三)
文章目录
函数
函数是什么
数学当中的函数:三角函数:sin,cos,y=ax+b,一个x对应一个y,具有某种映射关系
而编程当中的函数是一段可以被重复使用的代码
# 1.求1-100的和
theSum = 0
for i in range(1, 101):
theSum += i
print(theSum)
# 2.求300-400 的和
theSum = 0
for i in range(300,401):
theSum += i
print(theSum)
# 3.求1-1000的和
theSum = 0
for i in range(1, 1001):
theSum += i
print(theSum)
上面代码我们求了1-100的和,300-400的和,1-1000的和,我们发现功能都是类似的,我们可以使用函数来更加简洁的解决:
# 定义一个求和函数
def calcSum(begin,end):
theSum = 0
for i in range(begin,end):
theSum += i
print(theSum)
# 调用函数
# 1.求1-100的和
calcSum(1,101)
# 1.求300-400的和
calcSum(300,401)
# 1.求1-1000的和
calcSum(1,1001)
def为定义函数关键字。
语法格式
创建函数/定义函数:
def 函数名(形参列表):
函数体
return 返回值
形参列表中,可以有多个形参,多个形参之间使用逗号分隔,return语句并不是必须的。
调用函数/使用函数:
函数名(实参列表) //不考虑返回值
返回值 = 函数名(实参列表) //考虑返回值
-
函数定义并不会执行函数体内容,必须要调用才会执行,调用几次就会执行几次
-
定义在前,调用在后
函数参数
# 定义一个求和函数
def calcSum(begin,end):
theSum = 0
for i in range(begin,end):
theSum += i
print(theSum)
# 调用函数
# 1.求1-100的和
calcSum(1,101)
# 1.求300-400的和
calcSum(300,401)
# 1.求1-1000的和
calcSum(1,1001)
上面代码中:1,101,300,401,1,1001都是函数的实参,begin和end是函数的形参。
注意:
- 一个函数可以有一个形参,也可以有多个形参,也可以没有形参。
- 一个函数的形参有几个,那么传递实参的时候也得传几个,保证个数要匹配函数返回值
函数返回值
函数的参数可以视为是函数的“输入",则函数的返回值就可以视为是函数的“输出”。
此处的“输入",“输出”是更广义的输入输出,不是单纯指通过控制台输入输出.
我们可以把函数想象成一个"厂",工厂需要买入原材料,进行加工,并生产出产品.
函数的参数就是原材料,函数的返回值就是生产出的产品
下列代码:
def calcsum(beg, end):
sum=0
for i in range(beg, end + 1):
sum += i
print(sum)
calc(1,100)
可以转换成:
def calcsum(beg, end):
sum=0
for i in range(beg, end + 1):
sum += i
return sum
result = calcSum(1, 100)
print(result)
这两个代码的区别就在于,前者直接在函数内部进行了打印,后者则使用return语句把结果返回给函数调用者,再由调用者负责打印.
我们一般倾向于第二种写法。
实际开发中我们的一个通常的编程原则,是“逻辑和用户交互分离",而第一种写法的函数中, 既包含了计算逻辑,又包含了和用户交互(打印到控制台上),这种写法是不太好的,如果后续我们需要的是把计算结果保存到文件中,或者通过网络发送或者展示到图形化界面里,那么第一种写法的函数, 就难以胜任了。而第二种写法则专注于做计算逻辑,不负责和用户交互.那么就很容易把这个逻辑搭配不同的用户交互代码,来实现不同的效果。
Python中的一个函数可以返回多个值,C++要想返回多个值,可以通过输出型参数(指针/引用)
写一个函数,返回平面上的一个点:
def getPoint():
x = 10
y = 20
return x, y
a, b = getPoint()
print(f"a = {a},b = {b}")
虽然现在返回了多个值,但是只想用其中的一部分,不关注其他的,可以使用_来进行占位!
_, b = getPoint()
不要x,只要y,把y赋值给b即可!
变量作用域
观察以下代码
def getPoint():
x = 10
y = 20
return x,y
x,y = getPoint()
在这个代码中,函数内部存在x, y,函数外部也有x,y。但是这两组x, y不是相同的变量,而只是恰好有一样的名字,变量只能在所在的函数内部生效。在函数getPoint()内部定义的x, y只是在函数内部生效,一旦出了函数的范围,这两个变量就不再生效了。
def getPoint():
x=10
y=20
return x,y
getPoint()
print(x, y)
在不同的作用域中,允许存在同名的变量,虽然名字相同,实际上是不同的变量。
x=20
def test():
x = 10
print(f'函数内部x = {x}')
test()
print(f'函数外部x = {x}')
值为20的为全局变量,是在整个程序中都有效的,值为10的为局部变量,只是在函数内部有效
在函数里尝试读取全局变量,是可以的!当函数中尝试访问某个变量的时候,会先尝试在局部变量中查找,如果找到,就直接访问,如果没找到,就会往上一级作用域中进行查找。
如果想在函数里面修改全局变量:
x = 10
def test():
# 声明x为全局变量,没有glabal,则会将x当成局部变量进行定义
global x
x = 20
test()
print(f"x = {x}")
像if,while,for这些语句的代码块当中定义的变量,在python当中是可以在外面进行访问的,而C++是不允许的。C++当中是有作用域的限制的,而Python当中的作用域的限制是函数以及类当中。
函数执行过程
- 调用函数才会执行函数体代码,不调用则不会执行
- 函数体执行结束(或者遇到return语句),则回到函数调用位置继续往下执行。
链式调用
前面的代码很多都是写作
#判定是否是奇数
def isOdd(num) ;
if num % 2 == 0:
return False
else:
return True
result = isOdd(10)
print(result)
实际上也可以简化写作:
print(isOdd(10))
把一个函数的返回值,作为另一个函数的参数, 这种操作称为链式调用,这是一 种比较常见的写法。
嵌套调用
函数内部还可以调用其他的函数,这个动作称为“嵌套调用" .
def test():
print ("执行函数内部代码")
print ("执行函数内部代码")
print ("执行团数内部代码")
test函数内部调用了print 函数这里就属于嵌套调用。
一个函数里面可以嵌套调用任意多个函数,函数嵌套的过程是非常灵活的。
函数递归
在Python中,我们知道一个函数可以调用其他函数。函数甚至可能会调用自身。这些类型的构造称为递归函数。
递归函数的示例,求一个数字的阶乘:
def calc_factorial(x):
"""这是一个
求整数阶乘的递归函数"""
if x == 1:
return 1
else:
return (x * calc_factorial(x-1))
calc_factorial(4)
calc_factorial()是一个递归函数,它调用了自己。当我们用正整数调用此函数时,它将通过减少数量来递归调用自身。
每个函数将数字乘以该数字下面的数字的阶乘,直到它等于1。即4! = 4 * 3!,3! = 3 * 2!
递归调用的步骤:
calc_factorial(4) # 1st call with 4
4 * calc_factorial(3) # 2nd call with 3
4 * 3 * calc_factorial(2) # 3rd call with 2
4 * 3 * 2 * calc_factorial(1) # 4th call with 1
4 * 3 * 2 * 1 # return from 4th call as number=1
4 * 3 * 2 # return from 3rd call
4 * 6 # return from 2nd call
24 # return from 1st call
当数字减少到1时,递归结束。这称为基本条件。
每个递归函数必须具有停止递归的基本条件,否则该函数将无限调用自身。
Python解释器限制了递归的深度,以帮助避免无限递归,从而导致堆栈溢出。
默认情况下,最大递归深度为 1000。如果超出限制,则结果为RecursionError。
参数默认值
Python中的函数,可以给形参指定默认值.
带有默认值的参数可以在调用的时候不传参.
代码示例:计算两个数字的和
def add(x, y, debug=False):
if debug:
print(f"调试信息: x={x}, y={y}')
return x+ y
print(add(10,20))
print(add(10, 20,True))
此处debug=False即为参数默认值,当我们不指定第三个参数的时候默认debug的取值即为False.
带有默认值的参数需要放到没有默认值的参数的后面
def add(x, debug=False, y):
if debug:
print(f'调试信息: x={x}, y={y}')
return x + y
print(add(10, 20))
关键字参数
在调用函数的时候,需要给函数指定实参,一般默认情况下是按照形参的顺序,来依次传递实参的。
但是我们也可以通过关键字参数,来调整这里的传参顺序,显式指定当前实参传递给哪个形参:
def test(x, y):
print(f'x = {x}')
print(f'y = {y}')
test(x=10, y=20)
test(y=100, x=200)
形如上述test(x=10, y=20)这样的操作,即为关键字参数。按照形参的名字进行传参,非常明显的告诉程序员,你的参数要传给谁!,可以无视形参和实参的顺序。
列表和元组
什么是列表,什么是元组
编程中,经常需要使用变量,来保存/表示数据。
如果代码中需要表示的数据个数比较少,我们直接创建多个变呈即可。
num1 = 10
num2 = 20
num3 = 30
但是有的时候,代码中需要表示的数据特别多,甚至也不知道要表示多少个数据,这个时候,就需要用到列表。列表是一种让程序猿在代码中批量表示/保存数据的方式
就像我们去超市买辣条,如果就只是买—两根辣条,那咱们直接拿着辣条就走了,但是如果一次买个十根八根的,这个时候用手拿就不好拿,超市老板就会给我们个袋子。这个袋子,就相当于列表。
元组和列表相比,是非常相似的,只是列表中放哪些元索可以修改调整,元组中放的元素是创建元组的时候就设定好的,不能修改调整。
列表和元组类似于C++当中的数组。列表可变,元组不可变。
创建列表
创建列表有两种方式:
- 直接使用字面值来创建
a = []
# []表示一个空的列表
- 使用list()来创建
b = list()
- 可以在创建列表的时候,在[]中指定列表的初始值,元素之间使用,分割
a = [1, 2, 3, 4]
print(a)
C++当中要求一个数组里只能存相同类型的变量
- 可以在同一个列表里放不同类型的变量
a = [1,'hello',True,1.0]
print(a)
访问下标
列表里面可以管理很多元素,通过下标访问的方式来访问列表中的元素,下标访问运算符:[]
a = [1,'hello',True,1.0]
print(a[0],a[1],a[2],a[3])
注意下标从0开始计数。
使用下标修改列表元素:
a = [1,'hello',True,1.0]
a[0] = 100
print(a)
下标的有效范围:[0,长度-1],超出下标有效范围就是越界访问
可以使用内建函数len来获取到列表的长度,和字符串类似,len可以传参字符串,列表,元组,字典,自定义的类等,python中的下标,还可以写成负数,比如a[-1]表示列表a的倒数第一个元素,a[-2]表示列表a的倒数第二个元素
切片操作
通过下标操作是一次取出里面第一个元素,通过切片,则是—次取出—组连续的元素,相当于得到一个子列表
- 使用[ : ]的方式进行切片操作。
alist = [1, 2, 3, 4]
print(alist[1:3])
alist[1:3]中的1:3表示的是[1,3)这样的由下标构成的前闭后开区间。
也就是从下标为1的元素开始(2),到下标为3的元素结束(4),但是不包含下标为3的元素,所以最终结果只有2,3
- 切片操作中可以省略前后边界
alist = [1, 2, 3, 4]
print(alist[1:])
#省略后边界,表示获取到列表末尾
print(alist[:-1])
#省略前边界,表示从列表开头获取
print(alist[:])
#省略两个边界,表示获取到整个列表。
- 切片操作还可以指定“步长”,也就是""每访问—个元素后,下标自增几步”
alist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(alist[::1])
print(alist[::2])
print(alist[::3])
print(alist[::5])
这里再多加一个:,再多加一个数字,这个数字就是步长。
步长的数值还可以是负数,当步长为负数的时候,意思是从后往前来取元素
当切片中的范围超出有效下标之后,不会出现异常!而是尽可能的把符合要求的元素获取到:
alist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(alist[1:100])
切片操作是一个比较高效的操作,进行切片的时候,只是取出了原有列表中的一个部分,并不涉及到"数据的拷贝假设有一个很大的列表,进行切片,切片的范围也很大,即使如此,切片操作仍然非常高效.
遍历列表元素
- 使用for循环进行遍历
a = {1, 2, 3, 4, 5}
for elem in a:
print(elem)
对elem修改,不会影响a列表。
- 使用for循环遍历,通过下标的方式
a = {1, 2, 3, 4, 5}
for i in range(0,len(a)):
print(a[i])
- 使用while循环,通过下标遍历
a = {1, 2, 3, 4, 5}
i = 0
while i < len(a):
print(a[i])
新增元素
- 使用append方法,向列表末尾插入一个元素(尾插)。
alist = [1, 2, 3, 4]
alist.append('he11o')
print(alist)
此处的append是搭配列表对象a,来一起使用的,而不是作为一个独立的函数
type,print,input,len这些自定义函数都是独立的函数,这种要搭配对象来使用的函数,也叫做方法
-
使用insert方法,向任意位置插入—个元素
insert第一个参数表示要插入元素的下标。
alist = [1, 2, 3, 4]
alist.insert(1, "hello")
alist.insert(100, "hello")
print(alist)
什么是"方法”?(method)
方法其实就是函数.只不过函数是独立存在的,而方法往往要依附于某个"对象".
像上述代码 alist.append , append就是依附于alist,相当于是““针对alist这个列表,进行尾插操作”
查找元素
- 使用in操作符,判断元素是否在列表中存在,返回值是布尔类型。
alist = [1, 2, 3, 4]
print(2 in alist)
print(5 in alist)
print(1 not in alist)
#若1不在alist当中,则返回True,否则返回false
print(5 not in alist)
- 使用index方法,查找元素在列表中的下标,返回值是一个整数(下标),如果元素不存在,则会抛出异常
alist = [1, 2, 3, 4]
print(alist.index(2))
print(alist,index(5))
删除元素
- 使用pop删除列表中最末尾的元素
alist = [1, 2, 3, 4]
alist.pop()
print(alist)
- 使用pop还能删除任意位置的元素,pop的参数可以传一个下标过去
alist = [1, 2, 3, 4]
alist.pop(1)
print(alist)
- 使用remove方法,可以按照值来进行删除
a = ['aa', 'bb', 'cc', 'dd']
a.remove('cc')
print(a)
连接列表
- 使用+能够把两个列表拼接在—起。
此处的+结果会生成一个新的列表,而不会影响到旧列表的内容.
alist = [1, 2, 3, 4]
blist = [5, 6, 7]
print(alist + blist)
- 使用extend方法,相当于把一个列表拼接到另一个列表的后面。
a.extend(b),是把b中的内容拼接到a的末尾,不会修改b,但是会修改a。
alist = [1, 2, 3, 4]
b1ist = [5, 6, 7]
alist.extend(blist)
print(alist)
print(blist)
None这是一个特殊的变量的值,表示"啥都没有"。
- 使用+=进行拼接
alist = [1, 2, 3, 4]
b1ist = [5, 6, 7]
alist += blist
print(alist)
print(blist)
看似和extend执行结果一样,但是执行的过程是有差别的,a += b,等价于a = a + b,a += b会首先创建更大的空间来保存a + b,然后再将a + b赋值给a,a的旧值会释放。而extend操作只是将b的值附加到a的末尾了。extend的开销更小一些。
关于元组
元组的功能和列表相比,基本是一致的。
元组使用()来表示。
atuple = ()
atuple = tuple()
元组不能修改里面的元素,列表则可以修改里面的元素
因此,像读操作,比如访问下标切片,遍历, in, index,+等,元组也是一样支持的。
但是,像写操作,比如修改元素,新增元素,删除元素, extend等,元组则不能支持。
另外,元组在 Python中很多时候是默认的集合类型,例如,当一个函数返回多个值的时候。
def getPoint():
return 10, 20
result = getPoint()
print(type(result))
此处的result的类型,其实是元组。
问题来了,既然已经有了列表,为啥还需要有元组?
元组相比于列表来说,优势有两方面:
-
你有一个列表,现在需要调用一个函数进行一些处理,但是你又不是特别确认这个函数是否会把你的列表数据弄乱.那么这时候传一个元组就安全很多。
-
我们马上要讲的字典,是一个键值对结构,要求字典的键必须是"可hash对象"(字典本质上也是一个hash表),而一个可hash对象的前提就是不可变,因此元组可以作为字典的键,但是列表不行。
字典
字典是什么
字典是一种存储键值对的结构。
啥是键值对?这是计算机/生活中一个非常广泛使用的概念。
把键(key)和值(value)进行一个一对一的映射,然后就可以根据键,快速找到值。举个要子,学校的每个同学,都会有一个唯一的学号,知道了学号,就能确定这个同学。此处"学号”就是“键",这个"同学"就是"值"。可以根据key能够快速的找到value。在Python的字典中,可以同时包含很多个键值对,同时要求这些键,不能重复。
创建字典
a = {}
print(type(a))
b = dict()
print(type(b))
创建字典的同时设定初始值:
a= {"id" : 1,
"name" : "zhangsan"
}
print(a)
一个字典中的key的类型不一定都一样,一个字典中的value的类型不一定都一样
查找key
- 使用in可以判定key是否在字典中存在,返回布尔值
student = {
"id": 1,
"name": "zhangsan"
}
print("id" in student)
print("score" in student)
in不能判断value在不在字典中。
- 使用[]通过类似于取下标的方式,获取到元素的值,只不过此处的下标是key,可能是整数,也可能是字符串等其他类型
student = {
"id": 1,
"name": "zhangsan"
}
print(student["id"])
print(student["name"])
- 如果key在字典中不存在,则会抛出异常
student = {
"id": 1,
"name": "zhangsan"
}
print(student["score"])
该error表示这个key在该字典中不存在
新增/修改元素
使用[]来进行新增元素
a = {
"id": 1,
"name": "zhangsan"
}
# 该操作就是往字典中新增元素
a["score"] = 90
print(a)
修改操作,根据key修改value:
a = {
"id": 1,
"name": "zhangsan"
}
# 该操作就是往字典中新增元素
a["score"] = 100
print(a)
如果key 不存在,往里写入,相当于新增键值对。
如果key存在,往里写入,则相当于根据key修改value。
删除元素
使用pop方法,根据key来删除键值对
a = {
"id": 1,
"name": "zhangsan"
}
a.pop("name")
print(a)
遍历字典元素
遍历指的就是能够把一个可迭代对象,里面包含的元素依次的取出来,并进行一些操作.整个过程要求不重不漏。
字典被设计出来的初衷,不是为了实现遍历,而是为了增删改查。字典是哈希表,进行增删改查操作,效率都是非常高的,而字典的遍历则效率就要差一些,哈希表这个结构被设计的非常巧妙,能够以"常数级"时间复杂度来完成增删改查。
直接使用for循环来遍历字典:
# 直接使用for循环来遍历字典
a = {
"id": 1,
"name": "zhangsan"
"socre": 90
}
for key in a:
print(key,a[key])
for循环中对于字典拿到的是key而不是整个key和value。
在C++当中,哈希表里面的键值对存储的顺序是无序的,但是在Python 中还不一样,Python中做了特殊处理能够保证遍历出来的顺序,就是和插入的顺序一致的,Python中的字典,不是一个单纯的哈希表
取出所有key和value
keys 获取到字典中的所有key
values获取到字典中的所有value
items获取到字典中的所有键值对~
# 直接使用for循环来遍历字典
a = {
"id": 1,
"name": "zhangsan"
"socre": 90
}
print(a.)print(a.keys())
print(a.values())
print(a.items())
items返回的元素是一个列表,列表里面又是元组,所以可以这样遍历:
for key,value in a.items():
print(key,value)
合法的key类型
使用hash函数能够计算出一个变量的哈希值
print(hash(0))
print(hash(3.14))
print(hash('hello'))
print(hash(True))
print(hash((1, 2, 3)))
有的类型是不能计算哈希值的:
print(hash([1, 2, 3]))
list是不可哈希类型
print(hash(dict()))
字典也是不可哈希类型。
可以认为一个不可变的对象,一般就是可哈希的,可变的对象,一般就是不可哈希的。
文件
文件是什么
变量是把数据保存到内存中。如果重启程序或者主机重启,内存中的数据就会丢失
要想能让数据被持久化存储,就可以把数据存储到硬盘中,也就是在文件中保存。
电影->mp4文件
歌曲->mp3文件
图片->jpg
文本->txt
表格->xlsx
存储器分为内存和外村,所谓变量就是在内存中,硬盘是外存,文件就是在硬盘中
- 内存的空间更小,硬盘空间更大
- 内存访问更快,硬盘访问更慢
- 内存成本更贵,硬盘成本更便宜
- 内存的数据已丢失,硬盘的数据持久化存储
- 硬盘上存储的数据就是以文件的形式来组织的
文件操作
要使用文件,主要是通过文件来保存数据,并且在后续把保存的数据读取出来,但是要想读写文件,需要先"“打开文件”,读写完毕之后还要"关闭文件""。
1. 打开文件
使用内建函数open打开—个文件。
f = open( "d:/test.txt ", 'r')
第一个参数是—个字符串,表示要打开的文件路径,第二个参数是一个字符串,表示打开方式。其中r表示按照读方式打开。w表示按照写方式打开。a表示追加写方式打开。如果打开文件成功,返回一个文件对象,后续的读写文件操作都是围绕这个文件对象展开。如果打开文件失败(比如路径指定的文件不存在),就会抛出异常。
2. 关闭文件
使用close方法关闭已经打开的文件
f = open( "d:/test.txt ", 'r')
f.close()
文件在打开完之后,使用完了之后,也就一定要关闭!打开文件,其实是在申请一定的系统资源,不使用文件的时候,就应该及时释放,否则会造成文件资源泄漏。
python有一个重要的机制,垃圾回收机制,自动的把不使用的变量给进行释放。
虽然 Python给了我们一个后手,让我们一定程度的避免上述问题,但是也不能完全依赖,自动释放机制~~因为自动释放不一定及时,因此还是要尽量手动释放,万无一失。
3. 写文件
- 直接写方式打开
f = open( "d:/test.txt ", 'w')
#使用write来实现写文件操作,打开文件时需要以写方式打开
f.write("hello")
f.close()
- 追加写方式打开
f = open( "d:/test.txt ", 'w')
#使用write来实现写文件操作,打开文件时需要以写方式打开
f.close()
如果是使用w方式打开,会清空掉文件原有的内容!!!如果是使用a方式打开,则不会清空,写的内容会加在原有内容的末尾。
f = open( "d:/test.txt ", 'a')
#使用write来实现写文件操作,打开文件时需要以写方式打开
f.write("hello")
f.close()
4. 读文件
- 读文件内容需要使用’r’的方式打开文件
- 使用read方法完成读操作,参数表示"读取几个字符"
f = open("d:/test.txt", 'r')
result = f.read(2)
print(result)
f.close()
如果文件内容是中文,读取时可能会报错,要保证文件的编码方式和代码中的打开文件的编码方式相同,所以我们可以这样:
f = open("d:/test.txt", 'r',encoding='utf8')
result = f.read(2)
print(result)
f.close()
在实际开发中,最常见的需求是按行来读取
f = open("d:/test.txt", 'r',encoding='utf8')
for line in f:
print(f'line = {line}')
f.close()
我们发现多了空行,这是因为本来读到的文件内容(这一行末尾就带有\n),此处使用print来打印,又会自动加一个换行符
可以给print多设定个参数,不自动加换行:
print(f'line = {line}', end='')
end参数表示每次打印之后要在末尾加个啥,默认是\n。
还可以使用readlines方法直接把整个文件所有内容都读出来,按照行组织到一个列表里。
f = open("d:/test.txt", 'r',encoding='utf8')
content = f.readlines()
print(content)
f.close()
上下文管理器
打开文件之后,是容易忘记关闭的,Python提供了上下文管理器,来帮助程序猿自动关闭文件:
-
使用with语句打开文件。
-
当with 内部的代码块执行完毕后,就会自动调用关闭方法。
有些情况还是非常容易遗漏close的,防不胜防
def func():
f = open('d:/test.txt', 'r', encoding=utf8)
f.close()
有人说,我直接在写open时,就写close,就不会忘记close了,但是万一中间有条件判断,函数返回,可能就执行不到close了。使用上下文管理器,就能解决这个问题:
def func():
with open('d:/test.txt', 'r', encoding='utf8') as f:
#进行文件处理逻辑
#代码逻辑
#代码逻辑
#代码逻辑
#代码逻辑
#代码逻辑
#代码逻辑
if cond:
return
#代码逻辑
#代码逻辑
#代码逻辑
#代码逻辑
#代码逻辑
#代码逻辑
if cond:
return
不管有多少个条件,多少个return都没关系了,都不用写close了,当with对应的代码块执行结束,就会自动的执行f的close。
库
Python通过模块来体现"库",库就是别人已经写好了的代码,可以让我们直接拿来用。
一个编程语言能不能流行起来,—方面取决于语法是否简单方便容易学习,一方面取决于生态是否完备。所谓的"生态”指的就是语言是否有足够丰富的库,来应对各种各样的场景。实际开发中,也并非所有的代码都自己手写,而是要充分利用现成的库,简化开发过程。
按照库的来源,可以大致分成两大类:
-
标准库: Python自带的库,只要安装了Python就可以直接使用。
-
第三方库:其他人实现的库.要想使用,需要额外安装
咱们自己也可以实现"第三方库"发布出去,交给别人来使用。
标准库
认识标准库
Python自带的库,Python自身内置了非常丰富的库。
在Python官方文档上可以看到这些库的内容:https://docs.python.org/3.10/library/index.html
简单来说,主要是这些部分:
- 内置函数(如print, input 等)
- 内置类型(针对 int, str, bool, list, dict等类型内置的操作)
- 文本处理
- 时间日期
- 数学计算
- 文件目录
- 数据存储(操作数据库,数据序列化等)
第三方库
认识第三方库
第三方库就是别人已经实现好了的库,我们可以拿过来直接使用。虽然标准库已经很强大了,但是终究是有限的。而第三方库可以视为是集合了全世界Python程序猿的智慧,可以说是几乎无穷无尽。问题来了,当我们遇到一个需求场景的时候,如何知道,该使用哪个第三方库呢?
就需要用到百度,谷歌等浏览器了。
当我们确定了该使用哪个第三方库之后,就可以使用pip来安装第三方库了.
使用pip
pip 是 Python 内置的包管理器。
所谓包管理器就类似于我们平时使用的手机 app 应用商店一样。
第三方库有很多,是不同的人不同的组织实现的,为了方便大家整理, Python官方提供了一个网站PyPl PyPI · The Python Package Index,来收集第三方库,其他大佬写好的第三方库也会申请上传到 PyPl上。
这个时候就可以方便的使用pip工具来下载 PyPI上的库了。
pip在我们安装Python 的时候就已经内置了,无需额外安装,pip是一个可执行程序,就在 Python的安装目录中。
生成二维码
二维码本质上就是一段字符串,我们可以把任意的字符串,制作成一个二维码图片,生活中使用的二维码,更多的是一个URL
使用第三方库qrcode进行生成二维码
安装qrcode:
pip install qrcode[pil]
import qrcode
img = qrcode.make('https://blog.csdn.net/attemptendeavor?spm=1000.2115.3001.5343')
img.save("some_file.png")
实现文件查找工具
测试理解:
inputPath = input("请输入要搜索的路径: ")
pattern = input("请输入要搜索的关键词: ")
for dirpath, dirname, filenames in os.walk(inputPath)
print("----------------------------")
print(f'dirpath = {dirpath}')
print('dirnames:')
for name in dirnames:
print(name)
print('filenames:')
for name in filenames:
print(name)
dirpath表示遍历到当前位置对应的路径是啥
dirname表示当前目录下,都有哪些目录,是一个列表,可以包含多个目录名
filenames表示当前目录下,都有哪些文件名,是一个列表,可以包含多个文件名
os.walk每次调用都能自动的去针对子目录进行递归的操作,只需要使用上述循环就可以把所有的路径都获取出来。
实现文件以及目录查找工具:
import os
inputPath = input("请输入要搜索的路径: ")
pattern = input("请输入要搜索的关键词: ")
for dirpath, dirnames, filenames in os.walk(inputPath):
# 目录名
for name in dirnames:
if pattern in name:
print(f"{dirpath}/{name}")
# 文件名
for name in filenames:
if pattern in name:
print(f"{dirpath}/{name}")