python学习笔记(二)高级语法

143 阅读8分钟

== 和 is

== 判断值是否相等 , is判断是否指向的是一个东西

深拷贝 浅拷贝

import copy

c = copy.deepcopy(a) # 完成深拷贝

如果c是引用,引用指向的内容也拷贝(递归)

c = copy.copy(a) # 比deep浅

判断是否是可变类型,如果是不可变类型,不copy,如果是可变类型,只copy一层

进制

bin(18)#0b
oct(18)#0o
hex(18)#0x

int("0x12",16) #到10进制

位运算

& | ^ ~ << >>

私有化

  • xx 公有变量
  • _xx 单下划线 进制from xx import * ,类对象和子类可以访问
  • __xx 避免和子类命名冲突,子类访问不到(名字重整)
  • __xx__ 魔法对象或属性
  • xx_ 避免和python关键字冲突

property (属性)

class Test(object):
    def __init__(self):
       self.__num = 100

    def setNum(self, newNum):
        print("----setter----")
        self.__num = newNum

    def getNum(self):
        print("----getter----")
        return self.__num

    num = property(getNum, setNum)


t = Test()
#print(t.__num)
#t.__num = 200

#print(t.getNum())
#t.setNum(50)
#print(t.getNum())

print("-"*50)

t.num = 200 #相当于调用了 t.setNum(200)

print(t.num) #相当于调用了 t.getNum()

#注意点:
#t.num 到底是调用getNum()还是setNum(),要根据实际的场景来判断,
#1. 如果是给t.num赋值 那么一定调用setNum()
#2. 如果是获取t.num的值,那么就一定调用getNum()
#
#property的作用:相当于把方法进行了封装, 开发者在对属性设置数据的时候更方便

=================================================
class Test(object):
    def __init__(self):
       self.__num = 100

    @property
    def num(self):
        print("----getter----")
        return self.__num

    @num.setter
    def num(self, newNum):
        print("----setter----")
        self.__num = newNum

t = Test()

t.num = 200 #相当于调用了 t.setNum(200)

print(t.num) #相当于调用了 t.getNum()

import导入模块

搜索路径: sys.path

添加路径 sys.path.append("/home")

重新导入

在程序没退出的情况下 修改模块 新功能不能展示

from imp import *

reload(test)

循环导入

设计一个总模块,分别调用各个模块,防止之间的相互调用,造成循环

迭代器

可迭代对象:

  • list tuple dict set str
  • generator (生成器)

装饰器

def w1(func):
    def inner():
        print("--装饰--")
        func()
    return inner

@w1
def f1():
    prinf("----f1-----")

f1()

对有参数的函数装饰

def w1(func):
    def inner(a,b): #如果没有ab 会调用失败
        print("--执行前装饰--")
        func(a,b)
        print("--执行后装饰--")
    return inner

@w1
def f1(a,b): # 如果函数需要两个参数
    prinf("----f1-%d-%d---"%(a,b))

f1()

参数改为*args,**kwargs

def w1(func):
    def inner(*args,**kwargs): 
        print("--执行前装饰--")
        func(*args,**kwargs)
        print("--执行后装饰--")
    return inner

@w1
def f1(a,b): 
    prinf("----f1-%d-%d---"%(a,b))

f1()

通用装饰器

def w1(func):
    def func_in(*args,**kwargs):
        ret = func(*args,**kwargs)
        return ret

    return func_in

@w1
def test():
    pass

带有参数的装饰器

def func_arg(arg)
    def w1(func):
        def func_in():
            ret = func()

        return func_in
    return w1

@func_arg("heihei")
def test():
    pass

作用域

命名空间

  • globals
  • locals

LEGB

locals -> enclosing function -> globals -> builtins

  • 局部变量
  • 闭包外面的
  • 全局
  • 内建

动态绑定

import types

class P(object):
    def __init__(self.newName):
        self.name = newName

def eat(self):
    pass

