Python 基础

以下文件均以hello.py命名

1、运行Python hello.py时,Python 文件必须要以.py结尾,文件名只能是英文字母、数字和下划线的组合。

2、直接运行.py文件,在Windows上是不行的,但在Mac和Linux上是可以的,方法是在.py文件的第一行加上一个特殊的注释:

#!/usr/bin/env python3

然后通过命令给hello.py以执行权限:

chmod a+x hello.py

现在就可以直接运行hello.py了,在MAC下运行:

一、数据类型

1、整数(包括负整数):例如 1, 100, -8080, 0,等等。

2、浮点数(小数):称为浮点数是因为按照科学计数法表示时,一个浮点数的小数点位置是可变的,比如,1.23x109 和 12.3x108 是完全相等的。对于很大或很小的浮点数,必须用科学计数法表示,把 10 用 e 代替,1.23x109 就是 1.23e912.3e8,0.000012 就是 1.2e-5

整数和浮点数在计算机内部存储的方式是不同的,整数运算永远是精确的(除法难道也是精确的?是的!),而浮点数运算则可能会有四舍五入的误差。

3、字符串:是以单引号 ' 或双引号 " 括起来的任意文本,比如 'abc'"xyz" 等等。请注意 ''"" 本身只是一种表示方式,不是字符串的一部分,字符串 'abc' 只有 abc 这3个字符。如果 ' 本身也是一个字符,那就可以用 "" 括起来,比如 "I'm OK" 包含的字符是 I'm空格OK 这6个字符。
如果字符串内部既包含 ' 又包含 " 怎么办?可以用转义字符 \ 来标识,比如:

'I\'m \"OK\"!'

表示的字符串内容是:

