python学习之路 - littleboy12580/learning_python GitHub Wiki

python的核心数据结构

python是动态类型的,因此不存在变量类型声明

常见数据

数字

1.“/”运算符得到的一定是浮点数,就算两个整数相除其得到的也是浮点数 5/1=5.0 想要得到整数要用“//”,得到的是商(负数则是向下取整);“%”得到的是余数

2.乘方用“**”表示而不是用“^”

字符串

1.字符串内部有‘或者’‘时,可以用转义字符\,另外r' '表示' '内部的字符串默认不转义。

2.python中可以用'''...'''的形式来表示多行内容,r对这个无影响。

3.ord():将字符转换为ascii码的数字;chr():将数字转为字符。

4.在python中字符串是不可变的,但我们可以通过建立一个新的字符串并命名为和原字符串相同的名字来对其进行赋值(此时最初的字符串会被抹去)

5.字符串的格式化调用方法:

'{a},{0} and {b}'.format(42,a='lala',b=[1,2])

空值

1.为None,并不意味着未定义,它是某些内容而不是没有内容,是一个真正的对象并且有一块内存。

2.在列表中,可以通过None提前分配一个N项的列表,这样以后通过索引赋值就不会出现索引不存在的情况了,例如:

L=[None]*100

在这种情况下列表L就会有一个初始大小,可以向0~99的索引赋值了

序列(list)

1.list[0]表示左边第一个元素,list[-1]表示右边第一个元素。

2.使用pop()方法删除末尾元素,使用pop(index)删除指定位置元素,使用remove(value)移除指定值元素 使用append(value)在表尾添加一个元素,使用insert(index)在指定位置添加元素,使用index(i)返回i值的索引,若没有会报一个值错误。

3.list没有固定大小,list里的元素类型也可以各不相同。

4.list[X:Y:J]表示从X开始到Y之前结束(不包括Y),每J个取一次;当J为负数时表示倒序,那时上下边界也需要进行反转。

元组(tuple)

1.tuple一旦初始化就不能被修改。

2.只有一个元素的tuple需要定义成t=(1,)而不能定义成(1),否则结果是1。

字典

1.通过键值对的映射来进行存储。

2.d.get('sss',-1),查找字典里的某个key值‘sss’,如果找不到返回-1,如果找到返回该key值对应的值。

3.字典与格式化输出可以进行结合,如:

"%(age)d %(food)s" % values  

其中values为字典,age与food为字典里的键;也可以通过vars()函数替代values。

4.字典解析:一般用来初始化创建一个新字典,例如:

    D={x:x**2 for x in [1,2,3,4]}; 
    D={k:v for(k,v) in zip(['a','b','c'],[1,2,3])}

5.在python3.0以上,D.keys()现在返回的是一个视图而不是列表,若想变成列表需要用list(D.keys())进行转换;values()函数也是一样。

6.字典键排序有两种方式:

第一种是:

    Ks=D.keys();
    ks=list(Ks)
    ks.sort()        #不返回列表

第二种是:

    Ks=D.keys();
    sorted(Ks)       #返回排序好了的列表

也可以直接sorted(D),返回的同样是排序好了的键值列表

7.在python3.0中字典的大小比较被删除了,若要比较字典的大小需要用sorted(),即

    sorted(D1.items())<sorted(D2.items())

文件

1.文件的创建:

    f=open('data.txt','w')

第一个参数为文件名与格式,第二个参数为用户对文件的操作权限。

文件的按行读取一般不使用f.readline()方法,而是用文件迭代器,例如:

    for line in open('data'):
        print(line,end='')

2.从文件读取的数据回到脚本时是一个字符串,因此如果字符串不是我们需要的数据类型,我们需要自己去转换类型;往文件里写数据的时候,文件也不会自动的将数据转换为字符串格式,同样需要我们自己将数据进行字符串格式化。

3.文件上下文管理器:通过try/finally语句或者with/as语句来确保文件在退出后可以自动关闭。(一般情况下python的垃圾收集功能会在对象没有引用的时候自动回收,即会自动关闭文件,但不确定时间,通过上面两种语句可以控制文件的关闭。)

可变性与不可变性