p1.eat = types.MethhodType(eat,p1)
p1.run()

slots

slots = ("name","age") # 限定


生成器

把计算每个元素的方式保存了,不会马上生成,节省了内存

  1. 把列表生成式的中括号改成小括号
b = (x*2 for x in range(10))
next(b) #0
next(b) #2
next(b) #4

b.__next__() #和上面一样
  1. 写一个函数 加上yield
  • yield的返回值是send的内容

第一次调用需要传none或者先用next

生成器完成多任务

def test1():
    while True:
        print("---111---")
        yield None

def test2():
    while True:
        print("---222---")
        yield None

t1 = test1()
t2 = test2()
while True:
    t1.__next__()
    t2.__next__()

python 多任务

进程

import os
#ret==0子进程  else父进程

# windows 没有fork函数
pid = os.fork()
os.getpid()
os.getppid()

在windows上可以用的fork

from multiprocessing import Process
import os

#子进程需要执行的代码
def run_proc(name):
    print("---子进程---")

if __name__ == '__main__':
    print('父进程')
    p = Process(target=run_proc,args=('test',))
    print('子进程将要执行')
    p.start() 
    p.join() # 等待子进程
    print('子程序结束')

进程间通信

from multiprocessing import Queue

q = Queue(3) # 不填3就是无限大

#把q当成参数传入创建进程的函数
p = Process(target=write,arg=(q,))

q.qsize() #0

q.put('haha') 
q.qsize() #1

q.get() # 取出添加的第一个

q.empty()
q.full()

q.get_nowait() # 如果为空 报异常(放在try里面)

#-----------
如果是进程池之间通信 应该使用
q.Manager().Queue()
po = Pool()
po.apply(writer,(q,))
po.close()
po.join()

process子类

  • 调父类init
  • 重写process的run方法

进程池 Pool

from multiprocessing import Pool

def worker(msg):
    print(msg)

po = Pool(3) # 定义一个进程池 最大是3
for i in range(0,10):
    #po.apply_async(要调用的目标,(传递的参数元组,))
    #每次循环警徽用空闲出来的进程去调用目标
    po.apply_async(worker(i,))# 非堵塞
    po.apply(worker(i,))# 堵塞 几乎不用

po.close() # 关闭进程池,不能添加新的任务
po.join() #主进程等待进程池中执行完才结束

线程 Thread

底层 Thread模块 threading模块对Thread包装

  1. 函数
import threading
import time

def sayAaa():
    print("aaa")
    time.sleep(1)

if __name__ = '__main__':
    for i in range(5):
        t = threading.Thread(target=sayAaa)
        t.start() 
import threading
import time

class MyThread(threading.Thread):

    def run(self):
        for i in range(3):
            time.sleep(1)
            msg = 'I am '+self.name+' @ '+str(i)
            print(msg)

if __name__  == '__main__':
    t = MyThread()
    t.start()

线程之间共享全局变量

互斥锁

from threading import Thread, Lock
import time

g_num = 0

def test1():
    global g_num
    #这个线程和test2线程都在抢着 对这个锁 进行上锁,如果有1方成功的上锁,那么导致另外
    #一方会堵塞(一直等待)到这个锁被解开为止
    
    for i in range(1000000):
        mutex.acquire()
        g_num += 1
        mutex.release()#用来对mutex指向的这个锁 进行解锁,,,只要开了锁,那么接下来会让所有因为
                    #这个锁 被上了锁 而堵塞的线程 进行抢着上锁

    print("---test1---g_num=%d"%g_num)

def test2():
    global g_num
    for i in range(1000000):
        mutex.acquire()
        g_num += 1
        mutex.release()

    print("---test2---g_num=%d"%g_num)

#创建一把互斥锁,这个锁默认是没有上锁的
mutex = Lock()

p1 = Thread(target=test1)
p1.start()

#time.sleep(3) #取消屏蔽之后 再次运行程序,结果会不一样,,,为啥呢?

