ThinkPython
程序=数据+对数据的处理
数据:
数据的类型: 存放数据的容器
-
可变类型
-
列表(list)
序列,其元素可以是任意类型
-
字典(dist)
一种映射,用哈希实现
-
集合(set)
-
-
不可变类型
-
字符串(str)
字符串是一串有序的字符
-
数字(整形int, 浮点数float)
-
元组(tuple)
元组和列表非常相似。二者间重要的区别就是元组是不可修改的。
-
对数据的处理:
不同编程语言的具体细节看着很不一样,但几乎所有编程语言都会有一些基础指令,
输入系统
从键盘、文件、网络或者其他设备上获得数据
input, open.read()
输出系统
将数据在屏幕中显示, 或者存到文件中、通过网络发送等等
print, open.write()
数学运算
进行基本的数学操作, 比如四则运算
Python内置了一个数学模块 math, 这一模块提供了绝大部分常用的数学函数。
条件判断
检查特定条件是否满足来运行相应的代码
(1) if else
(2) 条件表达式
if x > 0:
y = math.log(x)
else:
y = float('nan')
#换成
y = math.log(x) if x > 0 else float('nan')
重复循环
迭代进行一些操作
(1) for, while
(2) 列表推导
列表推导简洁, 易阅读。这些语句的执行也往往比同样情况下的 for 循环更快一些, 有时候甚至快很多。
def capitalize_all(t):
res = []
for s in t:
res.append(s.capitalize())
return res
#换成
def capitalize_all(t):
return [s.capitalize() for s in t]
#方括号的意思是我们正在建立一个新的列表。方括号内的表达式确定了此新列表中的元素,然后 for 语句表明我们要遍历的序列。
(3)生成器表达式
生成器表达式与列表推导相似, 用的不是方括号, 而是圆括号。
>>> g = (x**2 for x in range(5))
>>> g
<generator object <genexpr> at 0x7f4c45a786c0>
上面这样运行得到的结果就是一个生成器对象,用来遍历一个值的序列。但与列表推导不同的是,生成器表达式并不会立即计算出所有的值;它要等着被调用。内置函数 next 会从生成器中得到下一个值:
>>> next(g)
0
>>> next(g)
1
当程序运行到序列末尾的时候,next 函数就会抛出一个停止遍历的异常。你也可以用一个 for循环来遍历所有的值。生成器对象能够追踪在序列中的位置,所以 for 语句就会在 next 函数退出的地方开始。一旦生成器使用完毕了,接下来就要抛出一个停止异常了:
>>> for val in g: ...
···print(val)
4
9
16
生成器表达式多用于求和、求最大或者最小这样的函数中:
>>> sum(x**2 for x in range(5))
30
(4) 递归:函数自己调用自己。
递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
使用递归需具备的条件:
- 子问题须与原始问题为同样的事,且更为简单;
- 不能无限制地调用本身,化简为非递归状况处理。
注意:一定要有基准语句;
基本思想
-
封装
对不同类型的数据组合起来: 结构体(其他语言, python有list, 其元素可以是任意类型, 所以不需要结构体)
对不同的数据和语句组合起来: 函数(方便维护, 避免代码冗余)
把不同的数据与函数组合起来: 类
把不同的类组合起来, 形成特定功能的小团体: 模块、包
-
泛化
由具体的、个别的扩大为一般的, 即用更通用替换特定的过程。
-
接口设计
目的: 允许调用者随意操作而不用处理一些无关紧要的细节
类方法的接口设计
信息隐藏: 一种开发原则, 一个对象提供的接口应该独立于其实现, 尤其是不受对象属性设置变化的影响。
-
重构
重构(Refactoring)就是通过调整程序代码改善软件的质量、性能,使其程序的设计模式和架构更趋合理,提高程序的扩展性和维护性。
-
增量式开发
其中增量是指在程序开发过程中, 先开发主要功能模块, 再开发次要功能模块, 逐步完善程序。
-
信仰之跃,pass
-
异常
捕获异常:
try: 可能出错的代码 #如果出错,则执行except:内容,否则不执行 except 异常1: 处理方式
抛出异常:
raise assert 语句:一种检查错误的语句,检查一个条件,如果不满足就抛出异常。
-
继承:
继承就是基于一个已有的类进行修改来定义一个新的类。
-
多态:
一个函数能处理多种类型的特征, 就叫做多态。
-
面向对象
Python 是一种面向对象的编程语言, 这就意味着它提供了一些支持面向对象编程的功能, 有以下这些特点:
• 程序包含类和方法的定义。
• 大多数运算都以对象运算的形式来实现。
• 对象往往代表着现实世界中的事物, 方法则相对应地代表着现实世界中事物之间的相互作用。方法在语义上与函数是完全相同的, 但在语法上有两点不同:
• 方法要定义在一个类定义内部,这样能保证方法和类之间的关系明确。
• 调用一个方法的语法与调用函数的语法不一样。函数与方法调用的区别:
函数调用的语法里面, print_time(start)就表明了函数是主动的。这句语句的意思就相当于说,『嘿, print_time 函数! 给你这个对象,你来打印输出一下。』
在面向对象的编程中, 对象是主动的。方法的调用, 比如 start.rint_time()就像是说,『嘿,start,你打印输出一下你自己』
难点
- 拷贝 以及 函数传参
其他
-
any: Python内置函数, 该函数接收一个布尔值序列, 只要里面有任意一个是真, 就返回真。
-
all: Python内置函数, 该函数在整个序列都是真的情况下才返回真。
-
计数器
计数器定义在一个名为 collections 的标准模块中。你可以用字符串, 列表或者任何支持遍历的类型来初始化一个计数器:
>>> from collections import Counter >>> count = Counter('parrot') >>> count Counter({'r': 2, 't': 1, 'o': 1, 'p': 1, 'a': 1})
-
默认字典
collection 模块还提供了一个默认字典, 与普通字典的区别在于当你读取一个不存在的键的时候, 程序会添加上一个新值给这个键。即当键存在时, 返回键对应的值; 键不存在时, 返回默认值:
>>> from collections import defaultdict >>> dic = defaultdict(int) >>> dic['a']#该式中的int 可以替换为 str flaot等。 #为int 时的默认值为 0 #为 str 时的默认值为 '' #若想设置默认值为一给定的值 比如 'oppo' 则如下 >>>> dic = defaultdict(lambda : 'oppo') >>>> dic['a'] 'oppo'
-
命名元组
Python 提供了一个更简单的方式来新建类:
from collections import namedtuple Point = namedtuple('Point', ['x', 'y'])
第一个参数是你要写的类的名字。第二个是 Point 对象需要有的属性列表, 为字符串。命名元组返回的值是一个类的对象。
>>> Point <class '__main__.Point'>
-
不定长参数
*args元组; **kwargs字典
def printall(*args, **kwargs): print(args, kwargs)