Python语言

 一、数据类型

Python3 教程 | 菜鸟教程 (runoob.com)

二、基本函数

1、while和for后面并列一个else表示当循环条件不满足时执行该语句。

2、pass 语句表示只占位置不做任何操作

3、迭代器
迭代器有两个基本的方法:iter() 和 next()。

字符串,列表或元组对象都可用于创建迭代器;通过两种方法的使用或for的方式遍历迭代器里面的数据:

在这里插入图片描述

 触发 StopIteration 异常来结束迭代:

在这里插入图片描述

4、生成器:其实就是返回一个迭代器。
使用了 yield 的函数被称为生成器(generator)。

在这里插入图片描述

5、函数
(1)、不带表达式的return相当于返回 None。
(2)、参数传递
在 python 中,类型属于对象,变量是没有类型的:
a=[1,2,3]
a=“Runoob”
等号左边是变量,没有类型;等号右边是对象,有类型。变量仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象。

可更改(mutable)与不可更改(immutable)对象
在 python 中,strings,numbers , tuples是不可更改的对象,而 list,dict 等则是可以修改的对象。

不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a。

可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

python 函数的参数传递:

不可变类型:类似 c++ 的值传递 ,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。

可变类型:类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的对象传过去,修改后fun外部的la也会受影响

(3)、不定长参数

 在这里插入图片描述

在这里插入图片描述

 在这里插入图片描述

 在这里插入图片描述

6、匿名函数
lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。 

在这里插入图片描述

7、闭包(直白的说,闭包就是对内部函数的引用)
我们可以将闭包理解为一种特殊的函数,这种函数由两个函数的嵌套组成,且称之为外函数和内函数,外函数返回值是内函数的引用,此时就构成了闭包。 

在这里插入图片描述

8、变量作用域 

在这里插入图片描述

好啦,图书馆快打烊了。今天就到这里。

 三、面向对象

类与继承

#!/usr/bin/python3
 
#类定义
class people:
    #定义基本属性
    name = ''
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))
 
# 实例化类
p = people('runoob',10,30)
p.speak()
执行以上程序输出结果为:
 
runoob 说: 我 10 岁。

类的单继承

#!/usr/bin/python3
 
#类定义
class people:
    #定义基本属性
    name = ''
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))
 
#单继承示例
class student(people):
    grade = ''
    def __init__(self,n,a,w,g):
        #调用父类的构函
        people.__init__(self,n,a,w)
        self.grade = g
    #覆写父类的方法
    def speak(self):
        print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
 
 
 
s = student('ken',10,60,3)
s.speak()
执行以上程序输出结果为:
 
ken 说: 我 10 岁了,我在读 3 年级

类的多继承

#!/usr/bin/python3
 
#类定义
class people:
    #定义基本属性
    name = ''
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))
 
#另一个类
class speaker():
    topic = ''
    name = ''
    def __init__(self,n,t):
        self.name = n
        self.topic = t
    def speak(self):
        print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
 
#多重继承
class sample(speaker,student):
    a =''
    def __init__(self,n,a,w,g,t):
        student.__init__(self,n,a,w,g)
        speaker.__init__(self,n,t)
 
test = sample("Tim",25,80,4,"Python")
test.speak()   #方法名同,默认调用的是在括号中排前地父类的方法
执行以上程序输出结果为:
 
我叫 Tim,我是一个演说家,我演讲的主题是 Python

类的属性与方法 

类的方法

在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数,self 代表的是类的实例。self 的名字并不是规定死的,也可以使用 this,但是最好还是按照约定是用 self。

类的私有方法

__private_method:两个下划线开头,声明该方法为私有方法,只能在类的内部调用 ,不能在类的外部调用。self.__private_methods。

类的私有属性

__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。

类的专有方法

__init__ : 构造函数,在生成对象时调用
__del__ : 析构函数,释放对象时使用
__repr__ : 打印,转换
__setitem__ : 按照索引赋值
__getitem__: 按照索引获取值
__len__: 获得长度
__cmp__: 比较
__call__: 函数调用
__add__: 加
__sub__: 减
__mul__: 乘
__truediv__: 除
__mod__: 求余
__pow__: 乘方

方法的重写(复写)

#!/usr/bin/python3
 
class Parent:        # 定义父类
   def myMethod(self):
      print ('调用父类方法')
 
class Child(Parent): # 定义子类
   def myMethod(self):
      print ('调用子类方法')
 
