PythonStudyNote

Python适合网络应用(网站、后台服务),日常小工具,管理员脚本任务等  
缺点是运行慢,代码不能加密(解释型语言都有这个问题,编译型没有)

输出:print()函数,可以接受多个字符串,用","隔开(遇到","会输出空格)
输入:input()函数,可以接收字符串参数作为输入提示语   x = input()  x 是字符串,如果输入的是数字可以转换:x = int(x)

变量本身类型不固定的语言称之为动态语言(Python),与之对应的是静态语言(在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错,如Java)

a = 'ABC'   Python解释器干了两件事情:
1、在内存中创建了一个'ABC'的字符串;
2、在内存中创建了一个名为a的变量,并把它指向'ABC'。
也可以把一个变量a赋值给另一个变量b,这个操作实际上是把变量b指向变量a所指向的数据
可以把任何数据都看成一个“对象”,而变量是程序中指向这些数据对象的,对变量赋值是把数据和变量给关联起来。对变量赋值x = y是把变量x指向真正的对象,该对象是变量y所指向的。随后对变量y的赋值不影响变量x的指向

字符编码:计算机内存中,统一使用Unicode编码,当要保存到硬盘或者需要网络传输时,就转换为UTF-8编码(可变长编码,节省空间)

Python字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes。
Python对bytes类型的数据用带b前缀的单引号或双引号表示:  
x = b'ABC'  
要注意区分'ABC'和b'ABC',前者是str,后者虽然内容显示得和前者一样,但bytes的每个字符都只占用一个字节。
encode:str->bytes  decode:bytes->str
格式化输入:print('%d-%2d' % (3, 1))  只有一个参数可以省略括号

列表和元组:
list:可变有序  e.g.: name = ['michael', 'mike', 'miky'] (可用索引访问,-1是最后一个元素 name[-2]:mike)
      追加元素到末尾:name.append('alex')   添加元素到指定位置:name.insert(2,'james')   删除末尾元素:name.pop()   删除指定位置元素:name.pop(2)   替换元素:name[2] = 'jack'
  list的元素可以不同类型
tuple:有序不可变,一旦初始化就不可修改(好处是安全,能用tuple就不用list)
       t = (1, 2)   定义只有一个元素的tuple要注意:t = (1, )


dict:使用键-值(key-value)存储,查找速度快(根据key算出value的存储位置,其他语言中也叫map)
      d = {'michael':98, 'mike':95}   删除:d.pop('mike')   获取value:d.get('michael')
  dict要占用大量的内存(空间换时间)  dict的key是不可变对象(对于不可变对象调用任意自身的方法都不会改变对象自身的内容,而是创建新的对象返回)
  
set:一组key的集合,不存value,key不能重复  
     两种创建方式:s = {'1','2','3'}  或者用list创建:list1 = ['1','2','3']  s = set(list1)
添加元素:s.add('4')   删除元素:s.remove('4')
set可以做交并差等集合的操作

函数:  
pass语句什么都不做,可以当做占位符
可以使用内置函数isinstance()检查传入函数参数的类型是否正确:  isinstance(x, (int,float))
函数可以返回多个值:return x,y   (实际上返回的是一个tuple (x,y),tuple的括号可以省略)
函数参数:
默认参数必须指向不变对象(比如:None) (不变对象的好处:不变对象一旦创建,对象内部的数据就不能修改,可以减少由于修改数据导致的错误。此外多任务环境下同时读取对象不必加锁)
*args是可变参数(传入任意个参数),接收的实际上是一个tuple (可以在list或者tuple前加'*'作为可变参数传参)
**kw是关键字参数(传入任意个含参数名的参数),接收的实际上是个dict(可以在dict前加'*'作为可变参数传参)
命名关键字参数(必须传入参数名):限制关键字参数的名字。 用'*'作为分隔符,'*'后面的参数视为命名关键字参数(如果函数定义中已有一个可变参数,后面不需加'*')


高级特性:
切片:L[0:3](取L的前三个元素,从0开始0可以省略,L[:3])  L[10:20:2](每隔2个取10-20的元素)    list、tuple和字符串都支持切片操作
迭代:通过collections模块的Iterable类型可以判断一个对象是否可迭代:isinstance(s, Iterable)
列表生成式:可以快速创建list生成式(代码简洁)
[x*x for x in range(1,6) if x % 2 == 0] = [4, 16]   [m+n for m in 'ab' for n in 'xy'] = [ax, ay, bx, by]   L = ['ABC', 'Hello'];[d.lower() for d in L if isinstance(d,str)] = ['abc', 'hello']
生成器(generator):一边循环一边计算的机制
g = (x * x for x in range(10))就是一个generator      可以通过next()方法获得generator的下一个返回值,直到抛出stopIteration错误(一般不用next()遍历,使用for循环(for循环本质也是调用next))
如果一个函数定义中包含'yield'关键字,这个函数就不再是一个普通函数,而是一个generator, generator跟函数的执行流程不同,每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次yield返回处执行
普通函数调用返回结果,generator函数'调用'返回一个generator对象


