Java程序员学python3.0--入门篇

参考廖雪峰大神的python3.0教程,适用于有一定基础的Java程序员,会对比着Java来学习python。代码在PyCharm中运行通过,地址为github。本篇主要介绍python的一些基础知识,包括安装运行(PyCharm设置)、基础语法、函数、高级特性、函数式编程、模块等。在下一篇会介绍python面向对象相关的知识。

python简介

Python的哲学就是简单优雅,尽量写容易看明白的代码,尽量写少的代码

应用场景

  • 首选是网络应用,包括网站、后台服务等等;
  • 其次是许多日常需要的小工具,包括系统管理员需要的脚本任务等等;
  • 另外就是把其他语言开发的程序再包装起来,方便使用。

优点

  • 简洁优雅。
  • 非常完善的基础代码库,覆盖了网络、文件、GUI、数据库、文本等大量内容
  • 大量的第三方库

缺点

  • 运行速度慢:Python是解释型语言,代码在执行时会一行一行地翻译成机器码。但是大量的应用程序不需要这么快的运行速度,因为用户根本感觉不出来
  • 代码不能加密:如果要发布你的Python程序,实际上就是发布源代码

安装Python

linux下安装

1
2
3
4
5
wget https://www.python.org/ftp/python/3.5.2/Python-3.5.2.tgz --no-check-certificate
tar -zxvf Python-3.5.2.tgz
cd Python-3.5.2/
./configure --prefix=/global/exec/fangyeqing/python-3.5.2/
make&&make install

从安装日志中可以看到python3自带pip,easyinstall,setup-tools

1
2
Installing collected packages: setuptools, pip
Successfully installed pip-8.1.1 setuptools-20.10.1

环境变量

环境变量添加,将刚才configure设置的地址添加到环境变量中:

1
vi ~/.bash_profile

内容:

1
2
#python
export PATH=/global/exec/fangyeqing/python-3.5.2/bin:$PATH

source之后测试是否安装成功:

1
2
source ~/.bash_profile
python3

windows下安装

python-3.5.2官方下载地址

安装过程中,务必勾上,就不用自己添加到环境变量了

  • [x] Add Python 3.5 to PATH

安装完后测试是否成功

1
python

解释器

当我们编写Python代码时,我们得到的是一个包含Python代码的以.py为扩展名的文本文件。要运行代码,就需要Python解释器去执行.py文件。安装python之后自带了CPython,就用这个 就可以了。

编译器

Windows下安装PyCharm,官方下载地址为pycharm-professional-2016.2.3,第一次打开的时候,选择激活方式为code,填入激活码(激活码来自互联网,仅供学习交流之用)

pycharm配置

配置的文件在github项目中,直接导入也可以,下载地址。不怕麻烦可以按下面一步步设置:

  1. 界面窗口设置:

    1
    Appearance&&Behavior -> Appearance -> show tool windows bars
  2. 编辑器设置:file -> Setting ->Editor

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #设置Python自动引入包
    general > autoimport -> python :show popup
    #“代码自动完成”时间延时设置
    Code Completion -> Auto code completion in (ms):0 -> Autopopup in (ms):500
    #显示“行号”与“空白字符”
    Appearance -> 勾选“Show line numbers”、“Show whitespaces”、“Show method separators”
    设置编辑器“颜色与字体”主题
    Colors & Fonts -> Scheme name -> 选择黑色背景的主题“Darcula”->Sava as先保存一份->Size -> 设置为“14”
    #python文件默认编码
    File Encodings> IDE Encoding: UTF-8;Project Encoding: UTF-8;
  3. python文件模板设置:file and code template>python scripts

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    """
    __title__ = '$Package_name'
    __author__ = '$USER'
    __time__ = '$DATE'
    # code is far away from bugs with the god animal protecting
    I love animals. They taste delicious.
    ┏┓ ┏┓
    ┏┛┻━━━┛┻┓
    ┃ ☃ ┃
    ┃ ┳┛ ┗┳ ┃
    ┃ ┻ ┃
    ┗━┓ ┏━┛
    ┃ ┗━━━┓
    ┃ 神兽保佑 ┣┓
    ┃ 永无BUG! ┏┛
    ┗┓┓┏━┳┓┏┛
    ┃┫┫ ┃┫┫
    ┗┻┛ ┗┻┛
    """

