输入输出

输出

最简单的输出

1
print('hello,world')

也可以接受多个字符串

1
2
3
4
print('hello','world')
print()遇到‘,’会输出空格
输出:
hello world

多行输出

1
2
3
4
5
6
7
print('''line1
... line2
... line3''')
输出
line1
line2
line3

可以直接计算结果

1
2
3
print(10+20)
输出
30

格式化输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
在Python中,采用的格式化方式和C语言是一致的,用%实现,举例如下:
>>> 'Hello, %s' % 'world'
'Hello, world'
>>> 'Hi, %s, you have $%d.' % ('Michael', 1000000)
'Hi, Michael, you have $1000000.'
你可能猜到了,%运算符就是用来格式化字符串的。在字符串内部,%s表示用字符串替换,%d表示用整数替换,有几个%?占位符,后面就跟几个变量或者值,顺序要对应好。如果只有一个%?,括号可以省略。

format()
另一种格式化字符串的方法是使用字符串的format()方法,它会用传入的参数依次替换字符串内的占位符{0}、{1}……,不过这种方式写起来比%要麻烦得多:
>>> 'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)
'Hello, 小明, 成绩提升了 17.1%'

f-string
最后一种格式化字符串的方法是使用以f开头的字符串,称之为f-string,它和普通字符串不同之处在于,字符串如果包含{xxx},就会以对应的变量替换:

>>> r = 2.5
>>> s = 3.14 * r ** 2
>>> print(f'The area of a circle with radius {r} is {s:.2f}')
The area of a circle with radius 2.5 is 19.62
上述代码中,{r}被变量r的值替换,{s:.2f}被变量s的值替换,并且:后面的.2f指定了格式化参数(即保留两位小数),因此,{s:.2f}的替换结果是19.62

输入

**input()**接受的数据默认以字符串形式储存,若需要使用,需提前进行数据转换

python基础

数据类型

整数

在python中的表示方法和数学上的写法一样

也可以使用十六进制表示,例如:0xff000xa5b4c3d2,等等。

对于很大的数,例如10000000000,很难数清楚0的个数。Python允许在数字中间以_分隔,因此,写成10_000_000_00010000000000是完全一样的。

浮点数

浮点数可以用数学写法,如1.233.14-9.01,等等。但是对于很大或很小的浮点数,就必须用科学计数法表示,把10用e替代,1.23x109就是1.23e9,或者12.3e8,0.000012可以写成1.2e-5,等等。

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

1
2
3
print(0.1+0.2)
输出
0.30000000000000004

字符串

字符串是以单引号'或双引号"括起来的任意文本,比如'abc'

如果字符串内部既包含'又包含"怎么办?可以用转义字符\来标识

1
2
3
4
例如
print('I\'m \"OK\"!')
输出
I'm "OK"!

还能用r''表示''内部的字符串默认不转义

1
2
3
4
a=r'\\\t\\'
print(a)
输出
\\\t\\

布尔值

一个布尔值只有TrueFalse两种值

数字布尔规则

1
2
3
4
5
整数:0为False,其他均为True

浮点数:0.0为False,其他均为True

复数:0+0j为False,其他均为True

字符串布尔规则

字符串的真假判断只基于是否为空,而不考虑内容。

1
2
3
"" False 空字符串

" " True 空格字符串(非空)

布尔值可以用andornot运算

空值

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

主要用途

1.表示函数没有返回值

1
2
3
4
5
def greet(name):
print(f"Hello, {name}!")

result = greet("Alice") # 函数没有 return 语句
print(result) # 输出: None

2.作为函数参数的默认值

1
2
3
4
def connect_to_database(host, port=None):
if port is None:
port = 3306 # 默认端口
print(f"Connecting to {host}:{port}")

……

变量

命名规则:

1.只能包含字母(a-z, A-Z)、数字(0-9)、下划线(_)

2.只能以字母或下划线开头

3.区分大小写

4.避免关键字

赋值

1
2
3
4
5
进行a = 'ABC'赋值时,Python解释器干了两件事情:

在内存中创建了一个'ABC'的字符串;
在内存中创建了一个名为a的变量,并把它指向'ABC'。
也可以把一个变量a赋值给另一个变量b,这个操作实际上是把变量b指向变量a所指向的数据

