Python3 总结

Python 有两个版本,一个是 2.x 版,一个是 3.x 版,这两个版本是不兼容的. 直接学习最新的 Python 3.6.4.
Python 是解释型语言,你的代码在执行时会一行一行地翻译成CPU能理解的机器码,这个翻译过程非常耗时,但是慢到用户感觉不出来

安装

  • 去官网下载安装包
  • 如果已经安装 Homebrew 直接执行 brew install Python3 安装

查看

1
2
3
4
5
bogon:~ syc$ python -V
Python 2.7.10
bogon:~ syc$ python3 -V
Python 3.6.4
bogon:~ syc$

解释器

  • 官方版本的解释器 CPython (用 C 开发的)
  • Jython 是运行在Java平台上的Python解释器,可以直接把Python代码编译成Java字节码执行。

简单使用

终端输入 Python3 出现 >>> 即可编写 Python 代码, 输入 exit() 或者按 Ctrl+d 退出
输入 Python3 filename.py 运行文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bogon:~ syc$ python3
Python 3.6.4 (default, Jan 6 2018, 11:51:15)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1+2-3*5
-12
>>> print("1+2-3*5=",1+2-3*5)
1+2-3*5= -12
>>> name = input("option haha->")
option haha->eee
>>> name
'eee'
>>> print(name)
eee
>>>

基本语法

Python 大小写敏感, 采用缩进式语法, # 表示注释, 当语句以冒号 : 结尾时,缩进的语句视为代码块.
按照约定俗成的管理,应该始终坚持使用4个空格的缩进.

转意

1
2
3
4
5
6
7
8
9
10
11
>>> print('\\')
\
>>> print(r'\\')
\\
>>> print('''1
... 2
... 3''')
1
2
3
>>>

除法

除法 / 结果为浮点型, // 地板除法的结果为整形, 既 只取结果的整数部分

1
2
3
4
5
>>> 9/3
3.0
>>> 10//3
3
>>>

字符

计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。
最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255(二进制11111111=十进制255),如果要表示更大的整数,就必须用更多的字节。
最早只有127个字符被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为 ASCII编码
Unicode 把所有语言都统一到一套编码里, 如 GB2312

Python的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes (对bytes类型的数据用带b前缀的单引号或双引号表示)
'ABC'b'ABC',前者是str一个字符对应若干个字节,后者是bytes每个字符都只占用一个字节。
1个中文字符经过UTF-8编码后通常会占用3个字节,而1个英文字符只占用1个字节。

ord() 函数获取字符的整数表示,chr() 函数把编码转换为对应的字符
以Unicode表示的 str 通过 encode() 方法可以编码为指定的 bytes, bytes 通过 decode() 变为 str

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

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

占位符

1
2
3
4
>>> 'int=%d float=%f string=%s 16=%x' % (1,2.3,'str',0x1a)
'int=1 float=2.300000 string=str 16=1a'
>>> 'string={0} float={1:.2f}'.format('haha',1.234567)
'string=haha float=1.23'

list 列表

list是一种有序的集合,可以随时添加和删除其中的元素。
list里面的元素的数据类型也可以不同

1
2
3
4
5
6
7
8
9
10
>>> arr = [0,1,2,'3a']
>>> arr[0]=9
>>> arr
[9, 1, 2, 3]
>>> len(arr)
4
>>> arr[2]
2
>>> arr[-1]
'3a'

arr[-1] 表示倒数第一个
arr.append(4) 添加
arr.insert(1,5) 添加到指定位置
arr.pop() 默认删除最后一个, arr.pop(1) 根据索引删除

set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# 有序 无重复
s = set([1,1,2,2,3,3])
print(s)

# 添加
s.add(4)
print(s)

# 根据 key 删除
s.remove(2)
print('s=',s)

s2 = set([4,5,6,7])
print('s2=',s2)

# 交集
print(s & s2)

# 并集
print(s | s2)

tuple 元组

元组不可变(swift 元组可变)
只有1个元素的tuple定义时必须加一个逗号 , 来消除歧义 t = (123,)

diction 字典(map)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

dic = {'a':1, 'b':2, 'c':3}

print(dic['a'])
print(dic.get('a'))