hello world

PyCharm

如果前面已经安装好PyCharm,就跟IntelliJ Idea一样,新建项目,新建py文件,直接运行就可以了。

1
2
print('hello python')
print(100+200+300)

后面的示例程序都是在PyCharm中直接运行即可。

当然也可以通过交互式命令行、文本形式、py脚本形式(linux)运行。

交互式命令行

1
2
3
python3 #进入交互式命令行模式,windows下为python
100+200+300
exit() #退出,Ctrl+D也可以

文本形式

编辑文本hello-world.py,内容为:

1
print(100+200+300)

执行

1
python3 hello-world.py

脚本形式

linux下如果想直接运行py脚本,在开头加上:

1
2
#!/usr/bin/env python3
print(100+200+300)

执行

1
hello-world.py

Python基础

  • #开头的语句是注释
  • 语句以冒号:结尾时,缩进的语句视为代码块
  • 4个空格的缩进
  • 大小写敏感
    1
    2
    3
    4
    5
    6
    # print absolute value of an integer:
    a = 100
    if a >= 0:
    print(a)
    else:
    print(-a)

数据类型和变量

数据类型

数据类型跟Java类似,基本类型主要有以下几种:

  • 整数
  • 浮点数
  • 字符串:单引号或者双引号,转义字符“\”
  • 布尔值:True、False
  • 空值:None
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 整数
    print(1)
    print(-8080)
    print(0xff00)
    # 浮点数
    print(1.23)
    print(12.3e8)
    # 字符串
    print('I\'m \"OK\"!')
    # 布尔值
    print(True)
    print(2 > 3)
    # 空值
    print(None)

变量

动态类型,“=”赋值任意类型

1
2
3
4
a = 'ABC'
b = a
a = 'XYZ'
print(b)

  • 执行a = ‘ABC’,解释器创建了字符串’ABC’和变量a,并把a指向’ABC’:
  • 执行b = a,解释器创建了变量b,并把b指向a指向的字符串’ABC’:
  • 执行a = ‘XYZ’,解释器创建了字符串’XYZ’,并把a的指向改为’XYZ’,但b并没有更改:
  • 所以,最后打印变量b的结果自然是’ABC’了。

常量

用全部大写的变量名表示常量。

1
2
PI = 3.14159265359
print(PI)

字符串和编码

计算机编码类型

  • ASCII编码:1 byte,只支持英文
  • Unicode编码:2 byte,支持中文、英文
  • UTF-8编码:可变长度1-6byte,英文字母1个字节,汉字通常3个字节,很生僻的字符被编码成4-6个字节。
字符 ASCII Unicode UTF-8
A 01000001 00000000 01000001 01000001
中 x 01001110 00101101 11100100 10111000 10101101
  • 在计算机内存中,统一使用2个字节的Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为可变长度的UTF-8编码。
  • 用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件。
  • 浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器.很多网页的源码上会有类似的信息,表示该网页正是用的UTF-8编码

python编解码

bytes类型

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

1
x = b'ABC'

纯英文可以用ascii编码成bytes,中文只能用UTF-8编码成bytes,所以最好统一用UTF-8

1
2
print('中文'.encode('utf-8'))
print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8'))

源码的中文处理

当你的源代码中包含中文的时候,就需要务必指定保存为UTF-8编码

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

格式化输出

与C语言类似,用占位符表示:%d、%f、%s、%x。其中,%%来转义表示一个%。

例如:小明的成绩从去年的72分提升到了今年的85分,请计算小明成绩提升的百分点,并用字符串格式化显示出’xx.x%’,只保留小数点后1位

1
2
3
4
5
6
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
s1 = 72
s2 = 85
s3 = (s1-s2)/s1*100
print('%.2f%%' % s3)

python集合类型

python集合类型 创建方式 对应Java类型
list [] List
tuple () List
map {} Map
set set() set

list:[]

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