字符串以及编码

最早的ASCII码利用一字节表示大小写英文字母,数字和一些符号,但是后来发现一个字节不够用,而且不能和ASCII码冲突,于是各个国家都制定了字节的编码标准,但是这又会导致冲突,在多语言文本中出现乱码,为了解决冲突问题,产生了Unicode字符集,用2个字节表示一个字符(除了非常偏僻的使用4个字节),

但是如果是纯英文的话又会导致使用Unicode编码比ASCII编码需要多一倍的存储空间,于是又出现了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。

字符编码工作方式:

在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。

用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件

浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器

字符串与字节类型的转换

由于Python的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes

Python对bytes类型的数据用带b前缀的单引号或双引号表示:

1
x = b'ABC'

以Unicode表示的str通过encode()方法可以编码为指定的bytes,例如:

1
2
3
4
5
6
7
8
>>> '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)

反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法:

1
2
3
4
>>> b'ABC'.decode('ascii')
'ABC'
>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
'中文'

len()

计算字符长度

1
2
3
4
>>> len('ABC')
3
>>> len('中文')
2

如果是bytes,就计算字节数

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

由于Python源代码也是一个文本文件,所以,当你的源代码中包含中文的时候,在保存源代码时,就需要务必指定保存为UTF-8编码。当Python解释器读取源代码时,为了让它按UTF-8编码读取,我们通常在文件开头写上这两行:

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

第一行注释是为了告诉Linux/OS X系统,这是一个Python可执行程序,Windows系统会忽略这个注释;

第二行注释是为了告诉Python解释器,按照UTF-8编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。

列表(list)和元组(tuple)

list

list是一种有序的集合,可以随时添加和删除其中的元素。

获取元素个数

1
2
>>> len(classmates)
3

访问元素(索引从0开始)

1
2
3
4
5
>>> classmates = ['Michael', 'Bob', 'Tracy']
>>> classmates[0]
'Michael'
>>> classmates[-1]
'Tracy'

追加元素

1
2
3
>>> classmates.append('Adam')
>>> classmates
['Michael', 'Bob', 'Tracy', 'Adam']

插入元素

1
2
3
>>> classmates.insert(1, 'Jack')
>>> classmates
['Michael', 'Jack', 'Bob', 'Tracy', 'Adam']

删除元素

1
2
3
4
5
6
7
8
9
>>> classmates.pop()(默认末尾)
'Adam'
>>> classmates
['Michael', 'Jack', 'Bob', 'Tracy']
加上索引
>>> classmates.pop(1)
'Jack'
>>> classmates
['Michael', 'Bob', 'Tracy']

替换元素

1
2
3
>>> classmates[1] = 'Sarah'
>>> classmates
['Michael', 'Sarah', 'Tracy']

一个列表可以储存不同数据类型

1
>>> L = ['Apple', 123, True]

list中也能嵌套list

1
2
3
>>> s = ['python', 'java', ['asp', 'php'], 'scheme']
>>> len(s)
4

tuple

另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改

1
>>> classmates = ('Michael', 'Bob', 'Tracy')

不可变的tuple有什么意义?因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。

元组的创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> t = ()或t = tuple()
>>> t
()

但是,要定义一个只有1个元素的tuple,如果你这么定义:
>>> t = (1)
>>> t
1

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

所以,只有1个元素的tuple定义时必须加一个逗号,,来消除歧义:
>>> t = (1,)
>>> t
(1,)

”可变“的元组

1
2
3
4
5
>>> t = ('a', 'b', ['A', 'B'])
>>> t[2][0] = 'X'
>>> t[2][1] = 'Y'
>>> t
('a', 'b', ['X', 'Y'])

模式匹配

当使用if…elif进行条件判断的时候,如果条件很多,就会显得代码很复杂,可读性较差,此时可以使用match语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
score = 'B'
if score == 'A':
print('score is A.')
elif score == 'B':
print('score is B.')
elif score == 'C':
print('score is C.')
else:
print('invalid score.')

改写为
score = 'B'
match score:
case 'A':
print('score is A.')
case 'B':
print('score is B.')
case 'C':
print('score is C.')
case _: # _表示匹配到其他任何情况
print('score is ???.')

复杂匹配