print('aaa' in dic)
#dic['aaa'] 报错
print(dic.get('aaa')) # None
print(dic.get('aaa', 111)) # 111

# 根据 key 删除
dic.pop('c')
print(dic)

切片(类似 range)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# list
arr = range(3,9)
print(arr)

arr = list(arr)
print(arr)

# 从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2
print(arr[0:3])

# 倒数第3个到倒数第1个
print(arr[-3:-1])


# 前10,每2个取一个
print(arr[:10:2])

# 所有数,每2个取一个
print(arr[::2])

# tuple
print((0,1,2,3,4,5,6,7,8)[2:6])
# str
print('abcdefg'[2:6])

if

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

1
2
if x:
print('True')

for / while

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

print('\n for in list')

for x in ['a',2,1.23]:
print(x)

print(r"\n for in range")

for x in range(3):
if x == 1:
# 结束当前循环
continue
print(x)

print(''' s
while
e''')
n = 0
while n < 4:
if n > 2:
# 跳出循环
break
print(n)
n+=1

迭代

凡是可作用于for循环的对象都是Iterable类型.
凡是可作用于next()函数的对象都是Iterator类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from collections import Iterable

b = isinstance('abc', Iterable)
print('str is Iterable', b)

b = isinstance([1,2,3], Iterable)
print('list is Iterable', b)

b = isinstance((1,2,3), Iterable)
print('tuple is Iterable', b)

print('\n for string')
# str
for s in 'abc':
print(s)

print('\n for list')
# list
a = [2,4,6,8]
for v in a:
print(v)

# enumerate函数可以把一个list变成索引-元素对
for i,v in enumerate(a):
print(i,v)

print('\n for dictionary')
# dict
d = {'a':1, 'b':'b', 'c':3.5}

for k in d:
print(k)

for v in d.values():
print(v)

for k,v in d.items():
print(k, v)

列表生成式 生成器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

a = [x*x for x in range(10)]
print(a)

a = [x+x for x in range(10) if x%2==0]
print(a)


a = [i+j for i in 'abc' for j in '123']
print(a)
a = [i+'-'+j for i in 'abc' for j in '123']
print(a)

一边循环一边计算的机制,称为生成器:generator

  • 列表生成式的[]改成(),就创建了一个generator
  • 函数定义中包含yield关键字,就是一个generator

generator 遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行.
函数是顺序执行,遇到return语句或者最后一行函数语句就返回.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

g = (i for i in range(5))
print(g)

for n in g:
print('for generator=',n)

# 函数
# 斐波拉契数列(Fibonacci)
def fib(max):
(n, a, b) = (0, 0, 1)
while n < max:
print('func=',b)
(a, b) = (b, a + b)
n = n + 1
return 'done'

fib(10)

