欢迎访问我的GitHub
https://github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套原始码,涉及Java、Docker、Kubernetes、DevOPS等;
本篇概览
- 欣宸是个Java程序员,最近正在学习Python,本文记录了学习程序,以及一点自己的思考,主要用途是作为笔记来总结和温习,另外如果您也是一位初学Python的Java程序员,希望本文能给您一些参考;
版本
作业系统:macOS Big Sur (11.6)
Anaconda3:2021.05
python:3.7.3
Jupyter Notebook:5.7.8
工具
- 编辑器用的是Jupyter Notebook,以下三个快捷键最常用到,尤其是第三个,执行当前行,并新增一行:
- 废话不多说了,直接开始动手操作;
除法
- 一个斜杠的除法,结果是浮点型,两个斜杠的触发,结果是整形:
字符串
- 格式化的时候,可以不指定自变量索引,此时按照出现顺序处理:
- 也可以在花括号中添加数字:
-
还可以在花括号中添加冒号,在冒号之后添加特定的输出格式
-
保留小数点后三位,f表示浮点数:
- 带符号保留小数点后三位,f表示浮点数:
- 不显示小数:
串列
- 逗号分隔,方括号包裹:
-
串列各个元素的型别无需相同(这一点和Java阵列是不同的)
-
访问串列中的元素,使用方括号+索引(从0开始):
- 索引数值可以为负,负一表示倒数第一:
- 与字符串的字符不同之处在于,串列的元素可以修改:
- 分片,下面代码表示从0开始,一直取到2-1位置(左闭右开):
- 分片的时候,冒号左边不填就表示从0开始,右边不填表示直到最后一个元素:
- 分片可以接受第三个自变量:步长,下面的表示每遍历两个元素才取一个
- 当步长等于负一的时候,相当于反转了:
- 用加号实作两个串列相连:
- 串列乘以数字N,表示生成一个新的串列,内容是原串列的N份复制:
- append:尾部追加元素
- insert:将元素插入在指定位置
- extend:将一个串列追加到另一个串列尾部
- 方法
id可以查看物件的存储器地址,如下图,可见经历了append、insert、extend等操作后,存储器地址不变,也就是说这些都是原地操作(in place):
串列的洗掉操作
-
洗掉串列元素有三种方式:pop、remove、clear
-
pop()会弹出最后一个元素:
- 也可以将索引作为入参传入,这样就能洗掉指定元素:
- remove方法的入参是串列中的值,也就是找到串列中与入参相同的元素,将其删掉,下图可见,myList中有两个'abc',用remove会洗掉第一个:
- clear方法会清空串列:
串列的记数和索引
- count方法统计指定元素在串列中的数量,从下图可见1在串列中出现了两次:
- index查找指定元素出现的位置:
串列排序
- sort方法用来排序,默认是比较元素大小:
- 默认是升序,添加reverse=True表示降序:
- sort操作的是串列物件本身,还可以用全域函式sorted来排序,该函式会生成一个新的副本,如下图,newList是排序后的串列,而原有的myList保持不变:
与串列相关的常用全域函式
-
除了sorted,还有一些常用的全域函式和串列有关:
-
operator(取代原有的cmp),用于比较大小以及是否相等:
- len:计算个数
- max:回传最大值
- min:回传最小值
- list:元组转为串列
- zip:两个串列中,同位置元素结合成一个元组,最终得到一个元组串列:
- enumerate:将指定串列的每个元素与其位置下表组成一个元组,最终得到一个元组串列(和上面的zip用法相似,不过简单多了,range操作已经在enumerate内部实作),如下图:
元组
- 元组与串列相似,但是一旦创建就不能修改,创建使用的是圆括号(串列是方括号)
-
要注意的是,只有一个元素的元组也要带逗号,例如(1,),这很好理解,毕竟(1)就是个整数而已
-
没有括号,只有逗号,也是元组:
- 下标操作和串列相同:
- 串列转元组用tuple函式:
- tuple函式还能将字符串直接转为元组:
- 修改元组会失败:
- 修改元组的思路是创建新的元组,如下图,用三个元组拼接的方式生成了一个新的元组,相比旧的,新元组的第三个元素已经从2变为'a',给人以修改过的感觉:
字典
- 字典和Java的map相似,由多个键值对构成,键和值之间用冒号分隔,多个键值之间用逗号分隔,外面用大括号包裹:
-
字典看起来很像json
-
items方法回传所有元素,keys回传所有键,values回传所有值:
- 可以用键查找值,和Java的map一样,不过语法是中括号:
- 也可以用get方法回传键对应的值,还能指定键不存在时的默认值:
- 直接用方括号,可以修改,如果键不存在就是添加:
- update方法的入参是另一个字典,该方法可以将入参字典的内容合并进自身:
- pop方法洗掉指定元素,popitem方法洗掉最后一个元素:
集合(Set)
-
提到Set,Java程序员应该不陌生,就是咱们经常用来排重的那个Set,是个无序元素集
-
集合用逗号分隔,大括号包裹:
-
小结三种包裹方式:串列方括号,元组圆括号,字典和集合大括号(字典的元素是键值对,集合是单个元素),另外元组可以不包裹,有逗号就行
-
set方法可以将串列转为集合:
-
集合的元素都是不可变型别的,如数值、字符串、元组
-
可变型别不能作为集合的元素,如串列、字典、集合,至于其中原因,看看下图红框的错误信息,如果您是个Java程序员,应该get到了:
- 可以用减号或者difference方法求两个集合的差集:
程序逻辑控制
- if判断,是用if、elif、else的组合,注意if、elif、else的行末尾都有冒号:
-
python不支持switch
-
if判断的三元运算子,赋值的时候可用if else组合:
- 普通的for回圈:
- 内置函式range可以创建整数串列,也能在for回圈中遍历:
- while回圈的语法和java相似:
- 回圈中的break和continue与Java类似,就不赘述了
推导式:串列
- 格式如下:
[生成表达式 for 变量 in 序列或迭代物件]
- 测验如下,a就是串列推导式生成的串列:
- 还可以通过if增加筛选条件,例如下面是只保留偶数:
- 如果串列的元素也是串列,我们可以用串列推导将其解开,平铺为一层,下图的例子中,a_element是a的元素,a_element自身也是串列,还可以用推导将其展开:
推导式:字典
- 对字典用推导式,可以取得键和值的处理,下面是用推导式生成一个新的字典,剔除了键为age的键值对:
推导式:集合
- 下面使用推导式,利用串列生成一个新集合,里面的值是原串列每个元素的平方,而且由于集合的不重复性,原串列中重复的元素已经被过滤为只剩一个:
汇入库
- 语法:
import 模块名 [as 别名]
- 例如汇入math模块来计算正弦值:
- 如果觉得每次在代码中写math太麻烦,还可以在汇入时设定别名:
- 如果觉得别名也麻烦,能不能把m.也去掉,可以用以下语法:
from 模块名 import 物件名
例如:
- 上述极简的方式是不推荐使用的,因为缺少了namespace隔离,在API的正确性上就缺少了保障
关于自己的模块
- 假设有一个python档案hello.py,内容如下,定义了名为doHello的方法,再执行一下试试:
def doHello():
print("hello world!")
doHello()
- 现在另一个档案test.py,里面会呼叫hello.py中的doHello的方法:
import hello
hello()
- 执行命令python test.py,结果如下,可见hello world!输出了两次:
will$ python test.py
hello world!
hello world!
-
上述结果显然不是我们想要的,test.py只是想使用doHello方法,结果将hello.py中的doHello()也执行了,需要一种方式来避免test.py中的doHello()被执行
-
这时候内置变量name就派上用场了(注意前后都是两个下划线),将hello.py改成如下内容,如果执行python hello.py,内置变量name的值就是main,其他时候,例如hello.py被其他档案import的时候,它的值就是模块名(这里就是hello):
def doHello():
print("hello world!")
if __name__=='__main__':
doHello()
- 再试试python test.py,这次只有一次输出了:
will$ python test.py
hello world!
- 我们再试试python hello.py,也能按照预期输出:
will$ python hello.py
hello world!
包
-
对于Java程序员来说,包很好理解,在python中也很相似,接下来咱们尝试一下,创建名为test的包,里面有两个模块:test1和test2
-
加入包名为test,咱们创建名为test的档案夹
-
test档案夹下,新增档案init.py,这是个空档案
-
创建档案test1.py:
def doTest1():
print("hello test1!")
- 再创建档案tes2.py:
def doTest2():
print("hello test2!")
- 现在回到test2.py档案的上一层目录,创建档案hello.py,用来验证如何使用包,可见访问方式是包名.模块名.方法名:
import test.test1 as test1
import test.test2 as test2
test1.doTest1()
test2.doTest2()
- 运行hello.py试试:
will$ python hello.py
hello test1!
hello test2!
内建模块:collections
-
Java程序员对collections包不会陌生,这里面都是一些和容器相关的类,为咱们的开发提供了极大便利,接下来看看该模块常用的几个类
-
namedtuple:可以用名字访问内容的元组子类,从下面的代码可见,namedtuple可以方便的定义一个物件,很像java中的bean:
from collections import namedtuple
# 自定义元组物件
Student = namedtuple('Student', ['name', 'age'])
# 实体化Student
student = Student('Tom', 11)
# 看一下student的型别
print(type(student))
# 使用name栏位
print(student.name)
# 使用age栏位
print(student.age)
- 执行结果如下,可见student的name和age栏位都能方便的访问到,而student实体的型别是class:
will$ python test.py
<class '__main__.Student'>
Tom
11
内建模块:deque
- deque是双向队列,在增加和洗掉资料的时候比串列的性能更好(串列的读性能更好),基本操作如下所示:
from collections import deque
# 实体化deque
dq = deque([1,2,3])
# 队列右侧增加元素
dq.append(4)
print('1. {}'.format(dq))
# 队列左侧增加元素
dq.appendleft(5)
print('2. {}'.format(dq))
# 指定位置增加元素
dq.insert(1, 6)
print('3. {}'.format(dq))
# 最右侧元素弹出(洗掉)
dq.pop()
print('4. {}'.format(dq))
# 最左侧元素弹出
dq.popleft()
print('5. {}'.format(dq))
# 洗掉元素,注意2是值,不是位置
dq.remove(2)
print('6. {}'.format(dq))
# 倒排
dq.reverse()
print('7. {}'.format(dq))
- 执行结果如下:
will$ python deque.py
1. deque([1, 2, 3, 4])
2. deque([5, 1, 2, 3, 4])
3. deque([5, 6, 1, 2, 3, 4])
4. deque([5, 6, 1, 2, 3])
5. deque([6, 1, 2, 3])
6. deque([6, 1, 3])
7. deque([3, 1, 6])
内建模块:OrderedDict
- OrderedDict是有顺序的字典,如果您了解LFU(Least frequently used)算法,那么就很容易理解有序的字典了,OrderedDict中的顺序是元素被添加的先后顺序,普通用法如下:
from collections import OrderedDict
# 实体化
od = OrderedDict()
# 添加
od['a'] = 1
od['c'] = 2
od['b'] = 3
# 顺序是添加的先后顺序
print("1. {}".format(od))
# 打印所有的键
print(od.keys())
# 把一个字典合并进来
od.update({'e':'4'})
# 顺序是添加的先后顺序
print("2. {}".format(od))
# 根据键洗掉键值对
od.pop('a')
print("3. {}".format(od))
# 把指定键的键值对移到末尾
od.move_to_end('c')
print("4. {}".format(od))
- 输出如下:
will$ python ordered.py
1. OrderedDict([('a', 1), ('c', 2), ('b', 3)])
odict_keys(['a', 'c', 'b'])
2. OrderedDict([('a', 1), ('c', 2), ('b', 3), ('e', '4')])
3. OrderedDict([('c', 2), ('b', 3), ('e', '4')])
4. OrderedDict([('b', 3), ('e', '4'), ('c', 2)])
内建模块:defaultdict
- defaultdict容易理解:带有默认值的字典,用法如下所示,要注意的是defaultdict实体化的入参是lambda表达式,至于这个lambda,相信java程序员并不陌生:
from collections import defaultdict
dd = defaultdict(lambda: 'ABC')
dd['a'] = 1
# 打印一个存在的键值
print(dd['a'])
# 打印一个不存在的键值
print(dd['b'])
- 输出如下:
will$ python defaultdict.py
1
ABC
内建模块:Counter
- Counter提供了计数器功能,下面的demo演示了用Counter将串列转为了每个元素的统计结果,要注意的是most_common方法,相当于排序和串列的功能,该方法的回传值是串列,里面的元素是元组:
from collections import Counter
# 一个普通串列
colors = ['aa', 'bb', 'cc', 'aa']
# 将串列传给Counter进行统计
result = Counter(colors)
# 打印result型别
print(type(result))
# 打印result内容
print(result)
# 用内置函数dict将Counter实体转为字典
print(dict(result))
# 取统计值最高的前两个元素
most = result.most_common(2)
# 检查most_common回传值的型别
print("most_common's type {}".format(type(most)))
# 检查most_common回传值的型别
print("most_common's value : {}".format(most))
- 输出结果如下:
will$ python Counter.py
<class 'collections.Counter'>
Counter({'aa': 2, 'bb': 1, 'cc': 1})
{'aa': 2, 'bb': 1, 'cc': 1}
most_common's type <class 'list'>
most_common's value : [('aa', 2), ('bb', 1)]
内建模块:datetime
- 名为datetime的模块中,有个名为datetime的类
- 还可以实体化datetime物件:
- datetime物件的年月日时分秒等栏位:
- 转时间戳:
- 还可以通过strptime方法将指定格式的字符串转为datetime物件:
- datetime物件转字符串也是常见操作,用的是strftime方法:
- 时间的计算,例如一天前,一小时后等操作,可以使用datetime包的timedelta类完成:
- datetime物件可以用减法结算时间差:
- 减法特性在计算日期间隔的时候很有用:
JSON处理
- 利用json进行物件和字符串之间的序列化、反序列化转换:
- 还可以用dump和load方法通过档案进行序列化反序列化操作
内置模块:random
- 生成随机数也是常见操作:
- 还可以产生整形随机数,设定内容范围和递增单位:
- 在一堆内容中做随机选择:
- 用choices方法(注意不是choice),可以随机选择指定数量的结果:
- choices得到的结果可能重复,如果想不重复可以用sample方法:
- 将原有集合资料的顺序打乱,相当于洗牌的效果:
函式
- 基本函式语法:
def 函式名([自变量串列]):
函式体
- 和Java不同的是,函式的入参型别并不固定:
- 使用关键字pass,可以定义一个空方法:
def test():
pass
- 一个函式可以回传多个值(本质上是个元组),呼叫的时候用多个变量来接收即可:
- 还可以给函式增加说明档案,然后用help命令查看:
- 呼叫自变量的时候可以用自变量名=xxx的形式传入自变量,此时自变量自变量的先后顺序可以随意,无所有谁先谁后:
- 可变自变量和Java的方法也相似,先看一个星号的可变自变量,可以理解为元组:
- 再看两个星号的可变自变量,可以理解为字典:
- 对于固定自变量的函式,还可以直接将字典作为入参,不过要加两个星号:
- 还可以设定默认自变量:
lambda表达式
- java程序员对lambda表达式很熟悉,这里也差不多,来看看如何定义和使用:
-
再来看看几个支持lambda的内置函式,熟悉lambda的使用
-
filter:过滤器,下面是个过滤奇偶数的例子,第一个自变量是判断是否过滤的逻辑,True保留,第二个自变量是串列,最终奇数全部被剔除,只留下偶数:
- map:逐一转换,下面是将奇数转为False,偶数转为True的例子:
- reduce:大名鼎鼎的map reduce,您应该有所耳闻,reduce会将集合中的资料逐个取出来和前面一轮的结果做同样的处理,最典型的当属累加:
- sort:排序,先来看看最简单的:
- sorted可以接受排序处理函式作为自变量,例如按照绝对值进行排序,内置函式是abs,被作为自变量传给sorted:
- sorted方法会生成一个新的串列,如果想直接改变原串列就不适合用sorted方法了,此时用串列的sort方法即可,如下图,还用了reverse自变量试试倒排序的功能:
面向物件
- 身为Java程序员,天天和物件打交道,下面的代码您应该很容易看懂:
- 如果变量名是由两个下划线开始的,就表示改变数是私有成员变量,不能在外部访问:
-
与Java不同的是,创建物件不需要关键字new
-
继承:
class 派生类名 (父类名):
陈述句...
- 下面是个继承的例子,Student是父类,Pupil是子类:
# 父类
class Student:
# 成员变量
name = '未知'
age = 11
__addr= 'ShangHai'
# 构造方法
def __init__(self, name, age, addr):
print('执行构造方法')
self.name = name
self.age = age
self.__addr = addr
def myInfo(self):
print('学生姓名[{}],年龄[{},地址[{}]]'.format(self.name, self.age, self.__addr))
class Pupil(Student):
#成员变量
grade = 1
# 构造方法
def __init__(self, name, age, addr, grade):
# 显式呼叫父类构造方法
Student.__init__(self, name, age, grade)
print('执行构造方法(子类)')
self.grade = grade
# 子类自己的方法
def myGrade(self):
print('学生年级[{}]'.format(self.grade))
- 执行效果如下,符合预期:
生成器
- 先回顾一下串列推导,下面的代码会生成一个串列:
a = [x*2 for x in range(10)]
- 如果串列很大就会很占用存储器空间,此时我们还有另一个选择:生成器,简单的说就是将上述代码的方括号改成圆括号,这样a就不是串列了,而是生成器,这是种特殊的迭代器:
例外处理
- 习惯了java的try-catch-finally,对python的例外处理就容易理解了,捕获和处理如下:
try:
x = 1/0
print('不可能打印这一句')
except ZeroDivisionError as err:
print('发生例外', err)
finally:
print('执行finally')
- 输出如下图:
- 关键字raise可以主动抛出例外:
- 以上就是欣宸在自学Python程序中的简化版笔记,希望能帮助您在初期抓住重点,快速入门;
你不孤单,欣宸原创一路相伴
- Java系列
- Spring系列
- Docker系列
- kubernetes系列
- 数据库+中间件系列
- DevOps系列
欢迎关注公众号:程序员欣宸
微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界...
https://github.com/zq2599/blog_demos
0 评论