如果有多个匹配值则使用‘|’来分隔不同的值

1
2
case 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18:
print('11~18 years old.')

列表匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
args = ['gcc', 'hello.c', 'world.c']
# args = ['clean']
# args = ['gcc']

match args:
# 如果仅出现gcc,报错:
case ['gcc']:
print('gcc: missing source file(s).')
# 出现gcc,且至少指定了一个文件:
case ['gcc', file1, *files]:
print('gcc compile: ' + file1 + ', ' + ', '.join(files))
# 仅出现clean:
case ['clean']:
print('clean')
case _:
print('invalid command.')

其中 case ['gcc', file1, *files]:``file1匹配的是gcc后的第一个元素。*files则是剩余所有没被匹配的元素,返回的结果是列表

', '.join(files)则是将files列表中的元素以’,‘隔开。

dict(字典)和set(集合)

字典dict全称dictionary,在其他语言中也称为map使用,使用键值对储存,有极快的查找速度。因为其底层使用了哈希表,实现了类似随机存取的效果,在哈希表不冲突的时候时间复杂度为o(1),因此可以快速查询。代价是内存占用多。

而list相反:

  1. 查找和插入的时间随着元素的增加而增加;
  2. 占用空间小,浪费内存很少。
1
2
3
>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d['Michael']
95

因为哈希值是对key进行哈希计算得到的,所以如果有相同的key值会发生冲突,python采用覆盖的形式处理,也就是相同的最后一个key中的值是最终的值

1
2
3
4
d = {'Michael': 95, 'Bob': 75, 'Tracy': 85,'Michael': 34}
print(d['Michael'])
输出
34

同样的,key的值应该为不可变对象,在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key

报错

若key不存在则会报错

要避免key不存在的错误,有两种办法,一是通过in判断key是否存在:

1
2
>>> 'Thomas' in d
False

二是通过dict提供的get()方法,如果key不存在,可以返回None,或者自己指定的value:

1
2
3
>>> d.get('Thomas')
>>> d.get('Thomas', -1)
-1

字典的删除

删除一个key,用pop(key)方法,对应的value也会从dict中删除:

1
2
3
4
5
d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d.pop('Bob')
75
>>> d
{'Michael': 95, 'Tracy': 85}

set

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

创建集合

1
2
3
4
5
6
7
8
>>> s = {1, 2, 3}
>>> s
{1, 2, 3}

或者使用一个list
>>> s = set([1, 2, 3])
>>> s
{1, 2, 3}

添加元素

add()函数

1
2
3
4
5
6
>>> s.add(4)
>>> s
{1, 2, 3, 4}
>>> s.add(4)
>>> s
{1, 2, 3, 4}

删除元素

1
2
3
>>> s.remove(4)
>>> s
{1, 2, 3}

数学计算

可以进行交集,并集等运算

1
2
3
4
5
6
>>> s1 = {1, 2, 3}
>>> s2 = {2, 3, 4}
>>> s1 & s2
{2, 3}
>>> s1 | s2
{1, 2, 3, 4}

对不可变对象使用replace()

1
2
3
4
5
>>> a = 'abc'
>>> a.replace('a', 'A')
'Abc'
>>> a
'abc'

这里是因为使用replace()时是创造了一个新的字符串‘Abc’并返回,而原字符串‘abc’是不变的,又a指向字符串‘abc’这一事实不变,所以a还是’abc’,当我们把replace()创造出的‘Abc’赋值给b,便能输出‘Abc’

1
2
3
4
5
6
>>> a = 'abc'
>>> b = a.replace('a', 'A')
>>> b
'Abc'
>>> a
'abc'

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

函数

函数调用

调用一个函数需要知道函数名和对应参数,否则会报错

函数的定义

定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。

函数体内部执行的语句一旦执行到return便会停止

如果没有return语句执行完返回None结果,return None可以简写为return

空函数

1
2
def nop():
pass

这种函数什么都不会做,但是可以用来占位让代码先跑起来。

参数检查

我们自己写的函数python会检查参数个数,但不会检查参数类型,因此我们在定义函数的时候要自己加入错误信息。数据类型检查可以用内置函数isinstance()实现:

例如

1
2
3
4
5
6
7
def my_abs(x):
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x