# generator
# 把 print ---> yield
def fib2(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'

g = fib2(10)
while True:
try:
n = next(g)
print('while generator=',n)
except Exception as e:
print('while Exception=',e.value)
break

函数

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

空函数

1
2
3
4
5
6
7
8
9
def nonFunc():
# pass 占位符,什么也不做
pass

nonFunc()

if 1 > 2:
# pass 占位符,什么也不做
pass

单个返回值函数

函数执行完毕也没有return语句时,自动return None

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def myFunc(a,b):
if not isinstance(a, (int, float)):
return 'type error'
elif not isinstance(b, (int, float)):
return TypeError('type error')
elif a > b:
return True
else:
return False

# 把函数名赋给一个变量,相当于给这个函数起了一个“别名”
a = myFunc
print(a(1,2))

print(myFunc(4,2))
print(myFunc('a',2))
print(myFunc(4,'a'))

多个返回值函数

返回一个tuple可以省略括号
默认参数必须指向不变对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import math

# 默认参数必须指向不变对象
def move(x,y, step = 0, angle = 0):
newx = x + step * math.cos(angle)
newy = y + step * math.sin(angle)
return newx, newy

x, y = move(1, 1, 2, 45*180)
print(x, y)

# step=2
x, y = move(1, 1, 2)
print(x, y)

# angle = 2
x, y = move(1, 1, angle = 2)
print(x, y)

可变参数

  • 参数前加 * 可变参数在函数调用时自动组装为一个tuple

    1
    2
    3
    4
    5
    6
    7
    8
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-

    def printParams(*pars):
    for par in pars:
    print(par)

    printParams(1,'a',3.5)
  • 参数前加 ** 关键字参数在函数调用时自动组装为一个dict

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-

    def printParams(**pars):
    print(pars)

    printParams(a=1,b='a',c=3.5)

    d = {'a':1, 'b': 'a', 'c':3.5}
    printParams(**d)
  • *, 后面的参数被视为命名关键字参数, 限制关键字参数的名字

    1
    2
    3
    4
    5
    6
    7
    8
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-

    # 只接收 b,c
    def printParams(a, *, b, c):
    print(a,b,c)

    printParams(1, b='a', c=0.3)
  • 混合使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-

    def printParams(a, b='b' , *c, **d):
    print(a,b,c,d)

    printParams(1, 2, 0.3,0.4, d1=1,d2='d2')
    # list or tuple
    arr = (1,2,3)
    dic = {'d1':1,'d2':2}
    printParams(1, 2, *arr, **dic)

    def printParams2(a, b='b' , *,c, **d):
    print(a,b,c,d)

    printParams2(1, 2, c=0.4, d1=1,d2='d2')

高阶函数

既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from functools import reduce

# map
# x * x
def f(x):
return x*x
r = map(f, [1,2,3,4,5])
print(r)
l = list(r)
print(l)

# int ---> str
r = map(str, [1,2,3,4,5])
print(list(r))

# reduce 计算
# sum
def f2(a,b):
return a+b

r = reduce(f2,[1,2,3,4,5])
print(r)

# filter 过滤
def f3(x):
b = x % 2 == 0
return b

r = filter(f3,[1,2,3,4,5])
print(list(r))

# sorted 排序
r = sorted([1,5,4,2,3])
print(r)

# 忽略大小写
# key 函数来实现自定义的排序
# reverse 反向排序
r = sorted(['Sss','Aaa','sss','aaa'], key = str.lower, reverse = True)
print(r)

闭包

TODO: 思想和 swift 一致

匿名函数

关键字 lambda 表示匿名函数,冒号前面的x表示函数参数
用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突
匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果
由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数

1
2
3
4
5
6
7
8
9
10
11
12
f = lambda x: x * x
v = f(3)
print(v)

m = map(lambda x: x*x, [1,2,3,4])
print(list(m))

def f(x):
return lambda: x + x
v = f(3)
print(v)
print(v())

装饰器

我的理解类似触发器/过滤器/aop(面向切面)

在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import functools

# log

print("============ log()")

def log(fu):
def show(*args, **kw):
print('log : call %s()' % fu.__name__)
return fu(*args, **kw)
return show

def func1():
print('func1111')


# 1
f = log(func1)
print('f1.name = %s' % f.__name__)
f()
print('f1.name = %s' % f.__name__)

# 2
f = log(func1())
print('f2.name = %s' % f.__name__)
f
print('f2.name = %s' % f.__name__)

#@log
print("============ @log")

def log2(msg):
def showf(fu):
def showt(*args, **kw):
print('log2 : call %s() msg: %s' % (fu.__name__, msg))
return fu(*args, **kw)
return showt
return showf

@log2('log2 func2 msg')
def func2():
print("func22222")

def func3():
print("func33333")


f = func2
print('f1.name = %s' % f.__name__)
f()
print('f1.name = %s' % f.__name__)

f = log2('log2 func3 msg')(func3)
print('f2.name = %s' % f.__name__)
f()
print('f2.name = %s' % f.__name__)



def log4(text):
def decorator(func):
# functools.wraps 则可以将原函数对象的指定属性复制给包装函数对象, 默认有 __module__、__name__、__doc__,或者通过参数选择。
@functools.wraps(func)
def wrapper(*args, **kw):
print('log4 : %s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator

def func4():
print("func44444")

f = log4('log4 func4 msg')(func4)
print('f4.name = %s' % f.__name__)
f()
print('f4.name = %s' % f.__name__)

functools.partial

functools.partial可以创建一个新的函数(偏函数),这个新函数可以固定住原函数的部分参数,从而在调用时更简单。

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import functools

def f(a, b):
print(a,b)

f(1,2) # print 1 2

ff = functools.partial(f,b=10)
ff(3) # print 3 10

OOP

面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想
封装、继承和多态

类(Class)和实例(Instance)

  1. _xx 以单下划线开头的表示的是protected类型的变量。即保护类型只能允许其本身与子类进行访问
  2. __xx 双下划线的表示的是私有类型的变量。只能允许这个类本身进行访问
  3. __xx__ 是特殊变量,特殊变量是可以直接访问的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

'class haha'

# 使用__author__变量把作者写进去,
__author__ = 'syc'

import types

# 类

class Preson(object):
def run(self):
print('Preson is running ...')

# 继承 object
class Student(Preson):
# 类属性
height = 170
# 方法的第一个参数永远是self,表示创建的实例本身, 其他随意
def __init__(self,name,score,age):
self.name = name
# 私有变量(private)
self.__score = score
self.__age__ = age

# 除了self不用传递,其他参数正常传入
def showMsg(self, msg):
print('%s - %f - %d - %d = %s' % (self.name,self.__score,self.__age__,self.height,msg))

class Teacher(Preson):
def run(self):
print('teacher override preson run')

# 动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。
class Dog(object):
def run(self):
print('dog is running...')

# Python这样的动态语言,则不一定需要传入 Preson类型。只需要保证传入的对象有一个run()方法就可以了
def go(obj):
obj.run()

# 实例
stu = Student('name',45.6,12)
# 实例属性
stu.weight = 123
print(stu.weight)
stu.showMsg('hahaha')
print(stu.name)
print(stu._Student__score)
print(stu.__age__)

tea = Teacher()

# 多态
stu.run()
tea.run()

# 鸭子类型
print('\ngo......')
go(stu)
go(tea)
d = Dog()
go(d)

print('\nattribute......')
# 判断是否有属性
b = hasattr(stu,'height')
print('stu has height = %s' % b)
b = hasattr(stu,'name')
print('stu has name = %s' % b)
b = hasattr(stu,'__score')
print('stu has score = %s' % b)
b = hasattr(stu,'__age__')
print('stu has age = %s' % b)
# 设置属性
setattr(stu, 'name','hahaname')
# 获取属性
b = getattr(stu,'name')
print('stu name = %s' % b)
print('stu height = %s' % stu.height)
Student.height = 11
print('stu height = %s' % stu.height)
print('stu height = %s' % Student.height)
# 获取不存在的属性
b = getattr(stu,'name222','222222')
print('stu name222 = %s' % b)
# 获取方法并执行
print('\nattribute......')
fn = getattr(stu,'showMsg')
fn('getattr')

print('\ntype......')
# 类型
t = type(stu)
print('student type = %s' % t)

# 类型判断
t = type(go) == types.FunctionType
print('is function type = %s' % t)

# 类型判断
print('stu is preson = %s' % isinstance(stu, Preson))

print(__doc__)
print(__author__)

每一个包目录下面都会有一个 __init__.py 文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。__init__.py 可以是空文件,也可以有Python代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
1. 让这个文件直接在Unix/Linux/Mac上运行
2. 文件本身使用标准UTF-8编码
"""

# 模块的文档注释,任何模块代码的第一个字符串都被视为模块的文档注释
# 文档注释用 __doc__ 访问
' a test module '

# 使用__author__变量把作者写进去,
__author__ = 'syc'

# 导入 sys 系统库
import sys

# 正常的函数和变量名是公开的(public)
def pubFun():
print("public func")

# 类似_xxx和__xxx这样的函数或变量就是非公开的(private)
def _priFun():
print("private func")

第三方库都会在Python官方的 pypi.python.org 网站注册,要安装一个第三方库,必须先知道该库的名称,使用 pip3 install 库名称 安装
Anaconda 是一个基于Python的数据处理和科学计算平台,它已经内置了许多非常有用的第三方库,装上Anaconda,就相当于把数十个第三方模块自动安装好了
Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys模块的path变量中 sys.path

未完待续


参考

本文标题:Python3 总结

文章作者:史彦超

发布时间:2018年02月23日 - 14:02

最后更新:2021年07月20日 - 16:07

原始链接:https://doingself.github.io/2018/02/23/2018-02-23-Python3-%E6%80%BB%E7%BB%93/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Donate comment here