迭代器(Iterator):可被next()函数调用并不断返回下一个值  可isinstance('abc', Iterator)判断
可迭代对象(Iterable):可直接用于for循环的对象  可isinstance('abc', Iterable)判断  可用for循环的有以下几种:
1、集合数据类型,list、tuple、dict、set、str        ---(不是Iterator,可通过iter()函数获得一个Iterator对象) Iterator的计算是惰性的,只有在需要返回下一个数据时才会计算
2、generator,包括生成器和带yield的generator function

函数式编程:(允许把函数作为参数传入另一个函数,允许返回一个函数)
高阶函数:把函数作为参数传入的函数。函数式编程就是指这种高度抽象的编程范式    f = abs  f(-10)==>10   函数名就是指向函数的变量
map函数:参数一:函数  参数二(三...):多个iterable    返回一个Iterator     只有一个iterable,对iterable中每个元素调用参数一的函数   多个iterable,并行调用参数一的函数
reduce函数:参数一:函数(必须有2个参数)  参数二:iterable序列   返回计算结果   将函数作用在一个序列[x1,x2,x3,,,]上   reduce(f, [x1, x2, x3, x4]) ==> f(f(f(x1, x2), x3), x4)
filter()函数:参数一:函数  参数二:iterable   返回:Iterable   从一个序列中筛选出符合条件的函数
sorted()函数:参数一:Iterable  参数二(可省略):比较函数  参数三(可省略):用来进行比较的元素  参数四(可省略):排序规则 reverse=True/False


闭包:内部函数可引用外部函数的参数和局部变量,返回的函数中保存了相关的参数和变量
函数可以返回一个函数:返回函数时并未执行这个返回的函数(返回函数一定不要引用任何可能会变化的变量,如循环变量)
匿名函数:lambda x: x*x   ':'前是函数参数  只能有一个表达式   匿名函数时一个函数对象,可以赋值给一个变量
装饰器:代码运行期间动态增加功能的方式  @语法
偏函数:functools.partial创建偏函数   int2 = functools.partial(int, base=2)  把一个函数的某些参数固定,从而调用更简单


模块:一个.py文件就是一个模块,模块可以置于包目录下,每个包目录下有一个__init__.py文件(必须存在),否则Python将这个目录当成普通目录,而不是一个包
模块是对象,且所有的模块都有一个内置属性 __name__,__name__ 的值取决于如何应用模块。如果import一个模块,__name__的值通常为模块文件名,不带路径或者文件扩展名。也可以像一个标准程序样直接运行模块,此时__name__值缺省为"__main__"
作用域:模块中,有的函数或变量希望给别人用,有的希望仅在模块内使用,通过_前缀实现
正常的函数名或变量名是公开的(public),如abc,x1,PI等
类似__xxx__的变量是特殊变量,可被直接引用,但是有特殊用途如__name__
类似_xxx和__xxx的函数或变量是非公开的(private),不应该被直接引用(并不是不能)
通常一个第三方库都会在Python官方的pypi.python.org网站注册,知道库的名字就可以安装这个第三方库了
模块搜索路径:Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys模块的path变量中。  添加自己的搜索目录:sys.path.append('xxx') (运行时生效,运行结束后失效)  或者设置环境变量PYTHONPATH,该变量的内容会自动添加到模块搜索路径中


面向对象
__init__方法初始化一个实例对象,有了__init__方法创建实例的时候就不能传入空的参数了
类中的函数第一个参数必须是self,调用时不需要传递这个参数
变量名类似__xxx__的,即以双下划线开头且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以不能用__name__、__score__这样的变量名。
以一个下划线开头的实例变量名如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。
双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量。(不同的解释器可能解释成不同的名字)


静态语言如Java,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用run()方法
对于Python这样的动态语言,则不一定需要传入Animal类型。只需要保证传入的对象有一个run()方法就可以了
这就是动态语言的“鸭子类型”,并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子     动态语言的鸭子类型决定了继承不像静态语言那样是必须的
获取对象信息:
type()函数,instance()函数(优先使用instance)     dir()函数可以获得一个对象的所有属性和方法,返回一个包含字符串的list     getattr(),setattr(),hasattr()可以操作一个对象的状态
不要对类属性和实例类型使用相同的名字,如果相同实例属性会屏蔽掉类属性


定义class时,可定义__slot__变量来限制该class实例能添加的属性(仅对当前类起作用,对继承的子类不起作用)
@property可以让调用者写出简短的代码,同时保证对参数进行必要的检查   @property装饰器可以吧一个方法编程属性调用
class允许定义许多定制方法,可以非常方便的生产特定的类  __str__,_iter__,__getitem__,__getattr__,__call__
meteclass:创建类

错误处理:
当认为某些代码执行可能出错时,可用try来运行这段代码。如果执行出错,后续代码不执行,跳转至错误处理代码(except)处,执行完except后,如果有finally语句块则执行finally语句块
错误也是class,且所有的错误都继承自BaseException,except捕获错误时,将其子类也捕获
raise语句会抛出错误