在python中的每一个对象都可以分为不可变形或可变性,在常见数据中不可变的有:数字,字符串与元祖;可变的为:列表和字典。

实用的内置函数

dir(type)

列出该数据类型的所有操作方法,获取模块内所有可用变量名。 ##help(type.func) 说明python内置函数的作用。 ##enumerate(nums) 遍历函数,能够同步遍历列表的序号与对象,例如:

    for index,value in enumerate(nums)。

##zip([seql, ...]) 接受一系列可迭代对象作为参数,将对象中对应的元素打包成一个个tuple(元组),然后返回由这些tuples组成的list(列表)。若传入参数的长度不等,则返回list的长度和参数中长度最短的对象相同。例如

    z1=[1,2,3]  
    z2=[3,4,5,6]

则zip(z1,z2)返回的是

    result=[(1,3),(2,4),(3,5)]

zip()配合*作用为解压,例如

    zip(*result)=[(1,2,3),(3,4,5)]

##pickle模块 pickle模块能够让我们直接在文件中存储几乎任何Python对象,能够用于文件的写入与读取。

    D={'a':1,'b':2}
    F=open('datafile.pk1','wb')
    import pickle
    pickle.dump(D,F)
    F.close()
    F=open('datafile.pk1','rb')
    E=pickle.load(F)

使用dump与load可以进行对象和字节字符串之间的相互转换 ##struct模块 struct模块能够构造并解析打包的二进制数据,能够用于二进制文件的写入与读取

    F=open('data.bin','wb')
    import struct
    data=struct.pack('>i4sh',7,'spam',8)
    F.write(data)
    F.close()
    F.open('data.bin','rb')
    values=struct.unpack('>i4sh',data)

通过pack()和unpack()进行写入与读取,其中,函数第一个参数表示格式字符串的信息

下面是格式字符串的一些字符含义

格式符 C语言类型 Python类型
x pad byte no value
c char string of length 1
b signed char integer
B unsigned char integer
? _Bool bool
h short integer
H unsigned short integer
i int integer
I unsigned int integer or long
l long integer
L unsigned long long
q long long long
Q unsigned long long long
f float float
d double float
s char[] string
p char[] string
P void * long
Character Byte order Size Alignment
@ native native native
= native standard none
< little-endian standard none
> big-endian standard none
! network (= big-endian) standard none
##next()函数 next(X)相当于X.__next__,会自动调用一个对象的__next__方法;对于列表之类的不是自身的迭代器的对象需要先调用iter(X)函数来启动迭代。 ##map()函数 实现对一个序列对象中的每一个元素应用被传入的函数 ```python counters = [1,2,3,4] list(map((lambda x:x+3),counters)) ``` 最后的结果为[4,5,6,7] ```python pow(3,4) #3^4,结果为81 list(map(pow,[1,2,3],[2,3,4])) ``` 最后的结果为[1,8,81] ##filter()函数 实现从一个序列中过滤出符合特定条件的元素 ``` list(filter((lambda x: x>0),range(-5,5)))) ``` 将lambda生成的函数应用到range产生的每个元素上,筛选出那些函数返回结果为TRUE的元素

#Python语句 ##try语句处理错误

try:
    pass     #主要代码块
except:
    pass     #异常处理代码
else:
    pass     #没有异常的时候执行的代码
finally:
    pass     #无论是否发生异常都会执行的代码

##赋值语句 ###序列赋值运算 1.元组赋值

A,B=nudge,wink

2.列表赋值

[C,D]=[nudge,wink]

3.Python3.0有一种新的序列赋值

a,*b = 'spam'

其结果是a被赋值's',b被赋值p['p','a','m']

若没有剩下的内容可以匹配带*的名称,则会赋值一个空的列表

a,b,c,d,*e = [1,2,3,4]
print(a,b,c,d,e)

此时的结果为 1 2 3 4 []

若有多个带*的名称,则会报错

a,*b,c,*d = [1,2,3,4]

会报错

若带*的名称自身没有编写到一个列表中也会报错

*a = [1,2,3,4]

会报错,正确的写法应该是:

*a, = [1,2,3,4]