1
2
3
4
5
6
7
8
9
10
11
12
classmates = ['Michael', 'Bob', 'Tracy'] #list初始化
print(classmates)
print(len(classmates)) #list长度len()
print(classmates[0]) #取序号处元素
print(classmates[-1]) #反向取序号处元素
classmates.append('Adam') #末尾插入
classmates.insert(1, 'Jack') #序号处插入
classmates.pop() #删除末尾
classmates.pop(1) #删除序号处
classmates[1] = 'Sarah' #序号处替换
print(classmates)

list里面的元素的数据类型也可以不同,比如:

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

list元素也可以是另一个list,比如:

1
2
s = ['python', 'java', ['asp', 'php'], 'scheme']
print(s[2])

如果一个list中一个元素也没有,就是一个空的list,它的长度为0:

1
2
L = []
print(len(L))

tuple:()

相当于不可变的list,没有append、insert方法,小括号表示。只有1个元素的tuple时,也会加一个逗号,以免你误解成数学计算意义上的括号

1
2
3
4
classmates = ('Michael', 'Bob', 'Tracy')
print(classmates)
t = (1,)
print(t)

与java的final类似,虽然是不可变的,但是tuple中的list是可变的

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

dict:{}

类似于java的map,dict的key必须是不可变对象

1
2
3
4
5
6
7
d = {'Michael': 95, 'Bob': 75, 'Tracy': 85} #初始化
print(d['Michael']) #取key为xxx的值,key不存在会报错
d['Adam'] = 67 #给key给xxx的赋值
print('Thomas' in d) #判断key是否存在
print(d.get('Thomas')) #取key为xxx的值,不存在返回空
print(d.get('Thomas', -1)) #取key为xxx的值,不存在返回-1
print(d.pop('Bob')) #删除key为xxx

注意:dict迭代时。

  • Python 3.x 里面,利用 items()来迭代
  • Python 2.x 里面,iteritems() 和 viewitems()方法已经废除

set

set和dict的唯一区别仅在于没有存储对应的value。创建set必须以list作为输入集合:

1
2
s = set([1, 2, 3])
print(s)

set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:

1
2
3
4
s1 = set([1, 2, 3])
s2 = set([2, 3, 4])
print(s1 & s2)
print(s1 | s2)

不变与可变

list是可变对象

1
2
3
classmates = ['Michael', 'Bob', 'Tracy']
classmates.sort()
print(classmates)

str是不变对象

1
2
3
4
a = 'abc'
b = a.replace('a', 'A')
print(a)
print(b)

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

其实说这么多,就是类似于java中的final类型,不能改变对象的地址,但是可以改变内容。

条件判断

注意冒号和缩进,else if必须写成elif

1
2
3
4
5
6
7
8
age = input('birth:')
age = int(age) #相当于java的Integer.parse(String)
if age >= 18:
print('adult')
elif age >= 6:
print('teenager')
else:
print('kid')

循环

for

跟java类似

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

range(i1,i2,n)表示从i1到i2的数组,步进为n,range(i)表示range(0,i),n省略为1,list(range())表示转化成list

1
print(list(range(1, 5)))

while循环

跟java类似

1
2
3
4
5
6
sum = 0
n = 99
while n > 0:
sum = sum + n
n = n - 2
print(sum)

break和continue

跟java一样,break语句可以在循环过程中直接退出循环,而continue语句可以提前结束本轮循环

1
2
3
4
5
6
for x in range(20):
if x == 10:
break
if x % 2 == 0:
continue
print(x)

函数

内置函数

绝对值、求最大值

1
2
print(abs(-100))
print(max(1, 2, 3, 199))

数据类型转换函数:
int、float、str、bool

1
2
3
4
5
6
7
print(int('123'))
print(int(12.34))
print(float('12.34'))
print(str(1.23))
print(str(100))
print(bool(1))
print(bool(''))

定义函数

定义函数,以def开头。没有return语句,返回结果为None

1
2
3
4
5
6
7
8
9
def my_abs(x):
if not isinstance(x, (int, float)): #参数检查
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x
print(my_abs(-10))