调试:
通过导入logging使用logging语句,可以指定记录信息的级别,debug,info,warning,error,logging不会抛出错误,可以输出到文件(logging最强大)
python -m pdb xxx.py 通过pdb进行单步调试    pdb.set_trace()可以为程序设置断点


单元测试:导入unittest,编写一个继承unittest.Test的类,每一类测试都要写一个test_xxx()方法,然后使用内置的条件判断   unittest.main()运行单元测试    可以在单元测试中编写setUp()和tearDown()方法,会分别在每个测试方法前后被执行
文档测试:Python内置的doctest模块可以直接提取注释中的代码并执行


同步IO:等待IO执行完成,再接着执行
异步IO:不等待IO执行完成,而去做别的事情(性能高,但是编程模型复杂,如何通知IO完成)
文件读写
磁盘上读写文件都是由OS提供的,现代OS不允许普通程序直接操作磁盘,读写文件就是请求OS打开一个文件对象(称为文件描述符),然后通过OS提供的接口从这个文件对象读取数据或把数据写入这个文件对象
读文件:open()函数,read()方法一次读取文件全部内容到内存(用str表示),最后close()关闭文件(必须关闭,文件对象会占用OS资源,且OS同一时间打开的文件数量有限)
readlines()每次读取一行,按行返回list  read(size)最多读取size个字节的内容   文件小,则用read()一次性读取,文件大小不确定用read(size)保险,配置文件用readlines()最方便
写文件:open(),write(),close() 写文件时,OS不会立刻把数据写入磁盘,而是先放到内存缓存起来,空闲时再慢慢写入,只有调用close()方法时,OS才保证把没有写入的数据全部写入磁盘       
最好使用with语句操作文件IO    with语句是对try...except...finally语法的一种简化,并提供了对异常很好的处理方式(with所求值的对象必须有__enter__()和__exit()__方法)

StringIO和BytesIO是内存中操作str和bytes的方法,使得和读写文件具有一致的接口

操作文件和目录的函数在os模块和os.path模块中    将两个路径合成一个时,不要直接拼字符串,使用os.path.join()函数,可以处理不同OS的路径分隔符    拆分路径使用os.path.split()函数    os.path.splitext()可以直接得到文件扩展名     shutil模块也有很多实用的函数,可看做是os模块的补充

pickle模块实现序列化操作:pickle.dumps()将任意对象序列化成一个bytes,pickle.loads()将bytes反序列化出对象,pickle.load()从一个file-like Object中直接反序列化出对象
json模块提供对象到JSON格式的转换:json.dumps()返回一个str,内容是标准的JSON  loads()吧JSON字符串反序列化,load()从一个file-like Object中读取字符串反序列化

进程线程:
os模块封装了常见的系统调用,包括fork,可以创建进程,不能再Windows上调用   multiprocessing模块是跨平台的多进程模块,提供一个Process类代表一个进程对象,需要传入一个函数和函数的参数   通过start()启动进程,join()方法等待子进程结束后继续往下执行,通常用于进程间同步
如果要启动大量的子进程,可以用进程池批量创建子进程   对Pool对象调用join()会等待所有子进程执行完毕,调用join()前必须调用close(),调用close()后就不能继续添加新的Process了    subprocess模块可以方便的启动一个子进程,控制其输入输出
进程间通信:multiprocessing模块封装了底层的机制,提供了Queue、Pipes等方式来交换数据

Python的线程时真正的Posix thread,而不是模拟出来的线程
_thread是低级模块,threading是高级模块,对_thread进行了封装,大多数情况下用threading模块    启动一个线程就是创建一个Thread实例,传入一个函数,调用start()开始执行
多进程中对于同一个变量,每个进程各自有个拷贝,互不影响,但是多线程中所有变量都由所有线程共享,所以多线程同时操作一个变量需要加锁,通过threading.lock()实现
Python解释器(CPython)执行代码时有一个GIL(Global Interpreter Lock)锁,Python线程执行前必须先获得GIL锁,然后每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。
ThreadLocal虽然是全局变量,但是每个线程都只能读写自己线程的独立副本,互不干扰,解决了参数在一个线程中各个函数间互相传递的问题
multiprocessing模块的子模块managers支持把多进程分布到多台机器上

网络编程:
socket表示打开一个网络连接,打开一个socket需要知道目标计算机的IP地址和端口号,再指定协议类型
客户端:创建一个socket,然后connect,send发送数据,recv接收数据,最后close关闭socket
服务端:创建一个socket,bind绑定监听地址和端口,listen监听端口,accept等待并返回一个客户端的连接(会返回一个socket和address,通常开一个线程去处理这个连接,send发送数据,recv接收数据,close关闭socket)


协程:看上去是子程序,但执行过程中,在子程序内部可中断,转而执行别的子程序,在适当的时候再返回来接着执行
协程是一个线程执行,执行效率高,没有现场切换开销,也不需要锁机制             Python对协程的支持是通过generator实现的(yield不但可以返回一个值,还可以接收调用者发出的参数)
https://blog.csdn.net/soonfly/article/details/78361819
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值