###多目标赋值 把右侧的对象赋值给所有提供的变量名,但是要注意不可变对象和可变对象的区别

a = b = 0
b = b + 1

此时a,b的值分别为0和1

a = b = []
b.append(42)

此时a,b的值分别为[42],[42] ###增强赋值 增强赋值并不是合并,它是对原处进行修改

L=[1,2]
M=L
L=L+[3,4]

此时的L,M分别为[1,2,3,4]和[1,2]

L=[1,2]
M=L
L+=[3,4]

此时的L,M分别为[1,2,3,4]和[1,2,3,4] ##打印操作语句

print([object,...][,sep=' '][,end='\n'][,file=sys.stdout])

object表示要打印的内容,sep表示打印内容间的分隔字符串,end表示打印结束后在文本末尾添加的一个字符串,file指定文本将要发送到的文件

print(x,y,z,sep='...',end='\n',file=open('data.txt','w'))

##判断语句 ###字典实现switch效果 在python中没有switch或case语句,但可以通过字典来达到同样的效果

branch = {'spam':1.25
          'ham':1.99
          'eggs':0.99}
print(branch.get('spam','Bad choice'))

或者是

choice = 'bacon'
if choice in branch:
    print(branch[choice])
else:
    pass

###三元表达式

A = Y if X else Z

当X为真时执行Y否则执行Z ##循环语句 1.break:跳过整个循环语句

2.continue:跳到循环开头

3.循环else块:当循环正常离开时才会执行(即没有碰到break语句) ##列表解析语句 解析语句可以通过加入if判断,双层for循环进行嵌套

lines = [line.rstrip() for line in open('script1.py') if line[0] == 'p']

这句话相当于

res=[]
for line in open('script1.py'):
    if line[0] == 'p':
        res.append(line.rstrip())
[(x,y) for x in range(5) if x % 2 == 0 for y in range(5) if y % 2 == 1]

最后的结果为[(0,1),(0,3),(2,1),(2,3),(4,1),(4,3)] ##迭代器 range()支持多个迭代器,zip(),map(),filter()只支持单个迭代器 #函数 ##作用域

  • 作用域可以分为本地作用域与全局作用域
  • 内嵌的模块是全局作用域
  • 全局作用域的作用范围仅限于单个文件
  • 在原处改变对象并不会把变量划分为本地变量,只有对变量名赋值才可以;例如L.append(X)语句不会将L划分为本地变量,而L = X却可以。 ##变量的LEGB作用域查找原则 当引用一个变量时,Python会按以下顺序依次进行查找:首先是在本地变量中查找,然后在任意上层函数作用域里查找,再然后是全局作用域,最后则是在内置作用域查找。 ##global语句 通过global声明可以将一个变量变为全局变量
X = 88
def func():
    global X
    X = 99
func()
print(X)

此时X值为99 ##文件间的调用修改 在导入模块之后,被导入模块的全局变量属性是可能会被修改的,如下例:

#first.py
X=99
#second.py
import first
print(first.X)
first.X = 88

这种文件依赖性过强的情况会导致代码不灵活,因此在文件间通信最好的办法是通过调用函数,传递参数,然后得到其返回值,如下例:

#first.py
X=99
def setX(new):
    global X
    X = new
#second.py
import first
first.setX(88)
##参数的引用
python中函数参数是通过赋值传递的函数中的参数名可以在调用时通过变量实现共享对象因此函数中的可变对象参数的原处修改是可以影响到调用者的就相当于C语言里的指针传递一样而不可变对象参数即使进行了原处修改也不会影响到调用者相当于值传递##参数的匹配扩展
###参数收集
参数收集有两种***