在其他py文件中调用,则需要引入from _2_def.py import my_abs。当然,在PyCharm中只需要Alt+Enter引入。

空函数

空函数:

1
2
def nop():
pass

pass还可以用在其他语句里

1
2
if age >= 18:
pass

返回多个值

游戏中经常需要从一个点移动到另一个点,给出坐标、位移和角度,就可以计算出新的新的坐标。Python函数返回的仍然是单一值,以tuple形式而已。

1
2
3
4
5
6
7
8
9
10
11
import math
def move(x, y, step, angle=0):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
a, b = move(100, 100, 60, math.pi / 6)
print(a, b)
r = move(100, 100, 60, math.pi / 6)
print(r)

练习

请定义一个函数quadratic(a, b, c),接收3个参数,返回一元二次方程:ax2 + bx + c = 0的两个解。详解见:_3_function/quadratic.py

递归函数

跟java类似,也要小心栈溢出的问题

1
2
3
4
5
6
7
def fact(n):
if n == 1:
return 1
return n * fact(n - 1)
print(fact(5))
print(fact(10))
# print(fact(1000))

函数参数

必选参数

必须传入的参数

默认参数

  • 必选参数在前,默认参数在后
  • 当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数
  • 默认参数必须指向不变对象
    1
    2
    3
    4
    5
    6
    7
    8
    def power(x, n=2):
    s = 1
    while n > 0:
    n -= 1
    s = s * x
    return s
    print(power(5))
    print(power(5, 3))

可变参数

在入参数前面加了一个*号,表示可变参数在函数调用时自动组装为一个tuple

1
2
3
4
5
6
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
print(calc(1, 2, 3))

关键字参数

在入参数前面加了一个**号,在函数内部自动组装为一个dict

1
2
3
4
5
6
7
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
person('Michael', 30)
person('Bob', 35, city='Beijing')
person('Adam', 45, gender='M', job='Engineer')
extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, **extra)

命名关键字

如果要限制关键字参数的名字,就可以用命名关键字参数。

1
2
3
def person(name, age, *, city, job):
print(name, age, city, job)
person('Jack', 24, city='Beijing', job='Engineer')

已经有了一个可变参数,命名关键字参数就不再需要一个特殊分隔符*了:

1
2
3
def person(name, age, *args, city, job):
print(name, age, args, city, job)
person('Jack', 24, 3, 1, city='Beijing', job='Engineer')

参数组合

参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
f1(1, 2)
f1(1, 2, c=3)
f1(1, 2, 3, 'a', 'b')
f1(1, 2, 3, 'a', 'b', x=99)
args = (1, 2, 3, 4)
kw = {'d': 99, 'x': '#'}
f1(*args, **kw)
def f2(a, b, c=0, *, d, **kw):
print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
f2(1, 2, d=99, ext=None)
args = (1, 2, 3)
kw = {'d': 88, 'x': '#'}
f2(*args, **kw)

对于任意函数,都可以通过类似func(args, *kw)的形式调用它

小结

  • 默认参数一定要用不可变对象,如果是可变对象,程序运行时会有逻辑错误!
  • 要注意定义可变参数和关键字参数的语法:
    • *args是可变参数,args接收的是一个tuple;
    • **kw是关键字参数,kw接收的是一个dict。
  • 调用函数时如何传入可变参数和关键字参数的语法:
    • 可变参数既可以直接传入:func(1, 2, 3),又可以先组装list或tuple,再通过args传入:func((1, 2, 3));
    • 关键字参数既可以直接传入:func(a=1, b=2),又可以先组装dict,再通过kw传入:func({‘a’: 1, ‘b’: 2})。
  • 使用args和*kw是Python的习惯写法,当然也可以用其他参数名,但最好使用习惯用法。
  • 命名的关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值。

高级特性

