《Python》的魅力之基础知识
前言:
- Big-man非常感谢C语言带来的春风一片,但是在用C语言去解决项目中实际开发的问题时,有显得是多么地力不从心的,所以这里介绍了一款更有力的开发语言——Python。
Python的优势:
- 这是为了让大家成为像Big-man这样的对于Python有兴趣,从实践的角度分析这门语言的好处。
- C语言是可以用来编写操作系统的贴近硬件的语言,所以,C语言适合开发那些追求运行速度、充分发挥硬件性能的程序。而Python是用来编写应用程序的高级编程语言。
- 当Big-man想着用一种语言开始做真正的软件开发时,Big-man除了需要去编写代码外,还需要很多基本的已经写好的现成的东西,来帮助Big-man加快开发进度。
- 比如说,要编写一个电子邮件客户端,如果先从最底层开始编写网络协议相关的代码,也比如说在Big-man大学的工程设计上,有一位伟大的同学说自己想要去写一个内核(Kernel),类似于这样的那估计一年半载也开发不出来。Big-man的企业老总怎么可能给自己一年半的时间去实现这样的开发,所有的企业家都不会这样去构建自己的项目吧。
- 然而高级编程语言通常都会提供一个比较完善的基础代码库,让你能直接调用,比如,针对电子邮件协议的SMTP库,针对桌面环境的GUI库,在这些已有的代码库的基础上开发,一个电子邮件客户端几天就能开发出来。如果不相信Big-man这样的话语,大家尽管去进行尝试和实现。
- Python就为我们提供了非常完善的基础代码库,覆盖了网络、文件、GUI、数据库、文本等大量内容,被形象地称作“内置电池(batteries included)”。Big-man在使用Python开发,许多功能不必从零编写,直接使用现成的即可。但是这里Big-man却是要给出建议的是在写算法的时候最好还是采用C语言去实现,因为Big-man他个人觉得算法的应用需要与硬件结合起来才合适的。
- 除了内置的库外,Python还有大量的第三方库,也就是别人开发的,供Big-man直接使用的东西。当然,如果Big-man他开发的代码通过很好的封装,也可以作为第三方库给别人使用。
- 许多大型网站就是用Python开发的:
适合Python开发的项目:
- 适合Python开发的项目:
- 首选是网络应用,包括网站、后台服务等等;
- 其次是许多日常需要的小工具,包括系统管理员需要的脚本任务等等;
- 另外就是把其他语言开发的程序再包装起来,方便使用。
Python的缺点:
- Big-man觉得需要辩证地去认知每一个新的事物,Python也是一样的,所以Python作为一门语言也有弊处。
- 运行速度慢:
- 和
C语言程序
相比非常慢,因为Python是解释型语言,Big-man他的代码在执行时会一行一行地翻译成CPU能理解的机器码,这个翻译过程非常耗时,所以很慢。而C程序是运行前直接编译成CPU能执行的机器码,所以非常快。
- 和
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("Hello world!\n");
return 0;
}
>>> print('Hello world!')
Hello world!
但是大量的应用程序不需要这么快的运行速度,因为用户根本感觉不出来。例如开发一个下载MP3的网络应用程序,C程序的运行时间需要0.001秒,而Python程序的运行时间需要0.1秒,慢了100倍,但由于网络更慢,需要等待1秒,你想,用户能感觉到1.001秒和1.1秒的区别吗?这就好比F1赛车和普通的出租车在北京三环路上行驶的道理一样,虽然F1赛车理论时速高达400公里,但由于三环路堵车的时速只有20公里,因此,作为乘客,你感觉的时速永远是20公里。
代码不能加密:
- 如果要发布你的Python程序,实际上就是发布源代码,这一点跟C语言不同,C语言不用发布源代码,只需要把编译后的机器码(也就是你在Windows上常见的xxx.exe文件)发布出去。要从机器码反推出C代码是不可能的,所以,凡是编译型的语言,都没有这个问题,而解释型的语言,则必须把源码发布出去。
- 这个缺点仅限于你要编写的软件需要卖给别人挣钱的时候。好消息是目前的互联网时代,靠卖软件授权的商业模式越来越少了,靠网站和移动应用卖服务的模式越来越多了,后一种模式不需要把源码给别人。
- 再说了,现在如火如荼的开源运动和互联网自由开放的精神是一致的,互联网上有无数非常优秀的像
Linux
一样的开源代码,Big-man从来不会高估他自己写的代码真的有非常大的“商业价值”。还有一部分应用的代码不愿意Open Source
的原因是代码写得太烂了,一旦开源,就没人敢用他们的产品了。
Python是一门计算机编程语言:
- Python是一门计算机编程语言。
- 计算机编程语言肯定是和Big-man日常使用的自然语言有所不同,最大的区别就是,自然语言在不同的语境下有不同的理解,而计算机要根据编程语言执行任务,就必须保证编程语言写出的程序决不能有歧义,所以,任何一种编程语言都有自己的一套语法,编译器或者解释器就是负责把符合语法的程序代码转换成CPU能够执行的机器码,然后执行。Python也不例外。
Python的代码缩进:
- Python的语法比较简单,采用缩进方式,写出来的代码就像下面的样子:
# print absolute value of an integer:
a = 100
if a >= 0:
print(a)
else:
print(-a)
#
注释 && 代码缩进 && 大小写:
# print absolute value of an integer:
if a >= 0:
- 以
#
开头的语句是注释,注释是给人看的,可以是任意内容,解释器会忽略掉注释。其他每一行都是一个语句,当语句以冒号:
结尾时,缩进的语句视为代码块。 - 缩进有利有弊:
- 缩进的好处:
- 好处是强迫Big-man写出格式化的代码,但没有规定缩进几个空格还是
Tab
。按照约定俗称的管理,应该始终坚持使用4个空格的缩进。 - 缩进的另一个好处是强迫Big-man写出缩进较少的代码,Big-man会倾向于把一段很长的代码拆分成若干函数,从而得到缩进较少的代码。
- 好处是强迫Big-man写出格式化的代码,但没有规定缩进几个空格还是
- 缩进的坏处:
- 缩进的坏处就在于”复制-粘贴”功能的失效了,这是坑洞最大的地方。也就是在Big-man优化自己代码的时候,也就是项目需要重构的时候,粘贴过去的代码必须重新检查缩进时候正确。此外, 在Python应用上的IDE虽然在一直的跟进中,但是由于本身语言的特性,所以Python的IDE很难像格式化
Java
代码那样格式化Python代码。
- 缩进的坏处就在于”复制-粘贴”功能的失效了,这是坑洞最大的地方。也就是在Big-man优化自己代码的时候,也就是项目需要重构的时候,粘贴过去的代码必须重新检查缩进时候正确。此外, 在Python应用上的IDE虽然在一直的跟进中,但是由于本身语言的特性,所以Python的IDE很难像格式化
- 最后,请务必注意,Python程序是大小写敏感的,如果写错了大小写,程序会报错。
- 缩进的好处:
- 注意:
- Python使用缩进来组织代码块,请务必遵守约定俗成的习惯,坚持使用4个空格的缩进。
- 在文本编辑器中,需要设置把Tab自动转换为4个空格,确保不混用Tab和空格。
数据类型和变量:
数据类型:
- 计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值。但是,计算机能处理的远不止数值,还可以处理文本、图形、音频、视频、网页等各种各样的数据,不同的数据,需要定义不同的数据类型。在Python中,能够直接处理的数据类型有以下几种:
整数:
- Python可以处理任意大小的整数,当然包括负整数,在程序中的表示方法和数学上的写法一模一样,例如:
1,100,-8080,0,
等等。 - 计算机由于使用二进制,所以,有时候用十六进制表示整数比较方便,十六进制用
0x
前缀和0-9
,a-f
表示,例如:0xff00,0xa5b4c3d2
等等。
- Python可以处理任意大小的整数,当然包括负整数,在程序中的表示方法和数学上的写法一模一样,例如:
浮点数:
- 浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,比如,1.23x
109
和12.3x
108
是完全相等的。浮点数可以用数学写法,如
1.23
,3.14
,-9.01
,等等。但是对于很大或很小的浮点数,就必须用科学计数法表示,把10用e替代,1.23* 109 就是1.23 * e9 ,或者12.3 * e8 ,0.000012可以写成1.2 * e−5 ,等等。 - 整数和浮点数在计算机内部存储的方式是不同的,整数运算永远是精确的(除法难道也是精确的?是的!),而浮点数运算则可能会有四舍五入的误差。
- 浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,比如,1.23x
109
和12.3x
108
是完全相等的。浮点数可以用数学写法,如
字符串:
- 字符串是以单引号
'
或双引号"
括起来的任意文本,比如'abc'
,"xyz"
等等。请注意,''
或""
本身只是一种表示方式,不是字符串的一部分,因此,字符串'abc'
只有a
,b
,c
这3个字符。 - 如果
'
本身也是一个字符,那就可以用""
括起来,比如"I'm OK"
包含的字符是I
,'
,m
,空格,O
,K
这6个字符。 - 如果字符串内部既包含
'
又包含"
怎么办?可以用转义字符\
来标识,比如:
- 字符串是以单引号
'I\'m \"OK\"!'
- 代表的字符串内容是:
I'm "OK"!
- 转义字符
\
可以转义很多字符,比如\n
表示换行,\t
表示制表符,字符\
本身也要转义,所以\\
表示的字符就是\
,可以在Python的交互式命令行用print()
打印字符串看看:
>>> print('I\'m ok.')
I'm ok.
>>> print('I\'m learning\nPython.')
I'm learning
Python.
>>> print('\\\n\\')
\
\
- 如果字符串里面有很多字符都需要转义,就需要加很多
\
,为了简化,Python还允许用r''
表示''
内部的字符串默认不转义,可以自己试试:
>>> print('\\\t\\')
\ \
>>> print(r'\\\t\\')
\\\t\\
- 如果字符串内部有很多换行,用
\n
写在一行里不好阅读,为了简化,Python允许用'''...'''
的格式表示多行内容,可以自己试试:
>>> print('''line1
... line2
... line3''')
line1
line2
line3
- 上面是在交互式命令行内输入,注意在输入多行内容时,提示符由
>>>
变为...
,提示你可以接着上一行输入。如果写成程序,就是:
print('''line1
line2
line3''')
- 多行字符串
'''...'''
还可以在前面加上r
使用,请自行测试。
注意:
string
类型是一种不可变的数据类型;
spam = 'I have a pet cat.'
spam[13] = 'r'
print(spam)
- 这样Python的运行环境会爆出一个错误:
TypeError: 'str' object does not support item assignment
。但是Big-man又想去达到他自己想要的效果也就是改变spam
位置为13
的值,所以需要如下的操作:
spam = 'I have a pet cat.'
spam = spam[:13] + 'r' + spam[14:]
print(spam)
Python
中还有一个方法是replace
,也是替换字符串中的字符:
spam = 'I have a pet cat.'
spam.replace(spam[13], 'r')
print(spam)
这个输出也是
I have a pet cat.
布尔值:
- 布尔值和布尔代数的表示完全一致,一个布尔值只有
True
、False
两种值,要么是True,要么是False,在Python中,可以直接用True、False表示布尔值(请注意大小写),也可以通过布尔运算计算出来:
- 布尔值和布尔代数的表示完全一致,一个布尔值只有
>>> True
True
>>> False
False
>>> 3 > 2
True
>>> 3 > 5
False
- 布尔值可以用
and
、or
和not
运算。 这三个运算在不同的语言中表现得不太一样的。这里仅仅是应用在Python语言中, 还请大家不要在其他语言中进行测试。 and
运算是与运算,只有所有都为True,and运算结果才是True:
>>> True and True
True
>>> True and False
False
>>> False and False
False
>>> 5 > 3 and 3 > 1
True
or
运算是或运算,只要其中有一个为True,or运算结果就是True:
>>> True or True
True
>>> True or False
True
>>> False or False
False
>>> 5 > 3 or 1 > 3
True
not
运算是非运算,它是一个单目运算符,把True变成False,False变成True:
>>> not True
False
>>> not False
True
>>> not 1 > 2
True
- 布尔值经常用在条件判断中,比如:
if age >= 18:
print('adult')
else:
print('teenager')
空值:
- 空值是Python里一个特殊的值,用
None
表示。None
不能理解为0,因为0是有意义的,而None
是一个特殊的空值。 - 此外,Python还提供了
列表
、字典
等多种数据类型,还允许创建自定义数据类型
,Big-man会在后面继续讲到以及代码的实现中会涉及到。
- 空值是Python里一个特殊的值,用
变量:
- 变量的概念基本上和初中代数的方程变量是一致的,只是在计算机程序中,变量不仅可以是
数字
,还可以是任意数据类型
。 - 变量在程序中就是用一个变量名表示了,变量名必须是
大小写英文
、数字
和_
的组合,且不能用数字开头
,比如:
- 变量的概念基本上和初中代数的方程变量是一致的,只是在计算机程序中,变量不仅可以是
a = 1
- 变量
a
是一个整数;
t_007 = 'T007'
- 变量
t_007
是一个字符串;
Answer = True
变量Answer是一个布尔值
True
在Python中,等号
=
是赋值语句,可以把任何数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量,例如:
a = 123 # a是整数
print(a)
a = 'ABC' # a变为字符串
print(a)
- 这种变量本身类型不固定的语言称之为动态语言,语言的强弱类型判别在强弱类型文章中,与之对应的是静态语言。静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错。例如
Java
是静态语言,赋值语句如下(//
表示注释):
int a = 123; // a是整数类型变量
a = "ABC"; // 错误 : 不能把字符串赋值给整型变量了
- 和静态语言相比, 动态语言更为灵活, 就是这个原因。
- 请不要把赋值语句的等号
=
等同于数学中的等号=。比如如下代码:
x = 10
x = x + 2
- 如果从数学上理解
x = x+2
那无论如何是不成立的,在程序中, 赋值语句先计算右侧的表达式x+2
, 得到结果12
, 再复制给变量x
, 由于x
之前的值是10
, 重新赋值后,x
的值变成12
。 - 最后,理解变量在计算机内存中的表示也非常重要。当我们写:
a = 'ABC'
- 这时,Big-man需要去查看一下解释器干了那两件事情:
- 1、在内存中创建了一个
ABC
的字符; - 2、在内存中创建了一个名为
a
的变量, 并把它指向ABC
。
- 1、在内存中创建了一个
- 也可以把一个变量
a
赋值给另一个变量b
, 这个操作实际上是把变量b
指向变量a
所指向的数据,例如下面的代码:
a = 'ABC'
b = a
a = 'XYZ'
print(b)
- 最后一行打印出变量
b
的内容到底是ABC
呢?还是XYZ
?如果从数学意义上理解, 就会错误地得出b
和a
相同, 也应该是XYZ
, 但实际上的值却是ABC
, 让Big-man一行一行进行解析代码, 就类似于编译器中的内容一样,下面就让Big-man来分析一下: - 执行
a = 'ABC'
, 解释器创建了字符串'ABC'
和变量a
, 并把a
指向'ABC'
:
- 执行
b = a
, 解释器创建了变量b
, 并把b
指向a
指向的字符串'ABC'
:
- 执行
a = 'XYZ'
, 解释器创建了字符串'XYZ'
, 并把a
的指向'XYZ'
, 但是这时的b
并没有更改:
- 所以, 最后打印变量
b
的结果自然是'ABC'
了。
a = {'h': 'ABC'}
b = a
a = {'h': 'XYZ'}
print(b)
# --------
a = {'h': 'ABC'}
b = a
a['h'] = 'XYZ'
print(b)
Big-man的同事测试了这样的代码,第一个打印出来是
{'h': 'ABC'}
, 但是第二个b打印却是{'h': 'XYZ'}
, 其实上面Big-man引用的图就可以看出来的,只不过这里的a
有字符串"ABC"
变为了一个字典{'h': 'ABC'}
,常量:
- 所谓常量就是不能变的变量, 比如常用的数字常数
π
就是一个常量。在
Python
中, 通常用全部大写的变量名表示常量:
- 所谓常量就是不能变的变量, 比如常用的数字常数
π
就是一个常量。在
PI = 3.14159265359
- 但事实上
PI
仍然是一个变量,Python
根本没有任何机制保证PI
不会被改变,所以,用全部大写的变量名表示常量只有一个习惯上的用法,如果你一定要改变变量PI
的值, 也没人能拦住你。 - 最后解释一下整数的除法为什么也是精确的。在Python中, 有两种除法, 一种除法
/
:
>>> 10 / 3
3.3333333333333335
/
除法计算结果是浮点数, 即使是两个整数恰好整除,结果也是浮点数:
>>> 9 / 3
3.0
- 还有一种除法
//
, 称为地板除,两个整数的除法仍然是整数:
>>> 10 // 3
3
- 大家没有看错,整数的地板除
//
永远是整数,即使除不尽 。要做精确的除法,使用/
就可以。 - 因为
//
除法只取结果的整数部分,所以Python语言肯定还提供一个余数运算, 可以得到两个整数相除的余数:
>>> 10 % 3
1
- 无论是整数做
//
除法还是取余数, 结果永远都是整数,所以,整数运算结果永远是精确的。
input
name = input("What is your name? ")
print "Hello," + name + "!"
Error:
What is your name? JackDan9
Traceback (most recent call last):
File "C:/python/test.py", line2, in ?
name = input("what is your name?")
File "<string>", line0, in ?
NameError: name 'JackDan9' is not defined
- 原因:
- input 会假设用户输入的是合法的Python表达式(或多或少有些与repr函数相反的意思).如果是字符串作为输入的名字,程序运行没有问题:
What is your name? "JackDan9"
Hello, JackDan9
如果是这样使你的用户输入的话,那你就可以放弃你的客人(Coding People)了,所以:
raw_input
- 它会把所有的输入当作原始数据(raw_data),然后将其放入字符串中
- input
>>> input("Enter a number: ")
Enter a number: 3
3
- raw_input
>>> raw_input("Enter a number:")
Enter a number: 3
'3'
Python的字符串和编码:
- 字符编码:
- 字符串也是一种数据类型, 但是,字符串比较特殊的是一个编码的问题。
- 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字(二进制数字)才能处理。最早的计算机在设计的时候采用的是8个比特
8bit
作为一个字节(byte
), 所以, 一个字节能表示的最大的整数就是255(二进制11111111 = 十进制的255), 如果要表示更大的整数, 就必须用更多的字节。比如两个字节可以表示的是最大整数是65535
, 4个字节可以表示的最大整数是4294967295
。 - 由于计算机是美国人发明的,因此,最早只有127个字符被编码到计算机里,也就是大小写英文字母、数字和一些符号, 这个编码表被称为
ASCII
编码, 比如大写字母A
的编码是65
, 小写字母z
的编码是122
。 - 但是要处理中显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突, 所以, 中国制定了
GB2312
编码, 用来把中文编进去。 - Big-man可以想得到的是, 全世界有上百种语言, 日本把日文编到
Shift_JIS
, 韩国把韩文编到Euc-kr
里, 各国有各国的标准, 就会不可避免地出现冲突, 结果就是, 在多语言混合的文本中, 显示出来会有乱码。 - 因此,
Unicode
应运而生。Unicode
把所有语言都统一到一套编码里, 这样就不会再有乱码问题了。 Unicode
标准也在不断发展, 但常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符, 就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode
。
ASCII
和Unicode
编码的区别:
ASCII
编码是1个字节(byte
), 而Unicode
编码是2个字节(byte
)。
- 字幕
A
用ASCII
编码是十进制的65
, 二进制的表示是01000001
; - 字符
0
用ASCII
编码是十进制的48
, 二进制的00110000
, 注意一点是字符'0'
和整数0
是不同的; - 汉子
中
已经超出了ASCII编码的范围, 用Unicode编码是十进制的20013
, 二进制是01001110 00101101
。
- 字幕
- 这样Big-man的固执就上来了, Big-man发现如果ASCII的编码
A
, 使用Unicode来进行编码的话只需要在前面补个零即可, 因此,A
的Unicode编码是00000000 01000001
。 - 大家有没有像Big-man这样想过, 为什么计算机中不统一用Unicode编码,这样的话,乱码的问题也会随着解开?
- 这个问题Big-man他自己想了几天,所以一直没敢更新,有一天在梦里,Big-man得到了答案。
- 如果都是采用Unicode编码的话, 对于全英文的软件是不是不太公平了,因为全英文的软件所有的字符都在ASCII编码的范围里面,而ASCII编码比Unicode编码少一倍的存储空间, 在存储和传输上就十分不划算。
- 所以本着中华名族勤俭节约的优良传统, 所以又出现了把
Unicode
编码转化为“可变长编码”的UTF-8
编码。 UTF-8
编码:
UTF-8
编码把一个Unicode字符根据不同的数字大小编码成1-6个字节, 常用的英文字母被编码成一个字节, 汉字通常是3个字节, 只有很生僻的字符才会被编码成4-6个字节。如果大家想去开发英文的软件,那么用UTF-8
编码也就不会浪费空间了:
字符 | ASCII | Unicode | UTF-8 |
---|---|---|---|
A | 01000001 | 00000000 01000001 | 01000001 |
中 | X | 01001110 00101101 | 11100100 10111000 10101101 |
- 从以上的表格还可以发现, UTF-8
编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8
的一部分, 所以, 大量只支持ASCII
编码的历史遗留软件可以在UTF-8
编码下继续工作。
计算机系统通用的字符编码工作方式:
- 在计算机内存中, 统一使用
Unicode
编码, 当需要保存到硬盘或者需要传输的时候, 就转换为UTF-8
编码。 - 用记事本编辑的时候, 从文件读取的
UTF-8
字符转换为Unicode
字符到内存里, 编辑完成后, 保存的时候再把Unicode
转换为UTF-8
保存:
- 浏览页面的时候, 服务器会把动态生成的
Unicode
内容转换为UTF-8
再传输到浏览器:
- 所以Big-man雪地里书写html页面的时候, 总是需要在前面加上一句
<meta charset="utf-8" />
Python的字符串:
- 搞清楚了令人头疼的字符编码问题后,接下来研究Python的字符串。
- 在最新的
Python 3
版本中, 字符串是以Unicode
编码的, 也就是说,Python
的字符串支持多语言, 例如:
>>> print('包含中文的str')
包含中文的str
《Python基础教程》