I'm "OK"!
  • 转义字符 \ 可以转义很多字符,比如 \n 表示换行,\t 表示制表符,字符 \ 本身也要转义,所以 \\ 表示的字符就是 \
  • 如果字符串里面有很多字符都需要转义,就需要加很多 \,为了简化,Python还允许用 r'' 表示 '' 内部的字符串默认不转义。
  • 如果字符串内部有很多换行,用 \n 写在一行里不好阅读,为了简化,Python允许用 '''...''' 的格式表示多行内容。
    在命令行内输入多行内容时,提示符由 >>> 变为 ...,提示可以接着上一行输入,... 是提示符,不是代码的一部分,当输入完结束符 '''和括号 ) 后,执行该语句并打印结果:

    如果写成程序并存为 .py 文件,就是:
print('''line1
line2
line3''')

4、布尔值:布尔值和布尔代数的表示完全一致,一个布尔值只有 TrueFalse 两种值,注意大小写!
布尔值可以用 andornot 运算:

  • and 运算是 运算,只有所有都为 Trueand 运算结果才为 True
  • or 运算是 运算,只要其中一个为 Trueor 运算结果就为 True
  • not 运算是 运算,只是一个单目运算符,把 True 变成 FalseFalse 变为 True

5、空值:是Python里一个特殊的值,用 None 表示,None 不能理解为 0,因为 0 是有意义的,而 None 是一个特殊的空值。

6、变量:变量名必须是大小写英文、数字和_的组合,且不能用数字开头。
请不要把赋值语句的等号等同于数学的等号,例如:

x = 10
x = x + 2

如果从数学的角度理解,x = x + 2 无论如何都是不成立的,在程序中,赋值语句先计算右侧的表达式 x + 2 ,得到结果 12,再赋值给变量 x,由于 x 之前的值是 10,重新赋值后,x 的值变为 12

7、常量:在Python中,通常用全部大写的变量名表示常量。
这里解释一下整数的除法为什么也是精准的,在Python中,有两种除法:

  • / 除法计算结果是浮点数,即使整除了结果也是浮点数
>>> 9 / 3
3.0
  • // 除法称为地板除,两个整数的除法永远是整数
>>> 10 // 3
3
  • 提供了一个余数运算 %,可以得到两个整数相除的余数
>>> 10 % 3
1

二、字符串和编码

1、字符编码
2、字符串:在最新的Python 3版本中,字符串是以Unicode编码的,支持多语言。
对于单个字符的编码,提供了 ord() 函数获取字符的整数表示,chr() 函数把编码转换为对应的字符,如果知道整数编码,也可以用十六进制写。

>>> ord('韩')
38889
>>> chr(26446)
'李'
  • 由于Python的字符串类型是 str,在内存中以Unicode表示,一个字符对应若干个字节.在网络上传输或保存到磁盘上,就需要把 str 变为以字节为单位的 bytes
    Python对 bytes类型的数据用带 b 前缀的单引号或双引号表示:
x = b'ABC'

要注意区分 'ABC'b'ABC',前者是 str,后者虽然内容显示得和前者一样,但 bytes 的每个字符都只占用一个字节。
以Unicode表示的 str 通过 encode() 方法可以编码为指定的 bytes,例如:

>>> 'ABC'.encode('ascii')
b'ABC'
>>> '中文'.encode('utf-8')
b'\xe4\xb8\xad\xe6\x96\x87'
>>> '中文'.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

纯英文的 str 可以用 ASCII 编码为 bytes,内容是一样的,含有中文的 str 可以用 UTF-8 编码为 bytes。含有中文的 str 无法用 ASCII 编码,因为中文编码的范围超过了 ASCII 编码的范围,Python会报错。

  • bytes 中,无法显示为 ASCII 字符的字节,用 \x## 显示。
  • 反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是 bytes。要把 bytes 变为 str,就需要用 decode()方法:
>>> b'ABC'.decode('ascii')
'ABC'
>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
'中文'
  • 如果 bytes 中包含无法解码的字节,decode() 方法会报错:
>>> b'\xe4\xb8\xad\xff'.decode('utf-8')
Traceback (most recent call last):
  ...
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 3: invalid start byte
  • 如果 bytes 中只有一小部分无效的字节,可以传入 errors='ignore' 忽略错误的字节:
>>> b'\xe4\xb8\xad\xff'.decode('utf-8', errors='ignore')
'中'
  • 计算 str 包含多少个字符,可以用 len() 函数
>>> len('ABC')
3
>>> len('中文')
2

len() 函数计算的是 str 的字符数,如果换成 byteslen() 函数就计算字节数

>>> len(b'ABC')
3
>>> len(b'\xe4\xb8\xad\xe6\x96\x87')
6
>>> len('中文'.encode('utf-8'))
6

当Python解释器读取源代码时,为了让它按UTF-8编码读取,我们通常在文件开头写上这两行:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

第一行注释是为了告诉Linux/OS X系统,这是一个Python可执行程序,Windows系统会忽略这个注释;
第二行注释是为了告诉Python解释器,按照UTF-8编码读取源代码,否则,在源代码中写的中文输出可能会有乱码。

申明了UTF-8编码并不意味着你的 .py 文件就是UTF-8编码的,必须并且要确保文本编辑器正在使用 UTF-8 without BOM 编码。

3、格式化:输出格式化的字符串
在Python中,采用的格式化方式和C语言是一致的,用 % 实现,举例如下:

>>> 'Hello, %s' % 'world'
'Hello, world'
>>> 'Hi, %s, you have $%d.' % ('Michael', 1000000)
'Hi, Michael, you have $1000000.'

常见的占位符有:

占位符 替换内容
%d 整数
%f 浮点数
%s 字符串
%x 十六进制整数
  • 格式化整数和浮点数还可以指定是否补 0 和整数与小数的位数
  • %s 可以把任何数据类型转换成字符串
  • 如果字符串里的 % 是个普通字符时,用 %% 来表示 %
  • 另一种格式化字符串的方法是使用 format() 方法,它会用传入的参数依次替换字符串内的占位符 {0}{1}......,这种方式比 % 要麻烦的多
>>> 'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)
'Hello, 小明, 成绩提升了 17.1%'

三、使用list和tuple

1、list:Python内置的一种数据类型是列表,有序集合,可以随时添加和删除其中的元素。
比如,列出班里同学的名字,可以用一个list表示:

>>> classmates = ['Jack', 'Bob', 'Rose']
>>> classmates
['Jack', 'Bob', 'Rose']
  • 变量 classmates 就是一个list。用 len() 函数可以获得list元素的个数:
>>> len(classmates)
3
  • 用索引来访问list中每一个位置的元素,索引是从 0 开始的,当索引超出范围时,会报一个 IndexError 错误:
>>> classmates[0]
'Jack'
>>> classmates[1]
'Bob'
>>> classmates[2]
'Rose'
>>> classmates[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range
  • 最后一个元素的索引是 len(classmates) - 1,还可以用 -1 做索引,直接获取最后一个元素:
>>> classmates[-1]
'Rose'
>>> classmates[len(classmates) - 1]
'Rose'
  • list是一个可变的有序表,所以可以用 append() 往list中追加元素到末尾:
>>> classmates.append('Kris')
>>> classmates
['Jack', 'Bob', 'Rose', 'Kris']
  • 也可以用 insert() 把元素插入到指定的位置,比如索引号为 1 的位置:
>>> classmates.insert(1, 'Frank')
>>> classmates
['Jack', 'Frank', 'Bob', 'Rose', 'Kris']
  • 要删除list末尾的元素,用 pop() 方法:
>>> classmates.pop()
'Kris'
>>> classmates
[Jack', 'Frank', 'Bob', 'Rose']
  • 要删除指定位置的元素,用 pop(i) 方法,其中 i 是索引位置:
>>> classmates.pop(1)
'Frank'
>>> classmates
['Jack', 'Bob', 'Rose']
  • 要把某个元素替换成别的元素,可以直接赋值给对应的索引位置:
>>> classmates[1] = 'Susa'
>>> classmates
['Jack', 'Susa', 'Rose']
  • list里面的元素的数据类型也可以不同,比如:
>>> L = ['Apple', 123, True]
  • list元素也可以是另一个list,比如:
>>> s = ['python', 'html', ['css', 'vue'], 'java']
>>> len(s)
4

注意 s 只有 4 个元素
如果想拿到 vue 可以写成 s[2][1],因此 s 可以看成是一个二维数组,类似的还有三维、四维……数组,不过很少用到。

  • 如果一个list中一个元素也没有,就是一个空的list,它的长度为0:
>>> L = []
>>> len(L)
0

2、tuple:Python中另一种有序列表叫元祖:tuple,和 list 类似,但是 tuple 一旦初始化就不能修改
同样,列出班里同学的名字:

>>> classmates = ('Jack', 'Bob', 'Rose')
>>> classmates
('Jack', 'Bob', 'Rose')

现在,classmates这个tuple不能变了,它没有append(),insert()这样的方法。其他获取元素的方法和list是一样的,你可以正常地使用 classmates[0]classmates[-1],但不能赋值成另外的元素。

因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。

  • 当你定义一个tuple时,在定义的时候,tuple的元素就必须被确定下来,比如:
>>> t = (1, 2)
>>> t
(1, 2)
  • 如果要定义一个空的tuple,可以写成 ()
>>> t = ()
>>> t
()
  • 但是,要定义一个只有1个元素的tuple,如果你这么定义:
>>> t = (1)
>>> t
1

这样定义的不是tuple,是1这个数!这是因为括号()既可以表示tuple,又可以表示数学公式中的小括号,这就产生了歧义,因此,Python规定,这种情况下,按小括号进行计算,计算结果自然是1

所以,只有1个元素的tuple定义时必须加一个逗号 ,,来消除歧义,在显示的时候Python也会加一个逗号 , 避免误解:

>>> t = (1,)
>>> t
(1,)

四、条件判断

1、if:

if <条件判断>:
    <执行>

2、if: else:

if <条件判断>:
    <执行1>
else:
    <执行2>

3、if: elif: elif: else

if <条件判断1>:
    <执行1>
elif <条件判断2>:
    <执行2>
elif <条件判断3>:
    <执行3>
else:
    <执行4>
  • if 判断条件可以简写
if x:
    print('True')

只要 x非零数值非空字符串非空list等,就判断为 True,否则为 False

4、input
一个有问题的条件判断:

birth = input('birth: ')
if birth < 2000:
    print('00前')
else:
    print('00后')

输入 1995,结果报错:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: str() > int()

这是因为 input() 返回的数据类型是 strstr 不能直接和整数比较,必须先把 str 转换成 整数。Python提供了 int() 函数来完成这件事情:

s = input('birth: ')
birth = int(s)
if birth < 2000:
    print('00前')
else:
    print('00后')

再次运行之后就可以得到正确的结果,但是,如果输入 abc 呢?

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'abc'

原来 int() 函数发现一个字符串并不是合法的数字时就会报错,程序就退出了。

五、循环

1、for...in:把每个元素代入变量x,然后执行缩进块的语句。

names = ['Michael', 'Bob', 'Tracy']
for name in names:
  print(name)

执行代码后,会依次打印出每个元素:

Michael
Bob
Tracy

如果要计算 1-100 的整数之和,Python提供一个 range() 函数,可以生成一个整数序列,再通过 list() 函数可以转换为 list:

>>> list(range(5))
[0, 1, 2, 3, 4]

range(100) 就可以生成 0-100 的整数序列:

sum = 0
for x in range(101):
  sum += sum + x
print(sum)

2、while:只要条件满足,就不断循环,条件不满足时退出循环。
如果要计算 100 以内所有奇数之和,可以用 while 循环:

sum = 0
n = 99
while n > 0:
  sum += sum + n
  n = n - 2
print(sum)

在循环内部变量 n 不断自减,直到变为 -1 时,不再满足while条件,循环退出。

3、break:在循环中,break 语句可以提前退出循环。
打印 1-100 的数字:

n = 1
while n <= 100:
    print(n)
    n = n + 1
print('END')

结果可以打印出 1-100,如果想提前结束,可以用 break 语句:

n = 1
while n <= 100:
    if n > 10: # 当n = 11时,条件满足,执行break语句
        break # break语句会结束当前循环
    print(n)
    n = n + 1
print('END')

执行上面的代码可以看到,打印出 1~10 后,紧接着打印 END,程序结束。

4、continue:跳过当前的这次循环,直接开始下一次循环。

n = 0
while n < 10:
    n = n + 1
    print(n)

结果可以打印出 1~10,但如果想只打印奇数,可以用 continue 语句跳过某些循环:

n = 0
while n < 10:
    n = n + 1
    if n % 2 == 0: # 如果n是偶数,执行continue语句
        continue # continue语句会直接继续下一轮循环,后续的print()语句不会执行
    print(n)

执行上面的代码可以看到,打印的不再是1~10,而是1,3,5,7,9。

六、使用 dict 和 set

1、dict
Python 内置了字典:dict 的支持,dict 全称 dictionary,在其他语言中也称为 map,使用键-值(key-value)存储,具有极快的查找速度。

如果要根据同学的名字查找对应的成绩,用 list 实现就需要两个 list:

names = ['Michael', 'Bob', 'Tracy']
scores = [95, 75, 85]

给定一个名字,要查找对应的成绩,就先要在 names 中找到对应的位置,再从 scores 取出对应的成绩,list 越长,耗时越长。

如果用 dict 实现,只需要一个“名字-成绩”的对照表,直接根据名字查找成绩,不论表有多大,查找速度都不会变慢:

>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d['Michael']
95
  • 把数据放入 dict
>>> d['Adam'] = 67
>>> d['Adam']
67

一个 key 只能对应一个 value,所以,多次对一个 key 放入 value,后面的值会把前面的值冲掉。

  • in 判断 key 是否存在
>>> 'Thomas' in d
False
  • get() 判断 key 是否存在,如果 key 不存在,可以返回 None,或者自己指定的value
>>> d.get('Thomas')
>>> d.get('Thomas', -1)
-1

注意:返回None的时候Python的交互环境不显示结果。

  • pop(key) 删除一个 key
>>> d.pop('Bob')
75
>>> d
{'Michael': 95, 'Tracy': 85}

2、set
set 和 dict 类似,也是一组 key 的集合,但不存储 value。由于 key不能重复,所以,在 set 中,没有重复的 key。

  • 要创建一个 set,需要提供一个 list 作为输入集合:
>>> s = set([1, 2, 3])
>>> s
{1, 2, 3}

注意,传入的参数 [1, 2, 3] 是一个 list,而显示的 {1, 2, 3} 只是告诉你这个 set 内部有 1,2,3 这 3 个元素,显示的顺序也不表示 set 是有序的。

  • 重复元素在set中自动被过滤:
>>> s = set([1, 1, 2, 2, 3, 3])
>>> s
{1, 2, 3}
  • 通过 add(key) 方法可以添加元素到 set 中,可以重复添加,但不会有效果:
>>> s.add(4)
>>> s
{1, 2, 3, 4}
>>> s.add(4)
>>> s
{1, 2, 3, 4}
  • 通过 remove(key) 方法可以删除元素:
>>> s.remove(4)
>>> s
{1, 2, 3}
  • set 可以看成数学意义上的无序和无重复元素的集合,因此,两个 set 可以做数学意义上的交集、并集等操作:
>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s1 & s2
{2, 3}
>>> s1 | s2
{1, 2, 3, 4}

3、再议不可变对象

  • 可变对象,比如 list,对 list 进行操作,list内部的内容是会变化的,比如:
>>> a = ['c', 'b', 'a']
>>> a.sort()
>>> a
['a', 'b', 'c']
  • 不可变对象,比如 str,对 str 进行操作,比如:
>>> a = 'abc'
>>> a.replace('a', 'A')
'Abc'
>>> a
'abc'

虽然字符串有个 replace() 方法,也确实变出了 'Abc',但变量 a 最后仍是 'abc',应该怎么理解呢?
先把代码改成下面这样:

>>> a = 'abc'
>>> b = a.replace('a', 'A')
>>> b
'Abc'
>>> a
'abc'

要始终牢记的是,a 是变量,而 'abc' 才是字符串对象!有些时候,我们经常说,对象 a 的内容是 'abc',但其实是指,a 本身是一个变量,它指向的对象的内容才是 'abc'


当我们调用 a.replace('a', 'A') 时,实际上调用方法 replace 是作用在字符串对象 'abc' 上的,而这个方法虽然名字叫 replace,但却没有改变字符串 'abc' 的内容。相反,replace 方法创建了一个新字符串 'Abc' 并返回,如果我们用变量 b 指向该新字符串,就容易理解了,变量 a 仍指向原有的字符串 'abc',但变量 b 却指向新字符串 'Abc' 了:

所以,对于不变对象来说,调用对象自身的任意方法,也不会改变该对象自身的内容。相反,这些方法会创建新的对象并返回,这样,就保证了不可变对象本身永远是不可变的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容