title: 《Python基础编程》笔记
date: 2017-06-02 10:37:37
tags:
- python
categories: - Python
第一章 基础知识
-
让脚本像普通程序一样运行:代码首句 #!/usr/bin/env python告诉系统这是py文件,默认用py解释程序运行。(可惜我电脑.py文件默认打开方式是pycharm…)
-
‘ # ‘ 行注释。
-
’\‘ 转义字符,eg:print(‘Let\’ go!’)>> let’s go!
-
‘’’ ‘’’ 长字符串:需要写一个跨多行或者包含特殊字符的字符串,用’’'代替普通引号。
-
r 原始字符串: 输出与原始字符串里每一个保持一致;eg:print(r’Let/‘s go!’)>> Let/'s go!
-
u Unicode字符串:py3.x中所有字符串都是Unicode编码
第二章 列表和元组
-
序列:Py含有六种内建序列:列表[],元组(),字符串,Unicode字符串,buffer对象,xrange对象。
-
列表可以修改,元组不能修改
-
通用序列操作:
- 索引:访问单个元素
- 从0开始,可以有负值(从右往左)eg: s='hello’s[-1] = ‘o’;
- 一个函数返回值是序列,就可以直接对结果进行索引操作
- 分片:访问一定范围内元素,是一种优雅的写法
- 格式:number[a: b : c] 序列number从起点a到b以步长c的集合。a可为空,默认0,b可为空,默认结尾,c可为空可省略,默认1.即 number[:]表示全部。
- eg:number=[1,2,3,4,5,6,7,8,9,10]; number[1,-2,2] >>[2,4,6,8]
- 序列相加:通过’+'可以进行序列连接操作
- 序列相乘:eg:初始化一个长度为10列表 sequence=[None]*10
- 成员资格:‘in’ 判断一个值是否在序列里,也可以判断字符串是不是另一个子串。
- 长度,最小值,最大值:内建函数len(),min(),max()
- 索引:访问单个元素
-
列表list:[]
- list函数:字符串->list:list(‘hello’) =[‘h’,‘e’,‘l’,‘l’,‘o’]
- 将一个字符构成的列表->字符串:’’.join([‘h’,‘e’,‘l’,‘l’,‘o’])
- 删除元素: del list[index]
- 分片赋值:
- 可以使用与原序列不等长序列将分片替换:
eg: name=list(‘Perl’) name[1:]=list(‘ython’)
name >>[‘P’,‘y’,‘t’,‘h’,‘o’,‘n’]; - 分片可以在不需要替换任何原有元素的情况下插入新的元素:
eg: number=[1,5];number[1:1]=[2,3,4]; number >>[1,2,3,4,5] - 以此类推,分片删除也是可行的:
eg: number=[1,2,3,4,5]; number[1:4]=[]; number >>[1,5]
- 可以使用与原序列不等长序列将分片替换:
- append(val):在末尾添加元素
- count(val):统计某元素在列表出现的次数
- extend([]):在末尾添加多个值,比如添加一个列表里所有元素。
- index(val):在列表里找到某个值第一个匹配的索引位置
- insert(index,val):在index位置插入一个对象
- pop(index):会移除列表里index位置元素,默认是最后一个,并且返回该值。
- remove(val):删除第一个匹配val的元素,没有返回值
- reverse():方向反转
- sort():无返回值,注意;sorted()函数返回排好列表;
- 高级排序,重写cmp(),sort(cmp)
-元组tuple:() 不可变序列
- 实现一个值的元组需要加逗号:eg : (42,)
- tuple() 函数:和list函数类似
- 除了创建,访问元组,没有太多操作。访问也可以用索引,切片。
第三章 使用字符串
- 基本字符串和前面序列操作类似,但字符串是不可变,初始化后就不能赋值。
- 字符串格式化:用% 实现 eg: print(‘Price of eggs $%d’ % 42)
- 常用方法:
-
find(val,start,end):在一个字符串里查找子字符串val,返回子串所在位置的最左端索引。没有找到返回-1.支持提供起点start,终点end。
-
val.join(list):将一个全是字符的list用val字符连接起来组成一个新的字符串。
-
lower():返回字符串小写字母版
-
replace(‘A’,‘B’):将字符串子串中’A’全部替换为’B’
-
‘str’.split(‘A’):是join的逆方法,用A将字符串str切割成序列。
eg:‘1+2+3+4+5’.split(’+’) >> [‘1’,‘2’,‘3’,‘4’,‘5’];
如果不提供分隔符,会默认空格作为分隔符. -
strip():返回除去字符串两侧空格后的字符串
-
translate(table): 需要先完成一张转换表:转换表是以某字符替换某字符的对应关系。
利用string里 maketrans():接收两个等长字符串的参数,表示第一个字符串每个字符都用第二个字符串中对应字符代替。
eg:
from string import maketrans table=maketrans('cs','kz') 'this is an incredibel test'.translate(table) >> 'thiz iz an inkredible tezt'
-
第四章:字典:当索引不好用时
-
字典创建:
- {} : phone={‘Alice’:‘123’,‘Bob’:‘110’}
- dict(): 用键值对(key,vaules)来建立字典
-
基本操作:和序列很多类似
- len()
- d[k]
- d[k]=v
- del d[k]
- k in d:检查字典d中含有键为k的项
-
字典的键类型为不可变元素,如整型,浮点型,字符串。
-
字典的格式化字符串:
phone={'Beth':'9102','Alice':'2341','Cecil':'3258'} print("Cecil's phone number is %(Cecil)s." % phone)
-
字典方法:
- clear()
- copy() :深复制
- get(key,value):访问一个不存在的健返回Node而不报错,而且可以修改权值。
- items iteritems:
- keys iterkeys: keys将字典键以列表形式返回
- values itervalues: values将字典值以列表形式返回,可以包含重复的元素
- pop(k): 将键值为k的从字典移除
- popitem():移出随机的项
- setdefault(key,value): 如果key不存就是添加,如果key存在,不修改返回原value.
- update(d): 用一个字典更新另一个字典,有相同的键会进行覆盖.
第五章 条件循环其他语句
-
print(,): 逗号隔开输出内容
-
import :导不同文件函数
-
赋值魔法:
-
序列解包(sequence unpacking):
- 多个赋值: x,y,z=1,2,3
- 交换两个变量: x,y=y,x
当函数或者方法返回元组(或其他序列,可迭代对象)时,这个特性很好用。同时所解包的序列中的元素数量必须和放置在赋值符号=左边的变量数量完全一致,否则报错。
-
链式赋值(chained assignment)是将一个值赋给多个变量的捷径(C++中不行)。eg: x=y=z;
-
增量赋值:x+=1
-
-
循环遍历字典元素:
- 并行迭代: 可以用序号或者zip压缩
eg: for name,age in zip(names,ages): - 编号迭代: 可以使用内建函数enumerate()
eg:
for index,string in enumerate(strings): if XXXXX: Strings[index]='XXXX'
- 并行迭代: 可以用序号或者zip压缩
-
循环外的else子句:神奇for里面有一个break循环下面的else就不执行,和C++不同。
eg:找100到81之间最大平方数是81,例子中81是开区间取不到。
for n in range(99,81,-1):
root = sqrt(n)
if root == int(root):
print(n);
break
else:
print("Didn't find it!")
-------> Didn't find it!
-
列表推导式-轻量级循环(list comprehension):
eg :[x*x for x in range(10)] -> [0,1,4,9,16,25,36,49,64,81]
能被3整除平方数: [x*x for x in range(10) if x%3==0] -> [0,9,36,81]
元组也行:[(x,y) for x in range(3) for y in range(3)] -> [(0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2,0),(2,1),(2,2)]
-
pass :什么都不做,可以作为占位符
-
del:用来删除变量或者数据结构一部分
-
exec(str):用字符串执行python语句 eg:
exec("printf('Hhello world')")
-
eval: 用于执行python求值语句,会有一个返回值。 eg:
print(eval(input("")))
第六章 抽象
-
创建函数:def
def fibs(nums): '文档字符串' result=[1,1] for i in range(nums-2): result.append(result[-2]+result[-1]) return result
文档字符串访问可以用 fibs.__doc __ 也可以用内建函数help()
-
参数魔法:
-
修改参数:传入参数是否被修改取决于该类型是否为可修改类型,如字符串,整形等不能修改,list,dict等都可以被修改:
eg:def init(data): data['first']={} data['middle']={} data['last']={} def lookup(data,label,name): return data[label].get(name) def store(data,full_name): names=full_name.split() if len(names)==2:name.insert(1,' ') labels='first','middle','last' for label,name in zip(labels,names): people=lookup(data,label,name) if people: people.append(full_name) else: data[label][name]=[full_name]
-
关键字参数和默认值:调用函数时候,指定哪个形参值是什么,不用考虑位置对齐的问题。
-
收集参数:星号* 意思是收集其余位置参数放在元组里。
eg:def print_params(title,*params): print(title) print(params) if __name__ == '__main__': print_params('Params',1,2,3) ---> Params (1, 2, 3)
- 处理关键字参数的收集:两个 ** 关键字参数放在字典里
def print_params(**params): print(params) if __name__ == '__main__': print_params(x=1,y=2,z=3)
- 处理关键字参数的收集:两个 ** 关键字参数放在字典里
-
-
-
递归:
- 二分(返回序列里第一个等于位置,不存返回None):
非递归版:def search(sequence,number,lower=0,upper=None): if upper==None: upper=len(sequence)-1 if upper<lower: if sequence[lower]==number : return lower else : return None; middle=int((lower+upper)/2); if sequence[middle]>=number: return search(sequence,number,lower,middle-1); else : return search(sequence,number,middle+1,upper);
def search2(sequence,number,lower=0,upper=None): if upper==None : upper=len(sequence)-1 while lower<=upper: middle=int((upper+lower)/2) if sequence[middle]>=number:upper=middle-1; else:lower=middle+1 if sequence[upper+1] != number: return None else: return upper+1
- 二分(返回序列里第一个等于位置,不存返回None):
第七章 更加抽象
-
创建自己的类:
class Person: def setName(self,name): self.name=name def getName(self): return self.name def greet(self): print("Hello,world! I'm %s." % self.name) def __inaccessible(self): print("Bet you cann't see me") def accessible(self): print("The secret messsage is:") self.__inaccessible() if __name__ == '__main__': p1=Person() p1.setName('yexiaoju') p1.greet() p1.accessible() p1._Person__inaccessible()
-
python并不直接支持私有方式,为了让方法或者特性变为私有(从外部无法直接访问),只要在它的名字前面加上双下划线即可。如上面例子。需要访问__inaccessible()方法,得加_类名+方法。
第八章:异常
Python 用异常对象(exception boject)来表示异常情况。遇到错误后,会引发异常。如果异常对象并未被处理或捕捉,程序就会被所谓的回溯终止执行。
- 捕捉异常(try/except):
while True:
try:
x=int(input('Enter the first number:'))
y=int(input('Enter the second number:'))
print(x/y)
except ZeroDivisionError:# 除0异常
print("The second number can't be zero!")
except TypeError:#输入类型异常
print("That wasn't a number !")
except:#捕捉所有上面漏掉的异常
print('There is something wrong!')
上面例子不止一个except,如果有异常会捕捉对应类型去接受,这里有ZeroDi…和TypeError两种.也可以用一个块去捕捉多个异常。用元组将他们列出:
except(ZeroDivisionError,TypeError,NameError):
就算程序处理好几种类型的异常,但是还是有异常会漏掉,像上面例子最后一个except:没有表明捕捉什么类型异常就是捕捉所有异常。
- raise 语句:引发异常,可以用一个Exception异常类或者自定义异常来被raise调用。 eg: raise Exception
- 自定义异常:继承EXception
class MyException(Exception):
def __init__(self,message):
Exception.__init__(self)
self.message=message
if __name__ == '__main__':
a = int(input("please input a num:"))
if a < 10:
try:
raise MyException("my excepition is raised ")# 引发自定义异常,进入下面的except模块里
except MyException as e:
print(e.message)
-
raise 不带参数:相当于没有异常处理,又抛出这个异常信息。
下面一个例子显示一个switch控制异常是否屏蔽的机制。class MufiedCalcul: switch=False def cal(self,expr): try: return eval(expr) except ZeroDivisionError: if self.switch: print("Division by zero is illege") else : raise
-
万事大吉(try/except/else):
- 异常没有发生执行一段代码,可以在后面加一个else。
- 不知道异常信息也可以打印出来。
while True:
try:
x=int(input('Enter the first number:'))
y=int(input('Enter the second number:'))
print(x/y)
except Exception as e:
print("Invalid input:",e)
print("please try again!")
else:
print("No Error,Quit!")
break
-
最后finally:它可以用来可能的异常后进行清理。
try: 1/0; except ZeroDivisionError: print("Unknow variable") else: print("That went well") finally: print("OK?")
不管异常有没有执行,最后finally一定会执行。
-
异常会递归回溯到直到函数调用的那一层。
-
异常之禅:有些时候在判断字典或对象是否存在特性时,条件语句可以实现和异常处理一样的功能,两者各有千秋。
第九章:魔法方法,属性和迭代器
-
构造方法:init()
class FooBar: def __init__(self): self.somevar=42; if __name__ == '__main__': b=FooBar() print(b.somevar)
-
继承:新的类的构造方法需要初始化父类的构造方法,防止父类有些特性没有继承过来。具体方法使用super函数。
-
Super函数:超类(父类)函数
class Bird:
def __init__(self):
self.hungry=True;
def eat(self):
if self.hungry== True :
print('Aaaaah')
self.hungry=False
else : print("No,thanks!")
class SongBird(Bird):
def __init__(self):
super(SongBird, self).__init__()#super()也可以不带参数
self.sound="Squawk"
def sing(self):
print(self.sound)
if __name__ == '__main__':
sb=SongBird()
sb.eat()
sb.eat()
sb.sing()
-
基本序列和映射规则:
序列和映射是对象的集合,如果对象是不可变那么只有下面前两个魔法,如果可变则可以使用下面四个魔法:- __ len__(self): 返回数目
- __ gettitem__(self.key): 返回键值查询值,每次用索引查询都会调用这个方法
- __ settitem__(self.key,value): 根据索引属性key设置value
- __ delitem __(self,key): 删除
实践,创建一个可以修改的无穷序列。实现了gettitem,settitem两个方法,因为是无穷的没有实现len,del方法,故调用的话就是非法报错。
def checkIndex(key): if not isinstance(key,int): raise TypeError if key<0: raise IndexError class ArithmticSequence: def __init__(self,start=0,step=1): self.start=start self.step=step self.changed={} def __getitem__(self,key): checkIndex(key) try: return self.changed[key] except KeyError: return self.start+key*self.step def __setitem__(self, key, value): checkIndex(key) self.changed[key]=value if __name__ == '__main__': s=ArithmticSequence(1,2) print(s[4]) s[4]=1 print(s[4])
- 子类化列表,字典和字符串:
class CountList(list): def __init__(self,*args): super().__init__(*args) self.counter=0 def __getitem__(self, item): self.counter+=1 return super().__getitem__(item) if __name__ == '__main__': c1=CountList(range(10)) print(c1) del(c1[3:6]) print(c1) c1[2]+=c1[4] print(c1.counter) -------------------------------- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [0, 1, 2, 6, 7, 8, 9] 2
-
property 函数:
- 将类方法转换为只读属性
- 重新实现一个属性的setter和getter方法
eg:
class Rectangle:
def __init__(self):
self.width=0
self.height=0
def setSize(self,size):
self.width,self.height=size
def getSize(self):
return self.width,self.height
size=property(getSize,setSize)
if __name__ == '__main__':
r=Rectangle()
r.width=10
r.height=5
print(r.size)
r.size=150,100
- 迭代器__ iter__: __ iter__()返回一个迭代器(iterator),所谓迭代器就是具有__ next__(这个方法在调用时不需要任何参数)方法的对象。在调用next方法时,迭代器会返回它的下一个值。如果next方法被调用,但迭代器没有值可以返回,就会引起一个
class Fibs:
def __init__(self):
self.a=0
self.b=1
def __next__(self):
self.a,self.b= self.b,self.a+self.b
return self.a
def __iter__(self):
return self
if __name__ == '__main__':
f=Fibs()
for i in f:
if i >1000:
print(i)
break
迭代器实现了__ iter__方法,这个方法实际上返回迭代器本身。
- 从迭代器的到序列:用list构造方法显式的将迭代器转换为列表。
class TestIterator:
value = 0
def __next__(self):
self.value += 1
if self.value > 10:raise StopIteration
return self.value
def __iter__(self):
return self
if __name__ == '__main__':
ti=TestIterator()
print(list(ti))
-
生成器: 用普通函数定义的迭代器 yield
-
这一段初看书,我也不是很懂,知乎上这个回答 不错。
-
创建生成器:
def flatten(nested): for sublist in nested: for element in sublist: yield element
if name == ‘main’:
nested=[[1,2],[3,4]]
for num in flatten(nested):
print(num) -
递归生成器:
```python
def flatten(nested):
try:
for sublist in nested:
for element in flatten(sublist):
yield element
except TypeError:
yield nested
if name == ‘main’:
nested=[[1],2,[3,[4]]]]
for num in flatten(nested):
print(num)上面代码有一个问题,如果列表里是字符串对象,那它也是一个序列,是不会出现TypeError,所以修改一下需要对字符串判断。 ```python def flatten(nested): try: try:nested+'' except:pass else :raise TypeError for sublist in nested: for element in flatten(sublist): yield element except TypeError: yield nested if __name__ == '__main__': nested=['123',['yexiaoju'],'memeda'] for num in flatten(nested): print(num)
-
-
通用来说生成器主要是由生成器函数和生成器迭代器组成。
-
运用生成器编写递归问题:这一块我看了好久,输出中间变量才满满懂了一点。
def conflict(state,nextX):
nextY=len(state)
for i in range(nextY):
if abs(state[i]-nextX) in (0,nextY-i):
return True
return False
def queens(num,state=()): #运用生成器写(一段递归程序)八皇后问题
if len(state) ==num-1:
for pos in range(num):
if not conflict(state,pos):
yield (pos,)
else:
for pos in range(num):
if not conflict(state,pos):
for result in queens(num,state+(pos,)):
yield (pos,)+result
def queens2(num,state=()):#将上面程序稍微简化写法
for pos in range(num):
if not conflict(state,pos):
if len(state)==num-1:
yield (pos,)
else:
for result in queens2(num,state+(pos,)):
yield (pos,)+result
def prettyprint(solution):#将得到的八皇后结果模拟图像形象的输出
def line(pos,length=len(solution)):
return '.'*(pos)+'X'+'.'*(length-pos-1)
for pos in solution:
print(line(pos))
if __name__ == '__main__':
print(list(queens(8)))
print(len(list(queens(8))))
queens3(8)
import random
prettyprint(random.choice(list(queens(8))))
第十章:充电时刻
-
模块:import
- 使用dir:查看模块包含的内容
- __ all__():
- help(): 获取帮助文本
-
文档:__ doc__ 在线文档:http://python.org/doc
-
使用源代码: __ file__ eg:print(copy.__ file__)#输出文件本地路径,就可以查看文件代码
-
标准库:
- sys: 访问与python解释器联系紧密的变量和函数。
import sys print(' '.join(reversed(sys.argv[1:]))) #反序打印命令行参数
- os:提供访问多个操作系统服务的功能。
import os import webbrowser if __name__ == '__main__': #通过命令打开程序 os.system(r'D:\"CS 1.6"\"CS 1.6"\cstrike.exe') #文件夹名需要" " os.startfile(r'D:\CS 1.6\CS 1.6\cstrike.exe') # 接受一般的路径,含有空格也没有关系 webbrower.open('mryxj.github.io')#启动浏览器打开特定网站
- fileinput:
-
集合:set():
-
堆:heapq()
- heappush(heap,x):将x入堆
- heappop(heap):将堆中最小的元素弹出
- heapreplace(heap,x) :将堆中最小元素弹出,并将x入堆
- nlargest(n,iter): 返回iter中第n大的数
- nsamallest(n,iter):返回iter中第n小的数
from heapq import * from random import shuffle data=[1,2,3,4,5,6,7,8,9,10] shuffle(data) heap=[] for n in data: heappush(heap,n) heappush(heap,0.5) print(heap) ----> [0.5, 1, 2, 5, 3, 4, 9, 10, 8, 7, 6]
-
双端队列:
- append(x):右端增加一个元素x
- appendleft(x):左端增加一个元素x
- popleft(x): 左端删除一个元素x
- roate(x):将右边前x个元素整体移到左端
from collections import deque q=deque(range(5)) q.append(5) q.appendleft(6)
-
time:获取当前时间,操作时间和日期。
-
random:
- random(n):返回[0,n)之间随机数
- getrandbits(n):以长整型形式返回n个随机数
- uniform(a,b):返回随机数n,a<=n<b
- randrange():
- choice(seq):从序列seq中返回随意元素
- shuffile(seq[,random]):