c = Child()          # 子类实例
c.myMethod()         # 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法
 
# super() 函数是用于调用父类(超类)的一个方法。
# 执行以上程序输出结果为:
 
调用子类方法
调用父类方法

在Pycharm中使用类

导包

调用另一个类的方法

四、正则

基础

1、点号“ . ”

一个点表示除了换行符(\n)以外的任意一个字符。

2、星号“ * ”

一个星号表示他前面的一个表达式的0次到无限次。

3、问号“ ?”

一个问号表示英文问号表示他前面的一个表达式的0次或1次。

4、(.*?)和(.*)的区别

只要是a开头y结尾,切断当第一个元素,继续找a开头y结尾的字符串。

 

a开头遇到第一个y结尾的并没有立即切断,而是继续找下一个y,直到最后一个y时才切断。 

将上面两个表达式括起来表示不要括号外面的数据,只返回括号里边的数据。 

5、反斜杠“ \ ”

转义,将特殊含义的字符转成普通字符;将普通字符转为特殊字符。

如:我的密码是*123456*不包括星号。

上面的这么写:我的密码是*.**不包括星号。// 错误

上面的这么写:我的密码是\*.*\*不包括星号。// 将斜杠放在字符前面就不具有特殊含义了

\\n     :此时失去了换行的特殊含义。

6、数字“ \d ”

一个\d表示一个数字,以此类推。

如:我的密码是*123456*不包括星号。

我的密码是\*\d*\*不包括星号。 // \d是个整体表示一个数字,紧跟着结合后面的*表示匹配0到无限多个数字。

7、小括号“ () ”

表示把括号里的内容提取出来。

如:我的密码是:123456abcde你帮我记住。

:.*?你      结果是    :123456abcde你  // 不满足需求

:(.*?)你      结果是    123456abcde       // 成立

8、其他符号


实例 

高级

1、re.match(正则式, 字符串, 修饰符)

re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

修饰符:

#!/usr/bin/python3
import re
 
line = "Cats are smarter than dogs"
# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
 
if matchObj:
   print ("matchObj.group() : ", matchObj.group(0))
   print ("matchObj.group(1) : ", matchObj.group(1))
   print ("matchObj.group(2) : ", matchObj.group(2))
else:
   print ("No match!!")

以上实例执行结果如下: 

matchObj.group() :  Cats are smarter than dogs
matchObj.group(1) :  Cats
matchObj.group(2) :  smarter

2、re.search(正则式, 字符串, 修饰符)

从头到尾匹配成功re.search方法返回一个匹配的对象,否则返回None。

group(index)       // 返回对应下标的值

groups()             // 返回所有值

import re
 
line = "Cats are smarter than dogs";
 
searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I)
 
if searchObj:
   print ("searchObj.group() : ", searchObj.group())
   print ("searchObj.group(1) : ", searchObj.group(1))
   print ("searchObj.group(2) : ", searchObj.group(2))
else:
   print ("Nothing found!!")

以上实例执行结果如下:

searchObj.group() :  Cats are smarter than dogs // 返回的是整个匹配串
searchObj.group(1) :  Cats       // 返回的是子串之一
searchObj.group(2) :  smarter       // 返回的是子串之二

3、re.match()与re.search()区别

re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

import re
 
line = "Cats are smarter than dogs";
 
matchObj = re.match( r'dogs', line, re.M|re.I)
if matchObj:
   print ("match --> matchObj.group() : ", matchObj.group())
else:
   print ("No match!!")
 
matchObj = re.search( r'dogs', line, re.M|re.I)
if matchObj:
   print ("search --> matchObj.group() : ", matchObj.group())
else:
   print ("No match!!")

以上实例运行结果如下:

No match!!
search --> matchObj.group() :  dogs

4、re.sub(pattern, repl, string, count=0, flags=0)

Python 的re模块提供了re.sub用于替换字符串中的匹配项。

参数:

pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
flags : 编译时用的匹配模式,数字形式。
前三个为必选参数,后两个为可选参数。

import re
 
phone = "2004-959-559 # 这是一个电话号码"
 
# 删除注释
num = re.sub(r'#.*$', "", phone)
print ("电话号码 : ", num)
 
# 移除非数字的内容
num = re.sub(r'\D', "", phone)
print ("电话号码 : ", num)

以上实例执行结果如下:

电话号码 :  2004-959-559 
电话号码 :  2004959559