切片

  • L[i1:i2]表示从第i个到第i-2个,间隔为1。i1为负数时,表示从倒数第-i1个开始。
  • L[i1:]表示到最后一个
  • L[:i2]表示前i2个
  • L[i1:i2:n]表示从第i个到第i-2个,间隔为n。
  • L[:]表示复制L
    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
    L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
    # 切片
    print(L[0:3])
    print(L[1:3])
    print(L[-1])
    print(L[-3:-1])
    L1 = list(range(100))
    print(L1[1:20])
    # 前十个数
    print(L1[:10])
    # 后十个数
    print(L1[-10:])
    # 前十个数,没两个取一个
    print(L1[:10:2])
    # 所有数,每5个取一个
    print(L1[::5])
    # 复制一个list
    print(L1[:])
    # tuple切片仍是tuple
    print((0, 1, 2, 3, 4, 5)[:3])
    # 切片用于字符串切割
    s = 'ABCDEFG'
    s1 = s[:3]
    s2 = s[-4:]
    print(s1, s2,)

迭代

任何可迭代对象都可以作用于for循环,包括我们自定义的数据类型,只要符合迭代条件,就可以使用for循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# dict迭代
from collections import Iterable
d = {'a': 1, 'b': 2, 'c': 3}
for key in d:
print(key)
for value in d.values():
print(value)
for k, v in d.items():
print(k, v)
# 字符串迭代
for ch in 'ABC':
print(ch)
# 判断是否可以迭代
print(isinstance('abc', Iterable))
print(isinstance(123, Iterable))
# 类java下标循环
for i, value in enumerate(['A', 'B', 'C']):
print(i, value)
# 两个变量,list元素中为tuple
for x, y in [(1, 1), (2, 4), (3, 9)]:
print(x, y)

列表生成式

运用列表生成式,可以快速生成list,可以通过一个list推导出另一个list,而代码却十分简洁

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
import os
# 生成[1x1, 2x2, 3x3, ..., 10x10]
print([x*x for x in range(1, 11)])
# 选出仅偶数的平方
print([x * x for x in range(1, 11) if x % 2 == 0])
# 两层循环生成全排列
print([m + n for m in 'ABC' for n in 'XYZ'])
# 列出当前目录下的所有文件和目录名
print([d for d in os.listdir('.')])
# 生成表达式
d = {'x': 'A', 'y': 'B', 'z': 'C'}
print([k + '=' + v for k, v in d.items()])
# list字符串变小写
L = ['Hello', 'World', 'IBM', 'Apple']
print([s.lower() for s in L])
# 条件判断
L1 = ['Hello', 'World', 18, 'Apple', None]
L2 = [s.lower() for s in L1 if isinstance(s, str)]
print(L2)
# 双重for循环-构造全排列dict组成的list
L1 = ['A', 'B', 'C']
L2 = [1, 2, 3]
L3 = [{'name': name, 'number': number} for name in L1 for number in L2]
print(L3)
# 双重for循环-构造一一对应dict组成的list:[{'number': 1, 'name': 'A'}, {'number': 2, 'name': 'B'}, {'number': 3, 'name': 'C'}]
L4 = [{'name': name, 'number': number} for name_index, name in enumerate(L1)
for number_index, number in enumerate(L2)
if name_index == number_index]
print(L4)
# zip-构造一一对应dict组成的list:[{'number': 1, 'name': 'A'}, {'number': 2, 'name': 'B'}, {'number': 3, 'name': 'C'}]
L5 = [{'name': name, 'number': number} for (name, number) in zip(L1, L2)]
print(L5)

生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

  • 把一个列表生成式的[]改成(),就创建了一个generator
  • 一个函数定义中包含yield关键字,是一个generator函数,generator函数的“调用”实际返回一个generator对象
  • generator函数在每次next(g)或者for循环调用的时候执行,yield返回结果,再次执行时从上次yield语句处继续执行
    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
    g = (x * x for x in range(10))
    print(next(g))
    print(next(g))
    #斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
    # 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
    def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
    yield b
    a, b = b, a + b
    n = n + 1
    return 'done'
    f = fib(6)
    print(f)
    for n in fib(6):
    print(n)
    # 杨辉三角
    def triangles():
    L = [1]
    while True:
    yield L
    L.append(0)
    L = [L[i-1] + L[i] for i in range(len(L))]
    n=0
    for t in triangles():
    print(t)
    n += 1
    if n == 10:
    break

迭代器

