1.2.2 Python语言
1.2.2.1 Python发展
1989年圣诞节期间,为了打发无聊的时间,荷兰人Guido van Rossum(吉多·范罗苏姆)(数学、计算机双硕士,2005年加入Google,2013年加入DropBox),决心开发一种新的解释性脚本语言。
1991年初发布了第一个公开发行版。由于他是英国BBC喜剧《Monty Python’s Flying Circus》的忠实粉丝,因此为这门语言取名Python。
Python目前已经成为很多大学的编程课语言。甚至在国内一些考试已经引入了Python。科学计算方面、运维领域Python几乎已经成为最主要的编程语言,拥有非常方便快捷开发的库。
Python的哲学,可以使用import this 查看Python之禅。
Python是Guido van Rossum写的,这个人是一个双料硕士,他在1989年无聊的圣诞节到1990年初这块时间,他圣诞节过的很无聊,怎么办呢,他在原来它所见到的一门语言叫abc这门语言,它在这个语言基础上说能不能舍弃这门语言的难学、难用的特点,我们要创造一个简单易用的语言,他是想创造一门这样的语言,他就开始尝试来做这件事,在1991年初的时候大概花了一年的时间他就把自己写的这个语言就公开了,但这个语言起什么名字呢,这个名字跟BBC的一个喜剧电视剧,这个电视剧是一个喜剧片段集叫《Monty Python’s Flying Circus》(Monty Python’s 的飞行马戏团),Monty Python’s是一个喜剧团体的名称,他们搞的这样的一个喜剧集,也搞好多的喜剧集,一季一季的放,他特别喜欢看这个,每次看的时候是哈哈大笑、前仰后合的,他一拍脑袋说起什么名字,算了咱们就用这里边的python这个词就行了,所以这个语言就这么诞生了,为什么要说一下这个python呢,就是说我们看到的有很多你觉得这个起名字稀奇古怪的,这原因是你没看过这个喜剧集,那么它有一些与python周边相关的很多工具什么的它起名字都跟蛇有关、跟蟒蛇有关,第二个是跟喜剧集里面人物、名称相关的,这是它的一个生态圈、文化圈。
1.2.2.2 Python的版本
目前企业中使用的主要版本还是2.x和3.x。
2.x最后一个版本是2.7,很多企业为了兼容老项目依然在维护。Python2将在2019年底不在支持,官方还提供了一个倒计时网站https://pythonclock.org/。
3.x还在不断的扩充发展,当前主流版本是3.6。
2015年9月发布3.5,2016年12月发布3.6,2018年6月发布3.7,2019年10月发布3.8.0。
Python2和3的区别
- 语句函数化,例如print(1,2)打印出1 2,但是2.x中意思是print语句打印元组,3.x中意思是函数的2个参数
- 整除,例如1/2和1//2,3.x版本中/为自然除
- 3.x中raw_input重命名为input,不再使用raw_input
- round函数,在3.x中i.5的取整变为距离最近的偶数
- 3.x字符串统一使用Unicode
- 异常的捕获、抛出的语法改变
早几年,各主要国内外大公司都已经迁移到了Python3。很多重要的Python第三方库也陆续停止了对Python2的支持,所以,Python 3已经是必须学习的版本。2018年Python3的使用比例已经超过了85%。
在公司内,往往老项目维护维持2.x版本暂不升级,新项目使用3.x开发。
开发时,假如使用3.5.8,部署时应尽量保持一致,不要随意升级版本,更不要降低版本。
不要迷信版本,学会一个版本,好好学会一门语言,其他都不是问题。当然,也不要迷信语言。
在最合适的领域使用最合适的语言。
1.2.3 Python基础
1.2.3.1 Python解释器
解释器 | 说明 |
---|---|
CPython | 官方,C语言开发,最广泛的Python解释器 |
IPython | 一个交互式、功能增强的CPython |
PyPy | Python语言写的Python解释器,JIT技术,动态编译Python代码 |
Jython | Python的源代码编译成Java的字节码,跑在JVM上 |
IronPython | 与Jython类似,运行在.Net平台上的解释器,Python代码被编译成.Net的字节码 |
stackless | Python的增强版本解释器,不使用CPython的C的栈,采用微线程概念编程,并发编程 |
Python它是解释执行,Python的源代码写好之后首先需要经过解释器的编译,注意这个编译是编译成中间代码称为叫字节码,字节码最终是要在解释器上去执行的,解释器有哪些呢,从官方下载的那个Python安装包它实际上叫CPython,它是用C语言写的Python,你打开它的源码看一下全部都是C语言,它可以运行中间字节码,它可以帮助你将源代码变成中间字节码,这是它做的工作,它本质上是用C语言写的,它是目前我们在企业中部署最多的,你开发和部署用的最多的就是它了,除非你有特殊需求否则都用它,但是这个Python它让你在做实验的时候它的交互式不强,它的交互式很差,它的命令行方式不是很好用,当然我们说有IDE工具我们可以用PyCharm ,在命令行方式下有一个对它的增强,这个增强就是IPython,IPython就是对CPython做了一个增强,IPython主要提供了一些交互式,还做了一些功能上的增强,它实际上包装的是CPython,依赖于CPython的,所以大家在使用的时候也可以使用IPython作为我们的学习时候用的东西,但是IPython它毕竟是命令行不方便,也不能保存我们写的代码,怎么办呢,它这有个子项目就是我们装的Jupyter,jupyter notebook它就能为我们运行一个后台的网站,并且在这个网站里面提供一个网页,让我们在网页里面去写代码,然后可以帮助我们将网页中写的这些东西给我们保存下来,这就是jupyter notebook的好处,保存下来可以反复的去运行,反复测试,它是个交互式的界面,这个用的人也比较多,主要是用在测试的时候,工程的时候就不用它了,工程的时候用PyCharm ;
在Python领域还有一个比较知名的一个解释器叫PyPy,什么叫PyPy呢,它是一个贪吃蛇,这个贪吃蛇有个特点自己的嘴咬自己的尾巴,它是个环行的,它的意思是用Python写的Python解释器,所以它把它叫PyPy,它的性能好不好,据说它自己是它的性能比CPython要高好几倍的,为什么呢,因为它用的Just In Time叫JIT技术,什么叫Just In Time呢,它就叫运行时动态的调整,运行时调整,那这个运行时它能干什么呢,它是在代码运行的过程中它发现了比如说要做类型的优化,做内存的优化等等,它有这些技术,它可以发现你的类型然后做内存的优化,所以它这种技术就在动态的去改变它的性能,所以说这种技术提供以后它的性能比CPython要好一点,CPython是编译成中间代码就不动了类型什么都不做优化了,这种在某些场景下它可能性能并不突出,但是PyPy这种解释器你能不能把有些库放到它上面去,它有个兼容性的要求,所以这个你要根据PyPy官网来定,有一小部分特别注重性能的它们经过测试发现可以在PyPy解释器上去运行,而且测试发现性能真的提升了,所以有很多人会在PyPy上来去运行它,去把自己的代码部署到PyPy上,但是它也有一些问题没有解决;
还有两个了解就可以了,一个叫Jython,一个叫IronPython,这两个干什么用呢,Jython是Python的源代码被转换成、被编译成java的字节码,你既然是java字节码就符合了java的字节码规范,这个东西它是怎么做到的,其实大家知道java是一门开源语言,java的字节码规范它实际上是公开的,那也就是说只要有人能够把编译过程把Python的源代码给它编译成指定的java的字节码规范,实际上就可以在JVM上跑了;IronPython与Jython很像,就是你把Python源代码给它编译成.Net平台的字节码,然后在.Net平台上去运行;
stackless叫做无栈,这个是在CPython的基础上做的增强的解释器,其实意思是做了改版,它不使用CPython当中的C语言的栈,这个学到函数的调用过程会讲,它采用微线程的概念编程,并发的编程,解决高并发的问题,微线程是什么东西呢,它有另一个名字叫协程,它是用这种协程的概念来解决并发的问题,它能解决什么在讲到协程的时候再说。,当然CPython原生的在协程这块支持的非常多,从3.5开始每一个版本包括到3.8做了大浮动的改动就是为了更好的支持协程,从语法角度原生支持,你如果愿意用这种协程概念你可以考虑用stackless,但是现在这个用的人少,大多数人都是用CPython,然后在里边用CPython到3.5之后发展出来的协程概念,在CPython上进行协程的编程,到底用哪个要看你自己的选择。
1.2.3.2 基础语法
1.2.3.2.1 注释
# 井号标注的文本
井号也叫哈希符号,也叫Sharp符号,Sharp尖锐的意思,井号在英文叫Sharp也叫hash,以后你见到类似的单词你应该知道它在说什么,中国人叫井号。
1.2.3.2.2 数字
-
整数int
-
Python3开始不再区分long、int,long被重命名为int,所以只有int类型了
-
进制表示:
- 十进制10
- 十六进制0x10
- 八进制0o10
- 二进制0b10
-
bool(布尔)类型,有2个值True、False
-
-
浮点数float
-
1.2、3.1415、-0.12,1.46e9等价于科学计数法1.46*109
-
本质上使用了C语言的double类型
-
-
复数complex
- 1+2j或1+2J
数字是数值型,数值型里边在Python当中是分3种的,一种叫整型,就是整数,整数分正整数、负整数和0,还有进制,在Python 3的时候它不像Python 2,原来在Python 2当中是有一个长整型和普通整型,在Python 3当中它把这个东西合并了,也就是说现在只有一个int,这个int实际上都是长整型,能有多长呢,以前我们认为长整型8个字节,在Python中不设上限,Python为了让你用的方便,其实在很多编程语言当中它有个题目,就是超大整型该怎么存放的问题,就是超过8个字节表示不了了那这个整型该怎么办呢,这是一个面试题,这种面试题在Python中就不存在了,为什么呢,因为Python 3中的这个long型你说表示多大咱就表示多大,能表示多大内存放不下为止,它可以这么大,所以Python的long整型一般对大家来讲的话你根本不知道边界在哪,这是它的好处,这样在学习的时候很多人就不需要为4整型、4个字节、2个字节、8个字节,最大数是多少,最小数是多少,你不用背了,随你用,不出问题;
进制我们一般习惯说十进制,也许是因为我们数数的时候是拿手指头来数的,你就算加上脚指头你数的时候也是按10进位的,所以很天然我们就有十进制,当然我们用的是阿拉伯数字,这个阿拉伯数字确切讲叫印度数字,它是阿拉伯人传到西方的,这里边最伟大的发明除了1-9之外,还有一个发明就是0,有了0这个占位符,十进制是我们生活中用到最多的东西,然后十六进制怎么表达呢,十六进制在表达10的时候怎么弄,我们说进制它是逢几进一,你比如说十进制是逢十进一,它是看不到10的,十六进制是逢十六进一,它是看不到16的,但是我们现在创造出来的阿拉伯数字只有0-9 10个,那这第10个数字对于十六进制来讲这第10个数字怎么办呢,它是用a、b、c、d、e、f来代替的,9之后没有数字怎么办呢,那就用10,那这个10怎么表达,用A来代替,那也就是说0-9之后对于十六进制它是看不见16,所以它第一个是a代表10,第二个是b代表11,第三个是c代表12,第四个是d代表13,第五个是e代表14,第六个是f代表15,到15就没了,因为逢十六进一,十六进制看不到16,十进制看不到16,二进制看不到2,八进制看不到8,八进制就从0、1、2、3、4、5、6、7,总共8个数字,0-7逢八进一也就没有8,所以几进制就是逢几进一,对于十六进制来讲0x10就是16,对于八进制来讲0o10就是8,二进制0b10就是2;
在整型里还有个子类型叫bool类型,bool型只有2个值,这两个值都是常量,就是True、False,就是真和假,这两个都是整型值;
浮点数类型什么意思,比如你写1.2、3.1415,这些数据有小数点就称为浮点数,有正浮点数和负浮点数,还可以用科学计数法,总之有小数点都是小数,对于小数都称为浮点数,它本质上用的是C语言当中的double类型,就是双精度类型,在这里称为叫float,就这一种类型;
还有一种叫complex叫复数,复数在有理数阶段不太用它,到无理数就用得上了。
# In:
10, 0xa, 0b1010, 0o12 # number, int integer
# Out:
(10, 10, 10, 10)
# In:
True, False #bool
# Out:
(True, False)
1.2.3.2.3 字符串
-
使用 ’ " 单双引号引用的字符的序列
-
‘’'和"“” 单双三引号,可以跨行、可以在其中自由的使用单双引号
-
r前缀:在字符串前面加上r或者R前缀,表示该字符串不做特殊的处理
-
f前缀:3.6版本开始,新增f前缀,格式化字符串
1.2.3.2.4 转义序列
- \\ \t \r \n \’ \"
- 上面每一个转义字符只代表一个字符,例如\t 显示时占了4个字符位置,但是它是一个字符
- 前缀r,把里面的所有字符当普通字符对待,则转义字符就不转义了。
转义:让字符不再是它当前的意义,例如\t,t就不是当前意义字符t了,而是被\转成了tab键
#字符串在Python当中有几种,最早它是有单引号引起来,比如像‘a’,"a",这个就叫字符串,它们分别用单引号和双引号,注意这时候的单引号和双引号叫界定符,界定'a'这个字符串的边界,就这个界定符之内的就是一个字符串,但是这个时候就跟转义字符在一起了,这个时候回出现一些特殊情况
a = 'a' #比如定义一个a = 'a'没有问题,称为这叫做标识符变量
a = 'abc' #a= 'abc'也可以,那我们以后能不能用这个值呢,你可以直接使用,但是我们说'abc'这个值交给了a这个变量,我们以后直接打这个变量就可以了
# In:
a
# Out:
'abc'
#我们把这个变量一打印它的值就出来了,它的值就存的'abc',什么意思呢,就是让a这个标识符与'abc'这个值之间建立了一种关联关系,你现在问a就相当于问它的值是多少
# In:
b = 1 #标识符b = 1 , 1 #你写1那就是1了
# In:
b #如果你写b,b它本身它是个变量,它是个指代,b这个标识符指代1这个数据,所以你敲b它告诉你,你问它是几,它告诉你我其实指向的是1,我是它的名字,就跟你是有值的,但是我要给你个代号,给你个学号,这个变量想当一个学号差不多,它只是对一个值的指代
#Out:
1
# In:
b = "abcd" #用双引号定义
# In:
a
# Out:
'abc' #这时候a的值是'abc'
# In:
b
# Out:
'abcd' #b的值是'abcd'
# In:
'abcde'
# Out:
'abcde' #不要变量也可以,直接打印'abcde'
#'abcde'就是字符串,但是你现在使用单引号作为界定符
'abc'de' #那么我在这个abcde直接要非得是用一个单引号它就出错了,它认为它的第一个单引号跟第二个单引号是对应的,后面的单引号它不知道跟谁对应了,它认为这是有错误的,它认为这个界定符到c后面就完了,这个怎么办,你说我c和d之间就有单引号,几种解决办法,
# In:
"abc'de" #第一种办法就是使用双引号作为界定符,双引号作为界定符,中间的单引号就没有歧义了,它就指的是一个字符
# Out:
"abc'de"
# In:
'abc\'de' #第二种方法就是在中间的单引号之前是用转义字符‘\’ 反斜杠,反斜杠称为转义字符,什么叫转义字符,转义字符就是把它的意思给转变了,使它不能成为当前的默认的意义,引号在这作为界定符,你在引号前面加一个反斜杠它就不能作为界定符了,这个引号就被转义了,转义成它原来的意思,它就是个引号了,它没有界定符的意思,它从一个界定符就被转回成另一种意思,转成它原来的意思,它原来的本意应该是单引号
# Out:
"abc'de"
# In:
'''abc'de''' #还有一种办法就是,界定符用3个单引号
# Out:
"abc'de"
# In:
'''abcde'''' #不能把单引号写到后面
File "<ipython-input-18-3b4243a05c67>", line 1
'''abcde''''
^
SyntaxError: EOL while scanning string literal
#会报错,它认为前3个单引号是界定符,最后一个单引号它跟谁挨着,它不知道是谁了
# In:
"""abcdef'""" #非要最后加个单引号,可以用3个双引号
# Out:
"abcdef'"
# In:
"""abcdef'
fg"""
# Out:
"abcdef'\nfg" #3引号能够换行,这里又多个换行符
abcd
efg
#换行符是什么意思呢,换行符在计算机系统里面比如说输入上面那样,你以为你在d后面写了个什么东西,你在这里写了一个字符,这个字符被编辑器发现之后这个编辑器就按照字符的约定将它给你折一行,换到下一行显示efg,其实从文件系统来讲的话,我们的文件它是一个字节挨着一个字节,它根本就没有换行只说,它全是二进制,它没有换行只说,这个换行符纯粹是当前编辑器为了好看给你做的,这个地方相当于abcd\nefg,这个n还是字符n吗,不是字符n了,这个n前面有个反斜杠它就失去了它当前的意义,它转换为另一个意义,\n就代表叫newline,就是新行的意思
"abcdef'\nfg" #在这里显示为什么会显示\n,因为ipython它在打印的时候它不会给你打印是换一行的打印,所以就出现了这种问题,这个问题该怎么解决呢
# In:
c = """abcdef'
fg"""
# In:
c #这个c是ipython帮你打印的
# Out:
"abcdef'\nfg"
# In:
print(c) #这个调的是python中的print函数完成的
# 打印结果
abcdef'
fg
#print函数在打印的时候考虑到了格式输出的问题,它遇到换行符就给你换了一行,这就是它们之间的差别
#三引号里边可以写单引号、双引号,还可以换行
# In:
"a"b"
File "<ipython-input-24-eb4605c4f676>", line 1
"a"b"
^
SyntaxError: EOL while scanning string literal
#这样写也会出错
# In:
'a"b'
# Out:
'a"b'
#这样写可以
# In:
"a\"b"
# Out:
'a"b'
#用转义字符也可以
# In:
dir = 'c:/windwos/nt' #这样写没有问题,因为windwos支持两种路径表达,‘\’ 反斜杠和‘/’ 斜杠
# In:
dir
# Out:
'c:/windwos/nt'
# In:
d = 'c:\windows\nt' # \n 表示newline换行
# In:
d
# Out:
'c:\\windows\nt' # \\ \的本意是转义符,但是在它前面再加一个转义符把它自己也转了,把反斜杠转成它本来的意思,它就是指我就是反斜杠了,没有转义的功能了, \\ 这里的意思就是将转义字符转成它本来的意思反斜杠,那也就是说它只是做一个路径分隔符了
# \n并没有转义,那就说明n被前面的反斜杠拿来转义,转义成\n,\n就是新行的意思
# In:
print(d)
# 打印结果:
c:\windows
t
#用print函数就可以看出来换行了
# In:
print(dir)
# 打印结果:
c:/windwos/nt
# In:
e = 'c:\\windows\\nt'
# In:
e
# Out:
'c:\\windows\\nt'
#用转义符
# In:
print(e)
# 打印结果:
c:\windows\nt
# In:
f = r'c:\windows\nt' # r前缀将字符串不要转义了
# In:
f
# Out:
'c:\\windows\\nt'
# In:
print(f)
# 打印结果:
c:\windows\nt
在python中,“\t”是指制表符,代表着四个空格,也就是一个tab。
制表符也属于“写法是两个字符的组合,但含义上只是一个字符”的情形。它的写法是“\t”,是反斜杠和t字母的组合,t取的是table之意。它的作用是对齐表格数据的各列,在不使用表格的情况下可以上下对齐。
# In:
print("a\tb")
# 打印结果
a b
# In:
print("a\tb\nc\td e") # \t table,\n newline,空格 space,这些都是不可见字符,也叫空白字符,它们都代表一个字符,用来占位用的
# 打印结果
a b
c d e
# In:
print(R"a\tb\nc\td e") #前面加R或r,转义字符就不转义了
# 打印结果
a\tb\nc\td e
# In:
a = 'abc'
b = 123
# In:
c = f'{a}******{b}' #f前缀,它是用来构造字符串的
# In:
c
# Out:
'abc******123'
# In:
d = f"{b} - {b} === {a}" #f前缀字符串,在其它语言里叫插值字符串
# In:
d
# Out:
'123 - 123 === abc'
1.2.3.2.5 缩进
- 未使用C等语言的花括号,而是采用缩进的方式表示层次关系
- 约定使用4个空格缩进
1.2.3.2.6 续行
- 在行尾使用 \,注意\之后除了紧跟着换行之外不能有其他字符
- 如果使用各种括号,认为括号内是一个整体,其内部跨行不用 \
# In:
a = 'abcdef'
'gh'
# Out:
'gh'
# In:
a
# Out:
'abcdef'
#你输入'abcdef',没有输完,在下一行继续输入,但是下一行输入的'gh'跟'abcdef'没有关系,‘gh’就自动输出了
# In:
a = 'abcdef'\
'gh'
# In:
a
# Out:
'abcdefgh'
#在'abcdef'后面加上反斜杠,在反斜杠后面什么都不要写,写了就是语法错误,这里的反斜杠是续行符
1.2.3.2.7 标识符
标识符
- 一个名字,用来指代一个值
- 只能是字母、下划线和数字
- 只能以字母或下划线开头
- 不能是python的关键字,例如def、class就不能作为标识符
- Python是大小写敏感的
标识符约定:
- 不允许使用中文,也不建议使用拼音
- 不要使用歧义单词,例如class_
- 在python中不要随便使用下划线开头的标识符
什么是标识符呢,就是像a = 'abc’这样,这个a是我们定义的一个变量,它不是字符串,它在等号的左边,它用来接收右边的这个值,将右边的这个值变成它来管理,也就是说这个a与后边的值产生了一个关系,它指代右边的这个值,那你说a它其实就是指向它所指向的值,它就相当于一个代理,它是个指代关系,就相当于给abc这个值起了一个代号,我们把这个代号称为叫标识一个值的代号,我们把这个名字称为叫标识符;
标识符是给谁用的,标识符是留给程序员用的,因为程序员在很多情况下会反复用这个值,你比如说我用了多次a,要反复用这个值,那反复用这个值怎么办,给它个名字,给它个代号,我以后就用这个代号,这个代号就是标识符,这是留给程序员用的,所以程序员对标识符很有感情;
标识符该怎么定义,一般情况下你可以写a、b、c、…,一般情况下你可以这么写,为什么呢,你只是做一个临时测试、临时变量你写这种无意义的就行了,但是我们真正在写业务代码的时候,大家不能这么写,标识符不能写这种毫无意义的东西,我们应该写它所指向这个值它代表业务上的什么意思,你比如说它是长度,那你应该叫lens,如果它是重量你可以叫weight,如果是年龄你可以叫age,你就应该起这样一些名字,所以我们说标识符对大家来讲的话我们在真正做项目的时候应该起名字,这个标识符有什么要求呢,它是一个指代,在python当中它要求是字母、下划线和数字,只能是这三种的组合,我相信大家在注册会员的时候都用过类似的东西,也就是说它对你有基本要求,但是绝对不能以数字开头,只能以字母或者下划线开头,还有它不能用python的关键字,关键字是什么意思,关键字是语言留的,因为语言也得用个def、class等来表示类、表示函数,所以这样的名字是不许你用的,只能语言留着用,所以你是绝对不可以跟它冲突的,def、class这种名字是语言留着的,我们把这种语言留的名字称为叫关键字,你绝对是定义不出来的;
# In:
def = 20
File "<ipython-input-2-1daef5e18ba4>", line 1
def = 20
^
SyntaxError: invalid syntax
#这样定义就直接报错了,它告诉你非法的语法,因为def是关键字不允许你用
# In:
def1 =20 #这样的可以用,但是这种标识符不好,一般不建议大家直接使用数字,大多数情况下请大家使用英文,不要使用拼音
也不要使用中文,虽然中文可以,因为它是Unicode字符它可以,但不要使用,也不建议使用拼音,除非有标准要求,比如说你要做国家项目,它这里有国标要求,它的国标要求它确实是用的拼音,那这个是可以的,但是在我们的日常编程当中请大家尽量使用英文单词,哪怕是使用中文化的英文单词你来组合在一起,你都不要使用拼音,这是一个基本要求;
不能以数字开头,也不能用关键字,而且它是大小写敏感
# In:
Abc = 10
# In:
ABc = 20
#这两个变量是完全不同的,它们区分大小写
# In:
Abc
# Out:
10
# In:
ABc
# Out:
20
不要使用歧义单词,比如在class_、def1、def_,因为有些人看不见这个下划线
常量
- 一旦赋值就不能改变值的标识符
- python中无法定义常量
字面常量
- 一个单独的不可变量,例如 12、“abc” 、‘2341356514.03e-9’
标识符本质
每一个标识符对应一个具有数据结构的值,但是这个值不方便直接访问,程序员就可以通过其对应的标识符来访问数据,标识符就是一个指代。一句话,标识符是给程序员编程使用的。
# In:
a
# Out:
'abcdefgh'
#原来a的值是'abcdefgh'
a = 100 # a可以表示任意的值,它还可以变化,原来指向'abcdefgh',后来又指向100,我们把这种可以变化值的标识符,称为变量
c = 200 # 在python中比如说这个标识符是c,c一旦给了200之后就不能变的,它就只能指向200,永远在不能变了,python中没有,如果一个标识符一旦定义了指向关系的话,比如它指向200,就不能在变了,它就不能指向abc,也不能指向300,也不能指向201,就是只能值200,你要找c它就只能指200,它再也不能改变了,那我们把这种标识符称为叫常量,就是这个标识符一旦指向200之后它不能再改变,python中没有常量定义,python中的所有标识符都可以改变它的值,就是它所对应的值都可以改变,python是没有常量的,是没有常量定义语法的,这就带来了一个python的重大问题,就是它的所有值都能被你改,什么都能被你改,几乎没有不能改的,这也带来也一个巨大问题,就是懂的人可以改,不懂的人也要改,不懂的人改就带来了一个很大问题,不懂的人改就该出问题来了吗,python你看着简单,但是python其实开发大型项目不好弄,为什么,因为这里面有一些人员它的训练不够,它素质不够,所以它写出的代码就会有各种各样的问题,包括变量的问题,因为你控制不住它,它就是想给你改,它无意中改了也是bug,所以python是没有常量当以的,它只有变量定义
#python中什么是常量,python中有没有常量呢,其实它没有常量,它有一种东西叫字面量常量,什么叫字面量常量呢,比如写个1,比如写个123,比如写个字符串'abc',这些东西叫字面常量,也叫字面量常量
# In:
a = 1
# In:
a = a + 1
#比如先让a等于1,然后a = a + 1,等式先算右边,那就相当于1 + 1等于2,那就是a = 2,1 + 1等于2是1变成2了吗,1是不可能变成2的,因为1叫字面常量,什么叫字面常量,一旦创建将永远不可更改,你实际上是拿2个1相加产生出来的2,2是一个字面常量,1也是字面常量,谁变了,是a的指向变了a以前是指向1的,然后你又找了个1跟1相加,加完之后产生了一个全新的字面常量2,然后a不指向1了,a指向2,也就是说a指向的值发生了变化,所以a这种标识符我们称为叫变量
标识符的本质,每一个标识符对应一个具有数据结构的值,什么意思,就想刚才说的a指向了1,b指向了一个字符串’abc’,就a和b这样的标识符是留给程序员用的,程序员拿到这个标识符能干吗,能找到它所对应的值,我们就是为了这个目的,程序员就得用标识符,所以说我们直接引用这个值不方便,我们甚至还要反复引用,所以我们就用这种标识符来访问它,它就是个指代关系。
1.2.3.2.8 语言类型
Python是动态语言、强类型语言。
静态语言
- 事先声明变量类型,之后变量的值可以改变,但值的类型不能再改变
- 编译时检查
int a = 100; # 定义变量的时候赋值了,要求变量必须是整数类型,静态语言需要在变量前面去申明一个类型,它要求变量必须是你申明的类型
a = 200 # right
a = 'abc' # wrong
# 静态语言有了类型,就有了约束,在编译的时候就可以做类型的检查,提前发现问题
动态语言
- 不用事先声明类型,随时可以赋值为其他类型
- 编程时不知道是什么类型,很难推断
a = 100 # 动态语言不需要指定类型,爱给什么给什么,只要是一个合法值都可以交给这个标识符a
a = 'abc' # a指向新的值,这个新的值可以是新的类型
# 动态语言对数据的类型没有任何的约束
# 做企业级开发的人发现这种问题存在的话,那可是非常大的问题了,因为我们做企业级开发如果说你现在都是这样的解决问题的方案的话,它会带来一个非常大的影响,什么影响呢,没有人替你检查你现在的这种东西对不对,什么意思呢,也就是说你本来你的心里想的是a应该永远是个整形,但是用的人因为你写好代码别人是不是要用啊,别人在用的时候根本就不知道你什么类型,瞎猜,他说我才可能是个字符串吧,它就给你送了个字符串进来,python是先编译成中间代码,然后在运行的时候运行到这一句发现类型错误了,报错了,这是它的问题,动态语言是在运行时,什么是运行时,就是我们把先编译成中间字节码,然后把字节码放到解释器当中去执行,这就叫运行时,在运行的时候才能发现类型不对了,为什么,你没告诉我类型对不对,你没指定类型,你爱给什么类型给什么类型,你随便换,反正都是变量,没有常量,你想换什么换什么,才发现类型不对了,太晚了,你上线了才发现bug,哭都来不急
强类型语言
- 不同类型之间操作,必须先强制类型转换为同一类型。print(‘a’+1)
弱类型语言
- 不同类型间可以操作,自动隐式转换,JavaScript中console.log(1+‘a’)
# In:
type(1) # 返回的是类型
# Out:
int
# In:
type('abc')
# Out:
str
# In:
1 + 2
# Out:
3
# In:
type(1 + 2)
# Out:
int
# In:
type(1 + 2.1) # int + float -> float int数值加上float得到float,类型发生了变化,但是这种类型发生的变化你有强制做吗,没有,这是悄悄的做了,我们把悄悄的做这种类型转化称为隐式的类型转化
# Out:
float
#对于我们现在所遇到的高级语言,比如C语言、java、python它都是高级语言,这种高级语言里边它都有隐式类型转化,你不需要强制,这种类型数值之间的转化是不需要强制
# In:
type(1 + 2.1 + True)
# Out:
float
#布尔型、整型和float型它们相加最后都转化成float型,这就叫隐式类型转化
# In:
1 + 'a'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-32-abf63472aed8> in <module>
----> 1 1 + 'a'
TypeError: unsupported operand type(s) for +: 'int' and 'str'
#它说我不支持这种操作,我不支持整型+字符串。这就叫不同类型之间不能相加,这两种类型之间不可调和,所以它不能做隐式类型转化,那该怎么做呢
# In:
str(1) + 'a' # 把1转化成字符串,str(1),str在这里是类型,这个类型可以加个括号当函数用,当函数用把1扔进去之后它会把1强制转化成从数值转化成字符串,然后做字符串相加,字符串的加法其实就是拼接,我们把强制类型转化的过程叫强制类型转化
# Out:
'1a'
# python对这两种类型它并不能直接拼接在一起,我们把这种语言做这个测试我们称为叫强类型语言,强类型语言其实指的是必须对这种测试做强制类型转化
# In:
%%js
console.log(1 + 'abc')
#在浏览器按f12,控制台里显示结果a1,如下图所示
在js当中它会直接把1 + 'abc’直接做隐式类型转化,我们把这种语言称作叫弱类型语言
但是要注意的是,强与弱只是一个相对概念,即使是强类型语言也支持隐式类型转换。