本篇博文目录:
- 一.Python基础语法
- 1.Python基础知识
- 2.了解Python的基础语法结构
- 3.python基础知识
- 二.数据类型
- 1.数字
- 2.字符串
- 3.布尔
- 4.空值:None
- 5.列表
- 6.元祖
- 7.字典
- 8.Bytes
- 9.集合(Set)
- 三:程序三大结构( 顺序结构,分支结构,循环结构)
- 1.顺序结构
- 2.分支结构
- 3.循环结构
- 四.函数
- 1.函数的基础
- 2.函数参数的类型
- 3.变量的作用域
- 4.递归函数
- 5.匿名函数
- 6.迭代器
- 五.内置函数
一.Python基础语法
1.Python基础知识
- 什么是Python
官网解释:Python 是一种编程语言,可让您快速工作并更有效地集成系统。片面的解释一下Python语言,第一该语言是一门高级的编程语言(简单易学,易用);第二该语言是一种解释类型的脚本编程语言(不会生成目标代码,边编译边运行);第三该语言开源,可以查看该编程语言的源代码,生态好。python官网地址:https://www.python.org/。
- python的二个版本
需要注意的是python稳定版本分为二类python2和python3,按照Python官方的计划,Python2只支持到2020年,为了不带入过多的累赘,Python3在设计的时候没有考虑向下相容,许多针对早期Python版本设计的程序都无法在Python3上正常执行。
- python环境的搭建
Python2.x安装及环境变量配置:https://blog.csdn.net/zafkiel_/article/details/104070775
Python3开发环境搭建详细教程:https://cloud.tencent.com/developer/article/1724511
2.了解Python的基础语法结构
不同的语言有不同的语法结构比如中文,英文,德语,日语等,编程语言也是一样的Java,C,C++,C# 等,但是对于编程语言的语法来说相似度非常的高,更加容易学习,下面给出几个学习Python语言的教程网站,可以通过该教程网站来了解Python的语法结构。
- 菜鸟编程Python3.0教程
地址:https://www.runoob.com/python3/python3-basic-syntax.html
- C语言中文网
地址:http://c.biancheng.net/python/
- 刘江的博客教程(推荐)
地址:https://www.liujiangblog.com/course/python/1
3.python基础知识
- python的行与缩进
pyhton和其他语言比如java,C语言等有个非常大的变化就是行与缩进上;python最具特色的就是使用缩进来表示代码块,不需要使用大括号 {} 。缩进的空格数是可变的,但是同一个代码块的语句必须包含相同的缩进空格数。
实例代码:
if True:
print ("True")
else:
print ("False")
运行效果:
缩进不同代码输出的结果也会不同,如果严重的话还可能会出现错误:
if True:
print ("Answer")
print ("True")
else:
print ("Answer")
print ("False") # 缩进不一致,会导致运行错误
运行效果:
- python变量和常量
python是一种动态语言,数据类型不需要进行声明,直接用变量名表示变量,变量的赋值还是使用“=”并且python并没有对常量有严格的定义,通常采用大写字母表示变量的名字,但是该值还是能够进行改变。
实例代码:
num = 10 # 变量
PI = 3.1415926 # 常量
备注:变量的作用域见函数章节内容。
- python的运算符
Python语言支持运算符有算术运算符;比较(关系)运算符;赋值运算符;逻辑运算符;位运算符;成员运算符;身份运算符;三目运算符
算术运算符:
需要注意一下取整数除,可以理解为整数做除法,没有小数部分。
比较运算符:
需要注意Python支持"<>" 表示不等于,而在其他语言如Java中并不支持。
赋值运算符:
位运算符:
逻辑运算符:
注意这里并不支持,"&&“和”||"这种逻辑运算符。
成员运算符:
in 与 not in是Python独有的运算符(全部都是小写字母),用于判断对象是否某个集合的元素之一,非常好用,并且运行速度很快。返回的结果是布尔值类型的True或者False。
身份运算符:
注意:is用于判断两个变量的引用是否为同一个对象,而==用于判断变量引用的对象的值是否相等!
三元运算符:
和其他语言不一样的是三元运算符的格式为:
为真时的结果 if 判定条件 else 为假时的结果
;例如: True if 5>3 else False
- python的标准输入和输出函数
输入函数:input()
输出函数:print()
实例代码:
inputNum = input("请输入一个数:")
print("这个数是:"+inputNum)
运行效果:
需要注意不管输入的是数值还是字符串最后赋值的都是一个字符串类型的数据,所以需要进行判断和数据类型的转换,否则可能会造成错误的产生:
实例代码:
inputNum = input("请输入一个数:")
print("这个数是:"+inputNum)
inputNum += 100
print(inputNum)
运行效果:
解决办法:
inputNum = input("请输入一个数:")
print("这个数是:"+inputNum)
num = int(inputNum)
num += 100
print(num)
运行效果:
二.数据类型
在Python的世界,数据类型分两种,内置的和自定义的。内置的包括数字、字符串、布尔、列表、元组、字典、Bytes、集合这些常用的以及一些不太常用的数据类型。而自定义的,一般以类的形式,根据需要组合以上内置类型成为独特的数据类型。
为什么要设置数据类型:
1.数字
Python 支持三种不同的数字类型,整数、浮点数和复数:
- 整数(Int)
包括负整数和正整数,不带小数点的数,在Python3中可以通过整数来表示更大的数(Long),所以在Python3中没有Long类型。
需要注意的是整数是一个无符号类型,指的是类型的值一旦有不同了,那么它就是一个全新的对象。
案例代码:
num = 20
num = 30
print(num)
运行效果:
注意:上文中num值的变化并不指的是数值的变化而是num对象指向的变化,从num指向整型20变成了指向整型30。
小整数对象池:
Python初始化的时候会自动建立一个小整数对象池,方便我们调用,避免后期重复生成!这是一个包含262个指向整数对象的指针数组,范围是-5到256。比如整数10,即使我们在程序里没有创建它,其实在Python后台已经悄悄为我们创建了。
实例代码:
# 观察-5~256的地址
print("-6的地址:",id(-6))
print("-5的地址:",id(-5))
print("-4的地址:",id(-4))
print("255的地址:",id(255))
print("256的地址:",id(256))
print("257的地址:",id(257))
运行效果:
小整数对象池:
Python还有整数缓冲区的概念,也就是刚被删除的整数,不会被真正立刻删除回收,而是在后台缓冲一段时间,等待下一次的可能调用。
实例代码:
num = 100000
print("num的地址:",id(num))
del num
newNum = 100000
print("newNum的地址:",id(newNum))
运行效果:
- 浮点
浮点数也就是小数,如1.23,3.14,-9.01,等等。但是对于很大或很小的浮点数,一般用科学计数法表示,把10用e替代,1.23x10^9就是1.23e9,或者12.3e8,0.000012可以写成1.2e-5,等等。
实例代码:
fNum = 36.2
fnum2 = 1.23e8 # 1.23x10^8
print("fNum=%f;fNum2=%f"%(fNum,fnum2))
运行效果:
- 复数
复数由实数部分和虚数部分构成,可以用a + bj,或者complex(a,b)表示,复数的实部a和虚部b都是浮点型。关于复数,不做科学计算或其它特殊需要,通常很难遇到。
实例代码:
cNum = 10+6j
cNum2 = complex(10,6)
print("cNum=%s;cNum2=%s"%(cNum,cNum2))
运行效果:
需要注意的是复数返回的是字符串,如果使用整型的占位符会报
%d format: a number is required, not complex
异常。
- 数据类型的转换
有时候,我们需要对数字的类型进行转换。Python为我们提供了方便的内置的数据类型转换函数。
函数 | 说明 |
---|---|
int(x) | 将x转换为一个整数。如果x是个浮点数,则截取小数部分。 |
float(x) | 将x转换到一个浮点数。 |
complex(x) | 将x转换到一个复数,实数部分为 x,虚数部分为 0。 |
complex(x, y) | 将 x 和 y 转换到一个复数,实数部分为 x,虚数部分为 y。 |
- 数学计算
对于数学计算,除了前面提到过的简单的加减乘除等等,更多的科学计算需要导入math这个库,它包含了绝大多数我们可能需要的科学计算函数,如下表。
实例代码:
import math
print(math.log(2))
print(math.cos(30))
print(math.cos(60))
print(math.sin(30))
print(math.sin(math.degrees(30)))
print(math.sin(math.radians(30)))
运行效果:
2.字符串
字符串是Python中最常用的数据类型之一,使用单引号或双引号来创建字符串,使用三引号创建多行字符串。字符串要么使用两个单引号,要么两个双引号,不能一单一双!Python不支持单字符类型,单字符在Python中也是作为一个字符串使用。字符串是不可变的序列数据类型,不能直接修改字符串本身,和数字类型一样!Python3全面支持Unicode编码,所有的字符串都是Unicode字符串,所以传统Python2存在的编码问题不再困扰我们,可以放心大胆的使用中文。
实例代码:
var1 = 'Hello World!'
var2 = "Jack"
var3 = "" # 空字符串
var4 = "it's apple" # 双引号中可以嵌套单引号
var5 = 'This is "PLANE"!' # 单引号中可以嵌套双引号
# 三引号创建多行字符串
var6 = '''
<HTML><HEAD><TITLE>
Friends CGI Demo</TITLE></HEAD>
<BODY><H3>ERROR</H3>
<B>%s</B><P>
<FORM><INPUT TYPE=button VALUE=Back
ONCLICK="window.history.back()"></FORM>
</BODY></HTML>
'''
print(var1)
print(var2)
print(var3)
print(var4)
print(var5)
print(var6)
运行效果:
注意:单引号嵌套单引号或者双引号嵌套双引号就会出现歧义。
虽然字符串本身不可变,但可以像列表序列一样,通过方括号加下标的方式,访问或者获取它的子串,当然也包括切片操作。这一切都不会修改字符串本身,当然也符合字符串不可变的原则。
s = "hello world!"
print("操作前:",s)
print(s[0])
print(s[0:2])
print("操作后:",s)
运行效果:
字符串的运算:
Python转义字符:
编程语言里,有很多特殊字符,它们起着各种各样的作用。有些特殊字符没有办法用普通字符表示,需要进行转义。python用反斜杠()转义字符。如下表:
关于字符串更多的操作,请查看这篇博文:https://www.liujiangblog.com/course/python/21
3.布尔
在Python语言中,布尔类型只有两个值,True与False。请注意,是英文单词的对与错,并且首字母要大写,不能其它花式变型。
实例代码:
print("===结合and===")
print(True and False)
print(True and True)
print("===结合or===")
print(True or False)
print(False or False)
print("===结合not===")
print(not False)
print(not False)
print("===结合is===")
print(True is False)
print(True is True)
print("===结合is not===")
print(True is not False)
print(False is not False)
print("===结合bool()===")
print(bool(3 >1 and 5 > 3))
运行效果:
注意:Python内置的bool()函数可以用来测试一个表达式的布尔值结果。
4.空值:None
空值是Python里一个特殊的值,用None表示(首字母大写)。None不能理解为0,因为0是整数类型,而None是一个特殊的值。None也不是布尔类型,而是NoneType。(其他语言中的null)
实例代码:
print(bool(None))
print(type(None))
运行效果:
5.列表
Python的列表是一个有序可重复的元素集合,可嵌套、迭代、修改、分片、追加、删除,成员判断。从数据结构角度看,Python的列表是一个可变长度的顺序存储结构,每一个位置存放的都是对象的指针。(类似于Java中的不带泛型修饰的ArrayList集合)
实例代码:
alist = [1, "a", [11, 22], {"k1":"v1"}]
print(alist)
运行效果:
更多列表的操作将这篇博文:https://www.liujiangblog.com/course/python/19
练习:
# 创建列表
alist = [1, "a", [11, 22], {"k1":"v1"},"b","c"]
print(alist)
# 通过索引查询;注意下标从0开始,不要越界
print(alist[0])
# 修改列表中的值
alist[0] = 2
print(alist[0])
# 删除列表的值del;remove;pop
del alist[0]
alist.remove("a")
alist.pop(0)
alist.pop()
print(alist)
#列表常用函数
print("len():%d"%(len(alist)))
print("max():%d"%(max([1,2,3])))# 不能混合其他数据类型的值
print("min():%d"%(max([1,2,3])))
s = list((1, "a", "b", 2))
print("list():",s)
# 切片
# [start:end]省略start表示以0开始,省略end表示到列表的结尾。注意,区间是左闭右开的![1:4]会截取列表的索引为1/2/3的3个元素
blist = [0,1,2,3,4,5,6,7,8,9]
print(blist[1:4])
# 提供的是负整数下标,则从列表的最后开始往头部查找;例如-1表示最后一个元素,-3表示倒数第三个元素;切片过程中还可以设置步长,以第二个冒号分割,例如list[3:9:2],表示每隔多少距离取一个元素
print(blist[-1::-2])# - 2表示从右往左走2步;
print(blist[1::2])# 2表示从左往右走2步
print(blist[::])# 不设置表示所有
运行效果:
6.元祖
元组用()括起来表示的数据,是一种不可变的序列结构,除了在内部元素不可修改的区别外,元组和列表的用法差不多。
元组与列表相同的操作:
- 使用方括号加下标访问元素
- 切片(形成新元组对象)
- count()/index()
- len()/max()/min()/tuple()
元组中不允许的操作,确切的说是元组没有的功能(元组里的数据无法修改):
- 修改、新增元素
- 删除某个元素(但可以删除整个元组)
- 所有会对元组内部元素发生修改动作的方法。例如,元组没有remove,append,pop等方法。
实例代码:
num = (1,[2,3,4],5)
print(num)
print(num[1][0])
运行效果:
元组只保证它的一级子元素不可变,对于嵌套的元素内部,不保证不可变,如下:
num = (1,[2,3,4],5)
print(num)
print("修改前的值:",num[1][0])
num[1][0] = 1
print("修改后的值:",num[1][0])
运行效果:
7.字典
Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度,字是一种不定长、可变、散列的集合类型。字典的key必须是不可变的对象,例如整数、字符串、bytes和元组,最常见的还是将字符串作为key。列表、字典、集合等就不可以作为key。同时,同一个字典内的key必须是唯一的,但值则不必。(类似于Java中的Map集合)
字典的每个键值对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中 ,例如:
d = {key1 : value1, key2 : value2 }
常使用的字典操作:
dic = {} # 创建一个空字典
# 添加数据
dic["name"] = "张三"
dic["age"] = 20
dic["id"] = "101"
# 通过key获取值
print("获取学生的姓名",dic["name"])
# 修改学生的姓名
dic["name"] = "李四"
print("获取学生的姓名",dic["name"])
# 删除字段元素,情况字典和删除字典
print(dic)
del dic["name"]
print("删除key为name后:",dic)
popKey = dic.pop("age") # 弹出并返回指定的键
print("弹出:",popKey)
print(dic)
# 清空字典
dic.clear()
print("清空字典后:",dic)
# 删除字典本身
del dic
运行效果:
字典的常用方法:
下表中列出了字典的重要内置方法。其中的get、items、keys和values是核心中的核心,必须熟练掌握!
实例代码:
dic = {"one":{1,2,3},"two":1,"three":3}
newDic = dic.copy()
print(newDic)
print("dic的地址=%d;newDic的地址=%d"%(id(dic),id(newDic)))
print("dic的one地址=%d;newDic的地址=%d"%(id(newDic.get("one")),id(newDic.get("one"))))
list = ['1','2','3','4']
newList = dic.fromkeys(list,"默认值")
print(newList)
print("删除前:",newList)
print("删除数据:",newList.popitem())
print("删除后:",newList)
print(newList.setdefault(4))
print(newList)
newList.update(newDic)
print(newList)
运行效果:
字典的常见变量方式:
dic = {'Name': 'Jack', 'Age': 7, 'Class': 'First'}
# 1 直接遍历字典获取键,根据键取值
for key in dic:
print(key, dic[key])
# 2 利用items方法获取键值,速度很慢,少用!
for key,value in dic.items():
print(key,value)
#3 利用keys方法获取键
for key in dic.keys():
print(key, dic[key])
#4 利用values方法获取值,但无法获取对应的键。
for value in dic.values():
print(value)
运行效果:
注意:从Python3.6开始,字典是有序的!它将保持元素插入时的先后顺序!请务必清楚!
8.Bytes
在Python3以后,字符串和bytes类型彻底分开了。字符串是以字符为单位进行处理的,bytes类型是以字节为单位处理的。bytes数据类型在所有的操作和使用甚至内置方法上和字符串数据类型基本一样,也是不可变的序列对象。
实例代码:
b = b'' # 创建一个空的bytes
print(b)
b = bytes() # 创建一个空的bytes
print(b)
b = b'hello' # 直接指定这个hello是bytes类型
print(b)
b = bytes('hello',encoding='utf-8') #利用内置bytes方法,将字符串转换为指定编码的bytes
print(b)
str = "hello"
b = str.encode('utf-8') # 利用字符串的encode方法编码成bytes,默认为utf-8类型
print(b)
bytes = b
print(bytes.decode('utf-8')) # 将bytes对象解码成字符串,默认使用utf-8进行解码。
运行效果:
9.集合(Set)
set集合是一个无序不重复元素的集,基本功能包括关系测试和消除重复元素。集合使用大括号({})框定元素,并以逗号进行分隔。但是注意:如果要创建一个空集合,必须用 set() 而不是 {} ,因为后者创建的是一个空字典。集合除了在形式上最外层用的也是花括号外,其它的和字典没有一毛钱关系。(类似于java中的Set,采用Map中的key不使用Value,这样key不能重复,起到去重的作用)
常见操作代码实例:
# 创建Set集合
s = set([1,2,3,4,5])
print(s)
s = set("it is a nice day")
print("字符串,集合会一个一个字符的拆开",s)
# 添加元素
s.add("你好呀")
print(s)
s.update("hello")
print("使用update函数后:",s)
# 删除
s.remove("你好呀")
print("删除后:",s)
s.pop()
print("删除后:",s)
运行效果:
除了add、clear、copy、pop、remove、update等集合常规操作,剩下的全是数学意义上的集合操作对集合进行交并差等,既可以使用union一类的英文方法名,也可以更方便的使用减号表示差集,“&”表示交集,“|”表示并集。看看下面的例子:
实例代码:
basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
print(basket) # 自动去重
print("apple是否存在该对象",('apple' in basket))
# 以下演示了两个集合的交、并、差操作
a = set('abc')
b = set('ad')
# 求交集
print(a&b)
# 求差集
print(a - b)
# 求并集
print(a | b)
运行效果:
三:程序三大结构( 顺序结构,分支结构,循环结构)
1.顺序结构
了解Python的代码执行顺序至关重要。学习链接:https://www.liujiangblog.com/course/python/26
python代码在执行过程中,遵循下面的基本原则:
普通语句,直接执行;
碰到函数,将函数体载入内存,并不直接执行
碰到类,执行类内部的普通语句,但是类的方法只载入,不执行
碰到if、for等控制语句,按相应控制流程执行
碰到@,break,continue等,按规定语法执行
碰到函数、方法调用等,转而执行函数内部代码,执行完毕继续执行原有顺序代码
实例执行顺序理解:
import os # 1
print('<[1]> time module start') # 2
class ClassOne():
print('<[2]> ClassOne body') # 3
def __init__(self): # 10
print('<[3]> ClassOne.__init__')
def __del__(self):
print('<[4]> ClassOne.__del__') # 101
def method_x(self): # 12
print('<[5]> ClassOne.method_x')
class ClassTwo(object):
print('<[6]> ClassTwo body') # 4
class ClassThree():
print('<[7]> ClassThree body') # 5
def method_y(self): # 16
print('<[8]> ClassThree.method_y')
class ClassFour(ClassThree):
print('<[9]> ClassFour body') # 6
def func():
print("<func> function func")
if __name__ == '__main__': # 7
print('<[11]> ClassOne tests', 30 * '.') # 8
one = ClassOne() # 9
one.method_x() # 11
print('<[12]> ClassThree tests', 30 * '.') # 13
three = ClassThree() # 14
three.method_y() # 15
print('<[13]> ClassFour tests', 30 * '.') # 17
four = ClassFour()
four.method_y()
print('<[14]> evaltime module end') # 100
运行效果:
备注:代码执行顺序的说明看此篇博文:https://www.liujiangblog.com/course/python/26
2.分支结构
在Python语法中,使用if、elif和else三个关键字来进行条件判断。(在Python中没有switch – case语句)
实例代码:
num = 10
if num == 9:
print("num等于9")
elif num == 8:
print("num等于8")
else:
print("num不等于9,也不等于8")
备注:分支结构和其他语言没有多大的区别都可以进行嵌套。
3.循环结构
Python用关键字for和while来进行循环控制,但是没有其它语言的do…while语句。
- while
实例代码:
num = 10
while num != 0:
print("num不等于0,当前num=",num)
num -= 1
print("当前num等于0,num=",num)
运行效果:
和其他语言的while不同的是,python语言的while可以添加一个else的从句;当while循环正常执行完毕,会执行else语句。但如果是被break等机制强制提前终止的循环,不会执行else语句。注意else与while平级的缩进方式!
num = 10
while num != 0:
print("num不等于0,当前num=",num)
num -= 1
if num == 8:
print("num等于8结束循环")
break;
else:
print("当前num等于0,num=",num)
print("当前num=",num)
运行效果:
将Num的整型指向7,如下图:
再次运行:
- for
for i in range(0,10):
print(i)
同样的for也可以使用else从句:
for i in range(0,10):
print(i)
else:
print("循环执行结束")
运行效果:
备注:range是一个内置函数可以理解为一个范围的数如(0,10)表示0~9,采用左闭右开
- break语句和continue语句
break语句和continue语句和其他编程语言的没有什么区别,break结束本次循环,continue结束本轮循环,进入下轮循环。
实例代码:
for i in range(0,10):
if i == 5:
print("结束本轮循环")
continue;
if i == 8:
print("结束本次循环")
break;
print("i的值:",i)
else:
print("循环执行完毕")
运行效果:
四.函数
1.函数的基础
在Python中,采用下面的语法定义函数:
def 函数名(参数):
# 内部代码
return 表达式
实例代码:
def summer(list):
total = 0
for i in list:
total += i
return total
if __name__ == '__main__':
list = [1,2,3,4,5,6]
sum = summer(list)
print(sum)
运行效果:
和其他编程语言不同的是Python的函数可以返回多个值:
实例代码:
def getNum(list):
var1 = 0;var2 = 0;var3=0;var4=0
for i in list:
if i == 5:
var1 += 1
elif i == 8:
var2 += 1
elif i == 10:
var3 += 1
elif i == 11:
var4 += 1
return var1,var2,var3,var4
if __name__ == '__main__':
list = [1, 8, 5,5 , 10, 6]
count1,count2,count3,count4 = getNum(list)
print("count1=%d,count2=%d,count3=%d,count4=%d"%(count1,count2,count3,count4))
运行效果:
参数的传递
- Python的函数参数传递的是实际对象的内存地址。
- Python的数据类型分可变数据类型和不可变数据类型。
实例代码(全局变量的b(开头的b=11)和函数内部的b是二个同名但不同对象的b(b=12)):
b = 11
def met(b):
print("b的地址:", id(b))
b = 12
print("b的地址:",id(b))
if __name__ == '__main__':
print("b的地址:", id(b))
met(b)
print("b的地址:",id(b))
运行效果:
实例代码:
def met(list):
print("list的地址:",id(list))
list[0] = 12
print("list的地址:",id(list))
if __name__ == '__main__':
list = [1,2,3,4]
print("list的地址:",id(list))
met(list)
print("list的地址:", id(list))
运行效果:
2.函数参数的类型
函数的参数类型和其他编程语言基本一致分为形参和实参,性参表示形式参数变量进行参数的传递,而实参表示实际的数比如整型的0,但是和Java等语言不同的是python的参数顺序是并不像Java那样固定,可以动态的传递参数给函数,并且python的参数上的操作更加丰富。
- 位置参数
也叫必传参数,顺序参数,是最重要的,也是必须在调用函数时明确提供的参数!位置参数必须按先后顺序,一一对应,个数不多不少的传递!
def add(a, b, c):
return a+b+c
print(add("你","好","呀"))
运行效果:
位置参数就是函数的顺序和传递的一致,顺序不一致输出的结果可能不同,参数的个数也不能少,如果缺少参数会报错,并且没有参数类型的限制,在输入参数时需要进行判断不然会报异常如下:
实例代码:
def add(a, b, c):
return a+b+c
print(add(1,"好","呀"))
运行效果:
- 默认参数
在函数定义时,如果给某个参数提供一个默认值,这个参数就变成了默认参数,不再是位置参数了。在调用函数的时候,我们可以给默认参数传递一个自定义的值,也可以使用默认值。
实例代码:
def power(x, n = 2):
return x**n
print(power(10))# 使用默认值参数
print(power(10, 4)) # 不采用默认值参数
运行效果:
默认参数必须在位置参数后面;当有多个默认参数的时候,通常将更常用的放在前面,变化较少的放后面;在调用函数的时候,尽量给实际参数提供默认参数名。
实例代码:
并不是一定需要按到顺序进行传递,可以使用参数名的方式不按顺序传递参数:
实例代码:
def student(name, age, classroom, tel, address="..."):
print("初始化")
student(classroom=101, name="Jack", tel=66666666, age=20)
默认参数尽量指向不变的对象:
实例代码:
def func(a=[]):
a.append("A")
return a
print(func())
print(func())
print(func())
运行效果:
备注:因为Python函数体在被读入内存的时候,默认参数a指向的空列表对象就会被创建,并放在内存里了。因为默认参数a本身也是一个变量,保存了指向对象[]的地址。每次调用该函数,往a指向的列表里添加一个A。a没有变,始终保存的是指向列表的地址,变的是列表内的数据!
实例代码:
def func(a=[]):
a.append("A")
print(id(a))
return a
print(func())
print(func())
print(func())
运行效果:
- 动态参数
动态参数就是传入的参数的个数是动态的,可以是1个、2个到任意个,还可以是0个。在不需要的时候,你完全可以忽略动态函数,不用给它传递任何值。(其他语言中的可变长参数)Python的动态参数有两种,分别是
*args
和**kwargs
,这里面的关键是一个和两个星号的区别,而不是args和kwargs在名字上的区别,实际上你可以使用*any
或**whatever
的方式。但就如self一样,默认大家都使用*args
和**kwargs
。注意:动态参数,必须放在所有的位置参数和默认参数后面!
1.*args
一个星号表示接收任意个参数。调用时,会将实际参数打包成一个元组传入形式参数。如果参数是个列表,会将整个列表当做一个参数传入。例如:
实例代码:
def func(*args):
for arg in args:
print(arg)
func('a', 'b', 'c')
li = [1, 2, 3]
func(li)
运行效果:
list列表作为整体传递到函数中去了,如果要一个一个的传递只需要在list前面加一个 “*”符号即可,如下:
2.**kwargs
两个星表示接受键值对的动态参数,数量任意。调用的时候会将实际参数打包成字典。例如:
实例代码:
def func(**kwargs):
for kwg in kwargs:
print(kwg, kwargs.get(kwg))
print(type(kwg))
func(k1='v1', k2=[0, 1, 2])
运行效果:
如果将字典数据直接传递过去会怎么样,如下:
实例代码:
def func(**kwargs):
for kwg in kwargs:
print(kwg, kwargs[kwg])
dic = {
'k1': 'v1',
'k2': 'v2'
}
func(dic)
运行效果:
因为这时候,我们其实是把dic当做一个位置参数传递给了func函数。而func函数并不接收任何位置函数。所以会出现异常,只需要加上二个“**” 符号即可,如下:
实例代码:
def func(**kwargs):
for kwg in kwargs:
print(kwg, kwargs[kwg])
dic = {
'k1': 'v1',
'k2': 'v2'
}
func(**dic)
运行效果:
3.变量的作用域
作用域指的是变量的有效范围。变量并不是在哪个位置都可以访问的,访问权限取决于这个变量是在哪里赋值的,也就是在哪个作用域内的。在Python中,没有块级作用域,也就是类似if语句块、for语句块、with上下文管理器等等是不存在作用域概念的,他们等同于普通的语句。
Python的作用域一共有4层,分别是:
- L (Local) 局部作用域
- E (Enclosing) 闭包函数外的函数中
- G (Global) 全局作用域
- B (Built-in) 内建作用域
实例代码:
x = int(2.9) # 内建作用域,查找int函数
global_var = 0 # 全局作用域
def outer():
out_var = 1 # 闭包函数外的函数中
def inner():
inner_var = 2 # 局部作用域
Python以L –> E –> G –>B的规则查找变量,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,最后去内建中找。如果这样还找不到,那就提示变量不存在的错误。
实例代码:
x = int(2.9) # 内建作用域,查找int函数
global_var = 0 # 全局作用域
def outer():
out_var = 1 # 闭包函数外的函数中
def inner():
inner_var = 2 # 局部作用域
print(inner_var)
print(out_var)
print(global_var)
print(x)
inner()
if __name__ == '__main__':
outer()
运行效果:
函数的局部变量和全局变量:定义在函数内部的变量拥有一个局部作用域,被叫做局部变量,定义在函数外的拥有全局作用域的变量,被称为全局变量。(类、模块等同理)
实例代码:
var = 10
def outer(num1,num2):
var = num1 + num2
print(var)
if __name__ == '__main__':
outer(10,20)
print(var)
运行效果:
由于函数outer()中的var是局部变量并没有什么外部全局变量的值,所以就算函数中的var有变化也不行对全局的var有影响,如果函数内部需要使用全局变量的var,需要加上global关键字,如下:
实例代码:
var = 10
def outer(num1,num2):
global var
var = num1 + num2
print(var)
if __name__ == '__main__':
outer(10,20)
print(var)
运行效果:
内部函数和外部函数也存在这类问题,如下:
def outer():
var =10
def inner(num1,num2):
var = num1 + num2
print(var)
inner(10,20)
print(var)
if __name__ == '__main__':
outer()
运行效果:
内部函数加上nonlocal关键字就可以使用外部函数的变量了,如下:
def outer():
var =10
def inner(num1,num2):
nonlocal var
var = num1 + num2
print(var)
inner(10,20)
print(var)
if __name__ == '__main__':
outer()
运行效果:
3.“万能”参数
当
*args
和**kwargs
组合起来使用,理论上能接受任何形式和任意数量的参数,在很多代码中我们都能见到这种定义方式。需要注意的是,*args
必须出现在**kwargs
之前。
实例代码:
def func(*args, **kwargs):
for arg in args:
print(arg)
for kwg in kwargs:
print(kwg, kwargs[kwg])
lis = [1, 2, 3]
dic = {
'k1': 'v1',
'k2': 'v2'
}
func(*lis, **dic)
运行效果:
如果普通参数和万能参数结合起来会怎么样呢?
实例代码:
def func(a, b, c=1, *args, **kwargs):
for arg in args:
print(arg)
for kwg in kwargs:
print(kwg, kwargs[kwg])
lis = ['aaa', 'bbb', 'ccc']
dic = {
'k1': 'v1',
'k2': 'v2'
}
func(1, 2, *lis, **dic)
运行效果:
函数需要5个参数,使用的时候传递了4个参数,第三个参数会从可变参数取一个,所以args输出的只有[‘bbb’, ‘ccc’],我们可以打印一下c看c是否为aaa,如下:
实例代码:
def func(a, b, c=1, *args, **kwargs):
print("c=",c)
for arg in args:
print(arg)
for kwg in kwargs:
print(kwg, kwargs[kwg])
lis = ['aaa', 'bbb', 'ccc']
dic = {
'k1': 'v1',
'k2': 'v2'
}
func(1, 2, *lis, **dic)
运行效果(确实如此):
- 关键字参数
函数参数传递可以根据一定参数格式来限定用户在某一个参数传递什么参数,这就是关键字参数,关键字参数的格式就是关键字参数前面需要一个特殊分隔符
*
和位置参数及默认参数分隔开来,*
后面的参数被视为关键字参数。在函数调用时,关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错。不同于默认参数,关键字参数必须传递,但是关键字参数也可以有缺省值,这时就可以不传递了,从而简化调用。
实例代码:
def student(name, age, *, sex="name"):
print("name=%s;age=%d;sex=%s"%(name,age,sex))
student(name="jack", age=18, sex='male')
student(name="jack", age=18)
student(name="jack", age=18, newSex='newMale',sex='male')
运行效果:
如果函数定义中已经有了一个*args参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符
*
了。
实例代码:
def student(name, age=10, *args, sex, classroom, **kwargs):
print("测试")
student(name="jack", age=18, sex='male', classroom="202", k1="v1")
4.递归函数
递归函数就是函数调函数,每一次调用后任务就会完成一部分,知道最后把所有任务完成,使用递归函数是比较耗性能的,因为每一次递归都会在内存中多开闭一个空间,python的递归函数和其他语言没有多大区别。
实例代码:
def iterateComments(list):
for i in range(len(list)):
# 遍历第二次,遍历字典
iterateDict(list[i])
def iterateDict(dict):
for i in dict.keys():
val = dict.get(i)
if isinstance(val,str):
print(val)
else:
iterateDict(val)
if __name__ == '__main__':
list = [
{
"评论1": "序号1的一级评论",
"评论2":
{
"评论3": "序号1的二级评论",
"评论4":
{
"评论4": "序号1的三级评论"
}
},
},
{
"评论1": "序号2的一级评论",
"评论2":
{
"评论3": "序号2的二级评论"
}
}
]
if __name__ == '__main__':
iterateComments(list)
运行效果:
5.匿名函数
python 中也存在匿名函数,就是没有名字的函数,使用lambda 关键字来表示匿名函数,如下:
实例代码:
f = lambda x:x*x
if __name__ == '__main__':
print( f(10))
运行效果:
6.迭代器
在Python中也存在迭代器的概念,可以通过迭代器将集合中的元素进行迭代获取。
可以通过collections模块的Iterable类型来判断一个对象是否可迭代
实例代码:
from collections.abc import Iterable
# list/tuple/string/dict/set/bytes都是可以迭代的数据类型
print(isinstance([1,2,3], Iterable))
print(isinstance((1,2,[2,5]), Iterable))
print(isinstance("hello World", Iterable))
print(isinstance({"key":"value"}, Iterable))
print(isinstance(set([1,2,3,4]), Iterable))
print(isinstance(b'1', Iterable))
运行效果:
使用迭代器遍历元素:
list = [1,2,3,4,5,6,7,8,9,10]
it = iter(list) # 创建迭代器对象
print(next(it)) # 使用next()获取下一个元素的值
# 通过for遍历迭代器元素
for x in it:
print(x,end=" ")
运行效果:
注意:很多时候,为了让我们自己写的类成为一个迭代器,需要在类里实现__iter__()和__next__()方法
五.内置函数
在编写Python代码的时候发现代码中使用的内置函数并没有进行导入就可以使用非常的方便,这是因为这些函数都是一个叫做builtins模块中定义的函数,而builtins模块默认在Python环境启动的时候就自动导入,所以你可以直接使用这些函数。
你可以通过这篇博文了解Python的内置函数的使用:https://www.liujiangblog.com/course/python/40