对比 Iterable(可迭代对象) Iterator(迭代器)
特点 可以直接作用于for循环 可作用于next()函数的对象
举例 集合类型、generator generator、iter(集合类型)

集合数据类型:如list、tuple、dict、set、str等。
generator:包括生成器和带yield的generator function。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 可迭代对象:Iterable判断
print(isinstance([], Iterable))
print(isinstance({}, Iterable))
print(isinstance('abc', Iterable))
print(isinstance((x for x in range(10)), Iterable))
print(isinstance(100, Iterable))
# 迭代器:Iterator判断
print(isinstance((x for x in range(10)), Iterator))
print(isinstance([], Iterator))
print(isinstance({}, Iterator))
print(isinstance('abc', Iterator))
# iter转化集合类型为Iterator
print(isinstance(iter([]), Iterator))
print(isinstance(iter('abc'), Iterator))

函数式编程

高阶函数

把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式

1
2
3
4
5
6
7
# 变量指向函数
f = abs
print(f(-10))
# 高阶函数
def add(x, y, f1):
return f1(x) + f1(y)
print(add(-5, 6, abs))

map/reduce

  • map(函数,Iterator):将传入的函数依次作用到序列的每个元素(并行计算),并把结果作为新的Iterator返回
    • map(f, [x1, x2, x3, x4]) = [f(x1), f(x2), f(x3), f(x4)]
  • reduce(函数,Iterator):reduce把结果继续和序列的下一个元素做累积计算(串行计算)
    • reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
      1
      2
      3
      4
      5
      6
      7
      8
      9
      # 实现int函数:map利用dict将集合str挨个转换为数字,reduce加权累加每位
      def str2int(s):
      def fn(x, y):
      return x * 10 + y
      def char2num(s):
      L = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
      return L[s]
      return reduce(fn, map(char2num, s))
      print(str2int('123'))

filter

filter()用于过滤序列。把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。返回的是一个Iterator

1
2
3
4
# filter:过滤偶数
def is_odd(n):
return n % 2 == 1
print(list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])))

sorted

语法:sorted(L, key=函数, reverse=True/False)

  • L:序列
  • key:排序规则
  • reverse:是否逆序
    1
    2
    3
    4
    5
    6
    7
    8
    9
    L = [36, 5, -12, 9, -21]
    print(sorted(L))
    # sorted:key
    print(sorted(L, key=abs))
    s = ['bob', 'about', 'Zoo', 'Credit']
    print(sorted(s))
    print(sorted(s, key=str.lower))
    # # sorted:reverse=True逆序
    print(sorted(s, key=str.lower, reverse=True))

返回函数

  • 返回的函数并没有立刻执行,而是直到调用了f()才执行
  • 相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”
  • 返回函数不要引用任何循环变量,或者后续会发生变化的变量
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    def lazy_sum(*args):
    def sum():
    ax = 0
    for n in args:
    ax = ax + n
    return ax
    return sum
    f = lazy_sum(1, 3, 5, 7, 9)
    print(f)
    print(f())

匿名函数

  • Lambda 函数相当于没有显式声明的函数,定义即用。
  • 只能有一个单独的表达式
    1
    lambda x, y: x * y

相当于:

1
2
def f(x, y):
return x * y

装饰器

在代码运行期间动态增加功能的方式,称之为“装饰器”。类似于java的Annotation。下述代码

  • now()相当于执行log(now)
  • tomorrow()相当于执行log(‘exective’)(now)
  • @functools.wraps(func)是为了不改变函数的__name__属性
    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
    import functools
    def log(args):
    if isinstance(args, str):
    def decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
    print('begin %s %s():'%(args,func.__name__))
    func(*args, **kw)
    print('end %s %s():'%(args,func.__name__))
    return wrapper
    return decorator
    else:
    func = args
    @functools.wraps(func)
    def wrapper(*args, **kw):
    print('begin call %s():' % func.__name__)
    func(*args, **kw)
    print('end call %s():'%func.__name__)
    return wrapper
    @log
    def now():
    print('2015-3-25')
    now()
    @log('exective')
    def tomorrow():
    print('2017/2/13')
    now()
    tomorrow()