p2 = Thread(target=test2)
p2.start()

print("---g_num=%d---"%g_num)

同步

from threading import Thread,Lock
from time import sleep

class Task1(Thread):
    def run(self):
        while True:
            if lock1.acquire():
                print("------Task 1 -----")
                sleep(0.5)
                lock2.release()

class Task2(Thread):
    def run(self):
        while True:
            if lock2.acquire():
                print("------Task 2 -----")
                sleep(0.5)
                lock3.release()

class Task3(Thread):
    def run(self):
        while True:
            if lock3.acquire():
                print("------Task 3 -----")
                sleep(0.5)
                lock1.release()

#使用Lock创建出的锁默认没有“锁上”
lock1 = Lock()
#创建另外一把锁,并且“锁上”
lock2 = Lock()
lock2.acquire()
#创建另外一把锁,并且“锁上”
lock3 = Lock()
lock3.acquire()

t1 = Task1()
t2 = Task2()
t3 = Task3()

t1.start()
t2.start()
t3.start()

ThreadLocal

import threading

# 创建全局ThreadLocal对象:
local_school = threading.local()

def process_student():
    # 获取当前线程关联的student:
    std = local_school.student
    print('Hello, %s (in %s)' % (std, threading.current_thread().name))

def process_thread(name):
    # 绑定ThreadLocal的student:
    local_school.student = name
    process_student()

t1 = threading.Thread(target= process_thread, args=('dongGe',), name='Thread-A')
t2 = threading.Thread(target= process_thread, args=('老王',), name='Thread-B')
t1.start()
t2.start()

异步、回调

from multiprocessing import Pool
import time
import os

def test():
    print("---进程池中的进程---pid=%d,ppid=%d--"%(os.getpid(),os.getppid()))
    for i in range(3):
        print("----%d---"%i)
        time.sleep(1)
    return "hahah" #返回给了父进程

def test2(args):
    print("---callback func--pid=%d"%os.getpid()) #是父进程做的
    print("---callback func--args=%s"%args)

pool = Pool(3)
pool.apply_async(func=test,callback=test2)

#异步的理解:主进程正在做某件事情,突然 来了一件更需要立刻去做的事情,
#那么这种,在父进程去做某件事情的时候 并不知道是什么时候去做,的模式 就称为异步
while True:
    time.sleep(1)
    print("----主进程-pid=%d----"%os.getpid())

GIL

Python的线程是假的
解决方式: 用C语言写

loop.c

void DeadLoop()
{
    while(1)
    {
        ;
    }
}   

main.py

from ctypes import *
from threading import Thread

#加载动态库
lib = cdll.LoadLibrary("./libdeadloop.so")

#创建一个子线程,让其执行c语言编写的函数,此函数是一个死循环
t = Thread(target=lib.DeadLoop)
t.start()

#主线程,也调用c语言编写的那个死循环函数
#lib.DeadLoop()

while True:
    pass 

gcc xxx.c -shared -o libxxxx.so


python3网络编程

TCP/IP

  • 应用层 (应用层 表示层 会话层)
  • 传输层 TCP UDP
  • 网络层 IP ICMP ARP RARP
  • 链路层(物理层 数据链路层)

端口号:0-65535
知名端口0-1023
动态端口1024-65535

IP地址

  • 0和255不能用(0网络号 255广播)
  • D类多播

参考资料:菜鸟教程

socket函数创建 socket.socket([family[, type[, proto]]])

  • family: 套接字家族可以使AF_UNIX或者AF_INET
  • type: 套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM
  • protocol: 一般不填默认为0.

例如: socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server TCP

#!/usr/bin/python3
# 文件名:server.py
import socket
# 创建 socket 对象
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 获取本地主机名
host = socket.gethostname()
port = 9999
# 绑定端口号
serversocket.bind((host, port))
# 设置最大连接数,超过后排队
serversocket.listen(5)
while True:
    # 建立客户端连接
    clientsocket, addr = serversocket.accept()
    print("连接地址: %s" % str(addr))
    msg = '欢迎访问菜鸟教程!' + "\r\n"
    clientsocket.send(msg.encode('utf-8'))
    clientsocket.close()