*在函数定义中表示在元组中收集不匹配的位置参数
```python
def f(*args): print(args)
f(1)
f(1,2,3,4)

上面代码最后输出的是(1,)和(1,2,3,4)

**在函数定义中只对关键字参数有效,它将关键字参数传递给一个新的字典

def f(**args): print(args)
f(a=1,b=2)

上面代码最后输出的是{'a':1,'b':2}

函数头部能够混合一般参数,*参数以及**参数来实现更加灵活的调用方式

def f(a,*pargs,**kargs): print(a,pargs,kargs)
f(1,2,3,x=1,y=2)

上面代码最后输出的是 1 (2,3) {'y':2,'x':1} ###解包参数 与参数收集相对应,在调用参数的时候也能够使用*和**语法,此时是将传入的参数解包成不同的参数

def func(a,b,c,d): print(a,b,c,d)
args = (1,2,3,4)
func(*args)

上面代码结果为1 2 3 4

args = {'a':1,'b':2,'c':3,'d':4}
func(**args)

上面代码结果为 1 2 3 4

func(*(1,2),**{'d':4,'c':4})
func(1,c=3,*(2,),**{'d':4})

上面代码结果为1 2 4 4和1 2 3 4 ###参数排序规则 在一个函数头部,keyword-only参数必须编写在**args之前,*args之后 ##lambda表达式 lambda表达式创建了一个之后能够调用的函数,但是它返回了一个函数而不是将这个函数赋值给了一个变量名。

f=lambda x,y,z:x+y+z
f(2,3,4)

默认参数也能够在lambda参数中使用

x=(lambda a="fee",b="fie",c="foe":a+b+c)
x("wee")

输出为'weefiefoe'

##生成器函数

  • 送回一个值并随后从其退出的地方继续的函数叫做生成器函数;它通过yield表达式來挂起函数并香调用这发送回一个值,但是保留足够的状态以使得函数能够从它离开的地方继续。
  • 生成器函数返回的是生成器对象,他支持迭代器协议,存在__next__()方法
def gensquares(N):
    for i in range(N):
        yield i ** 2
for i in gensquares(5):
    print(i,end=' : ')

最后的输出为 0 : 1 : 4 : 9 : 16 :

  • 生成器表达式:与列表解析类似不过是括在圆括号中而不是方括号中
(x ** 2 for x in range(4))

返回的是一个可迭代对象而不是列表

  • 生成器函数与生成器表达式均支持自动迭代和手动迭代,手动迭代需要使用iter()函数来启动迭代,然后使用next()进行迭代

  • 生成器是单迭代对象 ##解析表达式 python3.0中可用的4种解析表达式形式:列表解析,生成器表达式,集合解析以及字典解析

  • 列表解析

[x * x for x in range(10)]
  • 生成器表达式
(x * x for x in range(10))
  • 集合解析
{x * x for x in range(10)}
  • 字典解析
{x:x * x for x in range(10)}

#自己碰到的问题 1.交互模式下输入多行语句时需要进行缩进,否则会提示错误。

2.表达式1==2<3表示的意思是“1==2 and 2<3”。

3.在python中一些小的数字与字符对象在没有引用的时候并不会被回收而是会对这些对象进行缓存复用,等待下一次代码再次生成另一个相同对象来重复利用。因此有如下实例: X=42 Y=42 X==Y
输出的是TRUE X is Y 输出的也是TRUE

4.在python中“+”表达式不能混合数字与字符串,例如‘abc’+9是会抛出错误的。

5.无条件分片X[:]与字典的copy()方法只能做到顶层复制,即他们不能复制嵌套的数据结构;要实现深度拷贝需要导入标准的copy模块(即import copy),并用语句 X=copy.deepcopy(Y)来实现对任意嵌套对象Y进行完整的复制。

6.Python 会缩放分片限制值,所以L[3:1]相当于L[3:3],若有

    L=[1,2,3,4]
    L[3:1]=['?']

则最后L的输出为

    [1,2,3,'?',4]

7.把空列表赋值给一个索引,会将空列表的对象保存在这里;但是若把空列表赋值给一个分片,则会删除该分片。例如:

    L=[1234]
    L[2]=[]

此时的L为

    [1,2,[],4]

而如果采用分片形式,如

    L[2:3]=[]

则此时的L为

    [1,2,4]

8.当元组或列表出现在赋值符号(=)两边时,Python会根据左右两侧对象的位置把右侧对象赋值给左边目标。例如:

    X=SPAMY=EGGSXY = YX

此时的X值为‘EGGS’,Y的值为‘SPAM’

9.在Python中,map调用比等效的for循环要快两倍,而列表解析往往比map调用要稍快一些。

⚠️ **GitHub.com Fallback** ⚠️