偏函数

当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数

1
2
3
4
print(int('101', base=2))
# 将str转int的int函数改装成2进制,固定base参数为2
int2 = functools.partial(int, base=2)
print(int2('101'))

模块

  • 在Python中,一个.py文件就称之为一个模块(Module)
  • 按目录来组织模块的方法,称为包(Package)

使用模块

1
import module_name

安装第三方模块

安装

  • 第三方模块搜索:下载地址
  • pip安装:比如要做图片处理Pillow,
    1
    pip install Pillow

图片压缩

1
2
3
4
5
6
from PIL import Image
im = Image.open('xiaolan.jpg')
print(im.format, im.size, im.mode)
im.thumbnail((400, 400))
im.save('xiaolan.png', 'JPEG')

模块搜索路径

Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块。搜索路径存放在sys模块的path变量中,查看sys.path

1
2
import sys
print(sys.path)

如果我们要添加自己的搜索目录,有两种方法:

  1. 一是直接修改sys.path,添加要搜索的目录:
    1
    2
    >>> import sys
    >>> sys.path.append('/Users/michael/my_py_scripts')

这种方法是在运行时修改,运行结束后失效。

  1. 第二种方法是设置环境变量PYTHONPATH,该环境变量的内容会被自动添加到模块搜索路径中。

参考

http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000
http://blog.csdn.net/pipisorry/article/details/39909057

文章目录
  1. 1. python简介
    1. 1.1. 应用场景
    2. 1.2. 优点
    3. 1.3. 缺点
  2. 2. 安装Python
    1. 2.1. linux下安装
      1. 2.1.1. 环境变量
    2. 2.2. windows下安装
    3. 2.3. 解释器
    4. 2.4. 编译器
      1. 2.4.1. pycharm配置
  3. 3. hello world
    1. 3.1. PyCharm
    2. 3.2. 交互式命令行
    3. 3.3. 文本形式
    4. 3.4. 脚本形式
  4. 4. Python基础
    1. 4.1. 数据类型和变量
      1. 4.1.1. 数据类型
      2. 4.1.2. 变量
      3. 4.1.3. 常量
    2. 4.2. 字符串和编码
      1. 4.2.1. 计算机编码类型
      2. 4.2.2. python编解码
        1. 4.2.2.1. bytes类型
        2. 4.2.2.2. 源码的中文处理
        3. 4.2.2.3. 格式化输出
    3. 4.3. python集合类型
      1. 4.3.1. list:[]
      2. 4.3.2. tuple:()
      3. 4.3.3. dict:{}
      4. 4.3.4. set
    4. 4.4. 不变与可变
    5. 4.5. 条件判断
    6. 4.6. 循环
      1. 4.6.1. for
      2. 4.6.2. while循环
      3. 4.6.3. break和continue
  5. 5. 函数
    1. 5.1. 内置函数
    2. 5.2. 定义函数
      1. 5.2.1. 空函数
      2. 5.2.2. 返回多个值
        1. 5.2.2.1. 练习
    3. 5.3. 递归函数
    4. 5.4. 函数参数
      1. 5.4.1. 必选参数
      2. 5.4.2. 默认参数
      3. 5.4.3. 可变参数
      4. 5.4.4. 关键字参数
      5. 5.4.5. 命名关键字
      6. 5.4.6. 参数组合
      7. 5.4.7. 小结
  6. 6. 高级特性
    1. 6.1. 切片
    2. 6.2. 迭代
    3. 6.3. 列表生成式
    4. 6.4. 生成器
    5. 6.5. 迭代器
  7. 7. 函数式编程
    1. 7.1. 高阶函数
      1. 7.1.1. map/reduce
      2. 7.1.2. filter
      3. 7.1.3. sorted
    2. 7.2. 返回函数
    3. 7.3. 匿名函数
    4. 7.4. 装饰器
    5. 7.5. 偏函数
  8. 8. 模块
    1. 8.1. 使用模块
    2. 8.2. 安装第三方模块
      1. 8.2.1. 安装
      2. 8.2.2. 模块搜索路径
  9. 9. 参考
|