20190401数据结构与算法1第一章:python入门
1.1 python概述
python是一种解释性语言。通常在被称为python解释器的软件中运行,相应的.py文件被称为脚本或源代码。代码通常是一条命令在一行,但是也可以使一行命令在多行,这就需要反斜杠(\)等来进行多行代表一条命令的标识。(#)表示注释
1.2 python对象
1.2.1 赋值语句:
例如,下面的语句就是将float(98.6)赋值给temperature(标识符),在定义变量(赋值)时,不需要预先定义变量的类型,其会自动根据所赋予的值进行自动匹配。
temperature = 98.6
1.2.2 标识符(变量名,……)
在python中,标识符是有大小写之分的;标识符何有字母、数字、下划线(但不能以数字开头)构成;标识符不能与python中的33个保留字重复。
1.2.3创建和使用对象
实例化:
创建一个类的新实例的过程被称为实例化,通过调用类的构造函数来实例化对象。另一种创建类的实例的方法是调用一个函数来创建和返回这样一个实例。
调用方法:
python支持传统调用函数的方法,调用函数形式:sorted(data),data作为参数传递给函数;python的类可以定义一个或多个函数方法(成员函数),多个的这类的特定实例上的方法可以使用点操作符('.')来调用,例如,data.sorted()。即:如果某函数是相应类中的唯一函数,采用func(data)更好;如果相应类中不仅仅有func函数方法,采用func(data)或data.func()均可;点的左侧表达式用于确认被方法地哦啊用的对象。
1.2.4 Python的内置类
python内置类注意有可变的类和不可变的类,如果类的每个对象在实例化时有一个固定的值,并且在随后的操作中不会被改变,那么他就是不可变的类。,例如float类时不可改变的,一单一个实例被创建,他的值就不能被改变。
python的内置类如下:
类 | 描述 | 不可变 |
bool | 布尔值 | Yes |
int | 整数(任意大小) | Yes |
float | 浮点数 | Yes |
list | 对象的可变序列 | No(可变) |
tuple | 对象的不可变序列 | Yes |
str | 字符串 | Yes |
set | 不同对象的无序集合 | No(可变) |
frozenset | 集合类的不可改变的形式 | Yes |
dict | 关联映射(字典) | No(可变) |
总之,list、set、dict是python内置类中的三种 可变类。
1.2.4.1 序列类型:list、tuple、str类
list是([])python中最常用的容器类型,其有很多相应的操作,还具备随着需求动态扩展和收缩容量的能力。list()函数默认会产生一个空列表。
tuple()类是序列的一个不可改变的版本。注意:如果元组只有一个元素,应该在这一个元素后面增加一个逗号,进行表明是元组,否则就会被当成一个简单的带括号的数值表达式,(17,)是一个一元元组,但(17)是一个数值表达式。
str类专门用来代表一种不变的字符序列,可利用‘ ’ ,“ ”,""" """,形式进行表示。
set,集合中没有重复的元素,而且这些元素没有内在的关系,使用集合的主要优点在于他有一个高度的优化方法来检查特定元素是否包含在集合内。集合的限制:1)集合不保存任何有特定顺序的元素集2)只有不可变类型的实例才可以被添加到一个python的集合类中,因此set中可有int,float,str,tuple,但没有list或set构成的set.
ffozensets类是集合的一种可变形式,所以由frozensets类型组成的集合是合法的。
tuple("hello")
Out[76]: ('h', 'e', 'l', 'l', 'o')
set('hello')
Out[77]: {'e', 'h', 'l', 'o'}
frozenset('hello')
Out[78]: frozenset({'e', 'h', 'l', 'o'})
a = str('hello')
dict={'key':value},代表一个字典或者映射,即从一组不同的键中找到对应的值。有 .keys()、.values、.items()属性。
1.3 表达式、运算符、优先级
举例说明表达式:a+b:如果ab均是数字,则该表达式表示两个数字相加;如果ab均是字符,则表示字符串的连接;如果ab属于不同的类型,会报错。
1.3.1 逻辑运算符
not | 逻辑非 |
and | 逻辑与(短路保护) |
or | 逻辑或(短路保护) |
1.3.2 相等运算符
is | 同一实体 |
is not | 不同的实体 |
== | 等价 |
!= | 不等价 |
当标识符a和b是同一个对象的别名时,表达式 a is b结果为真;如果标识符a和b指向同一个对象,那么表达式 a==b为真。
==和!=运算符用于检验表达式是否相等。is与is not在有必要检验真正的混叠时是适用的。
1.3.3 比较运算符
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
1.3.4 算术运算符
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
// | 整数除法 |
% | 模运算符 |
q = n//m , r = n%m ,则有:n = q*m +r
1.3.5 位运算符
~ | 取反(前缀一元运算符) |
& | 按位与 |
| | 按位或 |
^ | 按位异或 |
<< | 左移位,用零填充 |
>> |
右移位,按符号填充
|
1.3.5 序列运算符
s(str、tuple、list)支持的操作符语法:带有索引的地方,注意索引从零开始:零索引;同时支持负索引
s[j] | 索引下标为j的元素 |
s[start:stop] | 切片,左闭右开[start,stop) |
s[start:stop:step] | 切片,带有步长 |
s+t | 序列的连接 |
k*s | k个序列的连接(s+s+s+s……) |
val in s | 检查元素val在序列s中 |
val not in s | 检查元素va不在序列s中 |
列表list()支持语法del s[i]
1.3.6 扩展赋值运算符
"+=" 和"= a + "的区别,前者会改变引用标识符的值,后者不改变。
alpha = [1,2,3]
belta = alpha
belta += [4,5]
belta = belta + [6,7]
print(alpha) # “+=” 改变原始被引用的标识符的值
[1, 2, 3, 4, 5]
print(belta)
[1, 2, 3, 4, 5, 6, 7]
1.3.7 复合表达式和运算符优先级
1.4 控制流程
条件语句和循环语句
1) 条件语句一般是:
if first_condition:
first_body
elif second_condition:
second_body
elif third_condition:
third_body
else:
fourth_body
2)while循环语句:
while condition:
body
3) for 循环语句:
for element in iterable:
body
for循环可以用在任何类型的迭代结构中,如列表、元组、str、集合、字典或文件(迭代器)。
data =[2,3,5,6,8,233,87,93,1,0,5]
def findmax():
biggest = data[0]
for val in data[1:]:
if val > biggest:
biggest = val
return biggest
biggest = findmax()
print(biggest) # 233
4)基于索引的for循环
def findmax_indexes(data):
biggest_index = 0
for i in range(len(data)):
if data[i] > data[biggest_index]:
biggest_index = i
return biggest_index
print(findmax_indexes(data)) # 5
5)break continue语句
break:如果在嵌套的控制结构中使用break语句,它会导致内层循环立刻终止。continue语句会使得循环体的当前迭代停止。
1.5 函数
函数来描述一个传统的、无状态的函数,该函数被调用而不需要了解特定类的内容或该类的实例。以关键字def开始的第一行作为函数的标志,无需在函数内指定参数或者相应变量的类型。函数定义的其余部分称为函数的主体。函数体通常以缩进的代码块的形式表示,每次调用函数时,python会创建一个专用的活动记录来存储与当前调用相关的信息,这个活动记录包括了命名空间。命名空间用以管理当前调用中局部作用域内的所有标识符。
return 语句
return语句一般在函数体内,用来表示该函数应该立即停止执行,并将所得到的值返回给调用者。如果return执行后没有明确的返回值,则会自动返回None值。通常return语句会在函数体的最后;但如果命令执行受条件逻辑控制,那么在同一函数中可以由多个return语句。
def contains(data,target):
for item in data:
if item == target:
return True
return False
# ex2
def dengcha(A):
A.sort()
d = A[1] - A[0]
for i in range(len(A)-1):
if A[i] != A[i+1] - d:
return 'Impossible'
return 'Possible'
n = int(input())
A = list(map(int, input().split(' ')))
print(dengcha(A))
1.5.1 信息传递
形参:定义func时()内的参数(标识符); 实参:调用func()时发送的对象是实参。例如上面的contains函数,定义时的data,target是形参,在真正调用时,传入的参数为实际参数。
可变参数:
如果在函数体内执行data.append('F'),新的条目被添加到函数标识为data的列表的后面。或者对于以后data,同时都乘同一个因子(factor).
默认参数值:
1)在定义函数时,若对某些形参定义了默认值,在后续传递实参时,如不需改变相应的value时,可以不再传递(但这部分的形参应该放在最后);但若在传递实参的时候,另赋值,则形参的默认值将会被传入的实参值覆盖。
2)当定义的函数有多个形参时,如需要定义某些形参的默认值,应该将其放在最后(如果某形参有默认值,则后续的形参都应有默认值)
def compute_gpa(grades,points={'A+':4.0,'A':4.0,'A-':3.67,'B+':3.33,'B':3.0,'B-':2.67,
'C+':2.33,'C':2.0,'C-':1.67,'D+':1.33,'D':1.0,'D-':1.0,'F':0.0}):
num_counts = 0
total_points = 0
for g in grades:
if g in points:
num_counts += 1
total_points += points[g]
return total_points/num_counts
val = compute_gpa(['A','D','B','A+','B+'])
print(val)
注:range()接受单参数、两个参数、三个参数。返回是list
arange()返回是array
关键字参数:
1.5.2 python内置函数
1.6 简单输入输出
1.6.1控制台的输入和输出
print()函数:
1)默认情况下,print()函数在输出时会在每对参数间插入空格作为分隔,可以通过关键字参数sep自定义想要的分隔符来分隔字符串。例如:
print(1,2,3,4,sep= '*')
1*2*3*4
2)默认情况下,在最后一个参数后悔输出换行符,但同样可以通过关键字参数end指定一个可选择的结尾字符串。
imput()函数
input()函数是一个内置函数,他的主要功能是接收来自用户控制台的信息。如果给出一个可选参数,那么这个函数会显示提示信息,然后等待用户输入任意字符,知道按下enter键。这个函数的返回值是yoghurt在按下返回键前用户所有的输入。
def f1():
reply = input('Enter x and y,separated by sapces:')
pieces = reply.split()
x = pieces[0]
y = pieces[1]
res = x+y
return x+y
In[168]:f1()
Enter x and y,separated by sapces:>? 2 3
Out[168]: '23'
1.6.2 文件
在python中访问文件要先调用一个内置函数open,它返回一个与底层文件交互的对象。例如:fp = open('sample.txt)用于打开名为sample.txt的文件。返回一个对该文本文件只读操作的文件对象。open()函数的第二个参数是确认对文件的访问权限.
'r' | 只读,初始位置在0 |
‘w’ | 对文件进行写的操作,初始位置在0 |
‘a’ | 对文件进行追加的操作,初始位置在文件的末尾 |
fp.close()会关闭与文件相关对象fp相关的文件。
1.7 异常处理
异常是程序执行期间发生的异常突发性事件。逻辑错误或为预料到的情况都有可能造成异常。python解释器也可能引发异常,如果在上下文中处理异常的代码,那么异常就有可能被捕获;如果没有捕获,异常可能会导师解释器停止运行程序,并向控制台发送合适的信息。
常见的错误类型:
python有大量的异常类,他们定义了各种不同类型的异常。Exception类是所有异常类的基类,
抛出异常:
执行raise语句会抛出异常,并将异常类的相应实例作为指定问题的参数。例如,计算平方根的函数传递了一个负数作为参数,就会引发有如下命令的异常:
raise ValueError("X cannot be negative")
1.8 迭代器和生成器
迭代器:
基本的可迭代的容器: 列表(list)、元组(tuple)、集合(set);此外,字符串可以产生它的字符的迭代,字典可以生成它的键的迭代,文件也可以产生它的行的迭代,用户自定义类型也可以支持迭代。
1) 迭代器是一个对象,通过一系列的值来管理迭代。如果变量i定义为一个迭代器对象,接下来每次调用内置函数next(i),都会从当前序列中产生一个后续的元素;要是没有后续元素了,则会抛出一个StopIteration异常。
2)对象obj是可迭代的,那么通过语法iter(obj)可以产生一个迭代器。
注:list的实例是可迭代的,但它本身不是一个迭代器,如data=[1,2,4,8],调用next(data)是非法的。然而,通过语法i=iter(data)则可以产生一个迭代器对象,然后调用next(i)将返回列表中的元素。python中的for循环语法使这个过程自动化,为可迭代的对象创造一个迭代器,然后反复调用下一个元素直至捕获StopIteration异常。
python还支持产生隐式迭代序列值函数和类,即无需立刻构建数据结构来存储它所有的值。例如,调用range(1000)不是返回一个数字列表,而是返回一个可迭代的range对象。
生成器:
在python中创建迭代器最方便的 技术是使用生成器。生成器的语法实现类似于函数,但不返回值。为了显示序列中的每一个元素,会使用yield语句。如下面例子的区别(普通函数和生成器):
# 传统的普通函数,返回值是具体的结果
def tra_factors(n):
results = []
for k in range(1,n+1):
if n % k == 0:
results.append(k)
return results
tra_factors(100)
Out[223]: [1, 2, 4, 5, 10, 20, 25, 50, 100]
# 定义的生成器函数,返回的是一个生成器。
def gen_factors(n):
for k in range(1,n+1):
if n % k == 0:
yield k
gen_factors(100)
Out[225]: <generator object gen_factors at 0x000001BEC78D1FC0>
注:在同一python实现中,yield和return语句结合起来是非法的。
1.9 python的其他便利特点:
1.9.1 条件表达式
条件表达式可以取代一个简单的控制结构。一般的语法表达式的形式如下:
expr1 if condition else expr2
例如具体求绝对值的条件表达式的形式:
result =(n if n >= 0 else -n)
1.9.2 解析语法
一个常见的编程任务是基于另一个序列的处理来产生一系列的值,通常,这个任务在python中使用所谓的解析语法后实现很简单。他的一般形式:
[expr1 for val in iterable if condition]
[k*k for k in range(1,n+1)] # 列表解析
{k*k for k in range(1,n+1)} # 结合解析
(k*k for k in range(1,n+1)) # 生成器解析
{k: k*k for k in range(1,n+1)} # 字典解析
例如求平方的列表解析:
squares = [k*k for k in range(1,5)]
print(squares)
[1, 4, 9, 16]
1.9.3 序列类型的打包和解包
自动打包:
例如 data = 2,4,6,8,会使标识符data赋值成元组(2,4,6,8),这种行为被称为元组的自动打包。;在python中,另一种常用的打包是从一个函数中返回多个值。return x,y
自动解包:
a,b,c,d = range(7,11) ,自动解包允许单个标识符的一系列元素赋值给序列中的各个元素。例如在调用有着多个返回值的函数时。
同时分配技术:
自动打包和自动解包结合起来就是同时分配技术,即我们显示地将一系列值赋给一系列的标识符,
x,y,z = 3,4,5
该赋值右边将自动打包成一个元组,然后自动解包,将他的元素分配给左边的三个标识符。(这类技术在排序算法中,常用于交换位置)。
1.10 作用域和命名空间
1.11模块和import语句
from math import pi,sqrt
这个命令将在math模块定义的pi和sqrt添加到当前的命名空间,允许直接使用标识符pi,sqrt来调用相应的math中的函数方法。
现有模块:
伪随机数生成:
python中的模块能够生成伪随机数(数字是统计上随机的)