repl 参数是一个函数

以下实例中将字符串中的匹配的数字乘于 2:

import re
 
# 将匹配的数字乘于 2
def double(matched):
    value = int(matched.group('value'))
    return str(value * 2)
 
s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))

执行输出结果为:

A46G8HFD1134

5、compile(pattern[, flags])

compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。

>>>import re
>>> pattern = re.compile(r'\d+')                    # 用于匹配至少一个数字
>>> m = pattern.match('one12twothree34four')        # 查找头部,没有匹配
>>> print m
None
>>> m = pattern.match('one12twothree34four', 2, 10) # 从'e'的位置开始匹配,没有匹配
>>> print m
None
>>> m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,正好匹配
>>> print m                                         # 返回一个 Match 对象
<_sre.SRE_Match object at 0x10a42aac0>
>>> m.group(0)   # 可省略 0
'12'
>>> m.start(0)   # 可省略 0
3
>>> m.end(0)     # 可省略 0
5
>>> m.span(0)    # 可省略 0
(3, 5)

6、findall

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

注意: match 和 search 是匹配一次 findall 匹配所有。

语法格式为:

findall(string[, pos[, endpos]])

参数:

  • string 待匹配的字符串。
  • pos 可选参数,指定字符串的起始位置,默认为 0。
  • endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。

查找字符串中的所有数字:

import re
 
pattern = re.compile(r'\d+')   # 查找数字
result1 = pattern.findall('runoob 123 google 456')
result2 = pattern.findall('run88oob123google456', 0, 10)
 
print(result1)
print(result2)

输出结果:

['123', '456']
['88', '12']

7、re.finditer

和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

re.finditer(pattern, string, flags=0)

参数

import re
 
it = re.finditer(r"\d+","12a32bc43jf3") 
for match in it: 
    print (match.group() )

输出结果:

12 
32 
43 
3

8、re.split

split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:

re.split(pattern, string[, maxsplit=0, flags=0])

参数

>>>import re
>>> re.split('\W+', 'runoob, runoob, runoob.')
['runoob', 'runoob', 'runoob', '']
>>> re.split('(\W+)', ' runoob, runoob, runoob.') 
['', ' ', 'runoob', ', ', 'runoob', ', ', 'runoob', '.', '']
>>> re.split('\W+', ' runoob, runoob, runoob.', 1) 
['', 'runoob, runoob, runoob.']
 
>>> re.split('a*', 'hello world')   # 对于一个找不到匹配的字符串而言,split 不会对其作出分割
['hello world']

五、进程线程协程

进程:表示一个程序的上下文执行活动(打开、执行、保存...)。

线程:进程执行程序的最小调度单位(执行a,执行b...)。

协程:一个线程中会有很多函数,执行某个函数后等待,去执行另一个函数,最后又回来执行之前那个函数,这个过程叫协程。

进程和线程,都是一种CPU的执行单元。
线程由操作系统调度,协程由程序调度。
进程里的各个线程共享进程数据,但是不同进程的线程间不能共享数据。

优点

  • 无需线程上下文切换的开销
  • 无需锁定及同步的开销
  • 方便切换控制流,简化编程模型
  • 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。

缺点

  • 无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上。当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
  • 进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序

创建进程

如果并发任务是CPU密集型,多进程效率高

from multiprocessing import Process
from threading import Thread
import os,time
def work():
    res=0
    for i in range(100000000):
        res*=i
 
 
if __name__ == '__main__':
    l=[]
    cpu = os.cpu_count()
    print(os.cpu_count()) #本机为4核
    start=time.time()
    for i in range(cpu):
        p=Process(target=work) #进程耗时5s多
        p=Thread(target=work) #线程耗时18s多
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop=time.time()
    print('run time is %s' %(stop-start))

创建线程

如果并发任务是I/O密集型,多线程效率高

from multiprocessing import Process
from threading import Thread
import threading
import os,time
def work():
    time.sleep(2)
    print('===>')
 
if __name__ == '__main__':
    l=[]
    print(os.cpu_count()) #本机为4核
    start=time.time()
    for i in range(400):
        # p=Process(target=work) #进程耗时12s多,大部分时间耗费在创建进程上
        p=Thread(target=work) #线程耗时2s多
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop=time.time()
    print('run time is %s' %(stop-start))

创建协程

1、yield实现协程效果