client TCP

#!/usr/bin/python3
# 文件名:client.py
import socket

# 创建 socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 获取本地主机名
host = socket.gethostname()
port = 9999# 设置端口号
s.connect((host, port))# 连接服务,指定主机和端口

msg = s.recv(1024) # 接收小于 1024 字节的数据
s.close()

print (msg.decode('utf-8'))

UDP server

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import socket
 
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("127.0.0.1", 6000))
print("UDP bound on port 6000...")
 
while True:
    data, addr = s.recvfrom(1024)
    print("Receive from %s:%s" % addr)
    print(data)
    if data == b"exit":
        s.sendto(b"Good bye!\n", addr)
        continue
    s.sendto(b"Hello %s!\n" % data, addr)

UDP client


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import socket
 
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
addr = ("127.0.0.1", 6000)
 
while True:
    data = input("Please input your name: ")
    if not data:
        continue
    s.sendto(data.encode(), addr)
    response, addr = s.recvfrom(1024) # 收到的是个元组
    print(response.decode())
    if data == "exit":
        print("Session is over from the server %s:%s\n" % addr)
        break
 
s.close()

SocketServer类

class ForkingUDPServer(ForkingMixIn, UDPServer)
class ForkingTCPServer(ForkingMixIn, TCPServer)
class ThreadingUDPServer(ThreadingMixIn, UDPServer)
class ThreadingTCPServer(ThreadingMixIn, TCPServer)
class ThreadingUnixStreamServer(ThreadingMixIn, UnixStreamServer)
class ThreadingUnixDatagramServer(ThreadingMixIn, UnixDatagramServer)

socketserver TCP Server

import socketserver
class MyTcpHandler(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            try:
                data = self.request.recv(1024)
                if not data: break  # 此行代码针对linux系统
                self.request.send(data.upper())
                print(data)
            except ConnectionResetError:
                break
        self.request.close()


if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('0.0.0.0', 8180), MyTcpHandler)
    server.serve_forever()

socketserver TCP Client

from socket import *
import os ,time

client = socket(AF_INET, SOCK_STREAM)
client.connect(('118.24.137.128', 8180))

while True:
    msg = '%s hello' % os.getpid()
    client.send(msg.encode("utf-8"))
    data = client.recv(1024)
    print(data.decode('utf-8'))
    time.sleep(1)

socketserver UDP Server


import socketserver
 
class MyUdpHandler(socketserver.BaseRequestHandler):
    def handle(self):
        res=self.request[0]
        print('客户端发来的数据:',res)
 
        self.request[1].sendto(res.upper(),self.client_address)
 
 
if __name__ == '__main__':
    server=socketserver.ThreadingUDPServer(('0.0.0.0',8888),MyUdpHandler)
    server.serve_forever()

socketserver UDP Client

from socket import *
import os, time

client = socket(AF_INET, SOCK_DGRAM)

while True:
    msg = '%s hello' % os.getpid()
    client.sendto(msg.encode('utf-8'), ('118.24.137.128', 8888))
    data, server_addr = client.recvfrom(1024)
    print(data.decode('utf-8'))
    time.sleep(1)

END

参考资料

一些零碎代码

UART py

# -*- coding: utf-8 -*
import serial
import time
# 打开串口
ser = serial.Serial("/dev/ttyUSB0", 115200)
def main():
    while True:
        # 获得接收缓冲区字符
        count = ser.inWaiting()
        if count != 0:
            # 读取内容并回显
            recv = ser.read(count)
            print(recv)
            #ser.write(recv)
        # 清空接收缓冲区
        ser.flushInput()
        # 必要的软件延时
        time.sleep(0.2)
    
if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        if ser != None:
            ser.close()