def consumer(name):
    print('开始吃包子...')
    while True:
        print('\033[31;1m[consumer]%s需要包子\033[0m'%name)
        bone = yield   #接收send发送的数据
        print('\033[31;1m[%s]吃了%s个包子\033[0m'%(name,bone))
def producer(obj1):
    obj1.send(None)   #必须先发送None
    for i in range(3):
        print('\033[32;1m[producer]\033[0m正在做%s个包子'%i)
        obj1.send(i)
 
 
if __name__ == '__main__':
    con1 = consumer('消费者A')  #创建消费者对象
    producer(con1)
 
#output:
开始吃包子...
[consumer]消费者A需要包子
[producer]正在做0个包子
[消费者A]吃了0个包子
[consumer]消费者A需要包子
[producer]正在做1个包子
[消费者A]吃了1个包子
[consumer]消费者A需要包子
[producer]正在做2个包子
[消费者A]吃了2个包子
[consumer]消费者A需要包子

2、greenlet模块实现程序间切换执行

import greenlet
 
def A():
    print('a.....')
    g2.switch()  #切换至B
    print('a....2')
    g2.switch()
def B():
    print('b.....')
    g1.switch()  #切换至A
    print('b....2')
 
g1 = greenlet.greenlet(A) #启动一个线程
g2 = greenlet.greenlet(B)
g1.switch()

六、工具库文件

WebSocket

 简介

从形式上看,websocket是一个应用层协议,socket是数据链路层、网络层、传输层的抽像;从应用场合上看,websocket可以使用javascript实现,而socket不能用javascript实现(真不能吗?我不太确定);从实际效果上看,和一般的socket连接用起来没什么区别。

我们知道http是短连接的,反复建立和销毁连接比较耗费资源,另外http协议经常头部内容比主体内容还长也比较浪费资源;websocket可以认为就是一个内容使用载荷固定格式的socket长连接。

websocket基本协议格式如下,更多说明见RFC 6455

安装

pip install websockets

服务端

import asyncio
import websockets

# 检测客户端权限,用户名密码通过才能退出循环
async def check_permit(websocket):
    while True:
        recv_str = await websocket.recv()
        cred_dict = recv_str.split(":")
        if cred_dict[0] == "admin" and cred_dict[1] == "123456":
            response_str = "congratulation, you have connect with server\r\nnow, you can do something else"
            await websocket.send(response_str)
            return True
        else:
            response_str = "sorry, the username or password is wrong, please submit again"
            await websocket.send(response_str)

# 接收客户端消息并处理,这里只是简单把客户端发来的返回回去
async def recv_msg(websocket):
    while True:
        recv_text = await websocket.recv()
        response_text = f"your submit context: {recv_text}"
        await websocket.send(response_text)

# 服务器端主逻辑
# websocket和path是该函数被回调时自动传过来的,不需要自己传
async def main_logic(websocket, path):
    await check_permit(websocket)

    await recv_msg(websocket)

# 把ip换成自己本地的ip
start_server = websockets.serve(main_logic, '10.10.6.91', 5678)
# 如果要给被回调的main_logic传递自定义参数,可使用以下形式
# 一、修改回调形式
# import functools
# start_server = websockets.serve(functools.partial(main_logic, other_param="test_value"), '10.10.6.91', 5678)
# 修改被回调函数定义,增加相应参数
# async def main_logic(websocket, path, other_param)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

客服端

import asyncio
import websockets

# 向服务器端认证,用户名密码通过才能退出循环
async def auth_system(websocket):
    while True:
        cred_text = input("please enter your username and password: ")
        await websocket.send(cred_text)
        response_str = await websocket.recv()
        if "congratulation" in response_str:
            return True

# 向服务器端发送认证后的消息
async def send_msg(websocket):
    while True:
        _text = input("please enter your context: ")
        if _text == "exit":
            print(f'you have enter "exit", goodbye')
            await websocket.close(reason="user exit")
            return False
        await websocket.send(_text)
        recv_text = await websocket.recv()
        print(f"{recv_text}")

# 客户端主逻辑
async def main_logic():
    async with websockets.connect('ws://10.10.6.91:5678') as websocket:
        await auth_system(websocket)

        await send_msg(websocket)

asyncio.get_event_loop().run_until_complete(main_logic())

更多参考

Python3+WebSockets实现WebSocket通信 - xiondun - 博客园 (cnblogs.com)

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不努力谁会可怜你?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值