python学习之day08
面向对象:
多态与鸭子状态
抽象类
1 import abc 2 3 # python本身不提供抽象类和接口机制,要想实现抽象类,可以借助abc模块。 4 # ABC是Abstract Base Class的缩写。 5 6 class Animals(metaclass=abc.ABCMeta): 7 @abc.abstractclassmethod 8 def run(self): 9 pass 10 11 class Pig(Animals): 12 def run(self): 13 print('pig run ...') 14 15 class Cat(Animals): 16 def run(self): 17 print('cat run ...') 18 19 def AniamlRun(obj): 20 if isinstance(obj,Animals): 21 obj.run() 22 23 pig = Pig() 24 cat = Cat() 25 26 AniamlRun(pig) 27 AniamlRun(cat)
Python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子’
1 class Plane(): 2 def run(self): #鸭子类型 3 print('plane run ...') 4 5 def AniamlRun(obj): 6 if isinstance(obj,Animals): 7 obj.run() 8 else: 9 obj.run() #鸭子类型 10 11 plane = Plane() 12 AniamlRun(plane)
封装
隐藏
1 #其实这仅仅这是一种变形操作 2 #类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式: 3 class Girl: 4 __age = 18 #类的数据属性就应该是共享的 5 #但是语法上是可以把类的数据属性设置成私有的如__age,会变形为_Girl__age 6 def __goShop(self): 7 print('age: %d' % self.__age) 8 print('love goshoping') 9 def hasHobby(self): 10 self.__goShop() #只有在类内部才可以通过__goShop的形式访问到. 11 12 g = Girl() 13 g.hasHobby() 14 #A._A__N是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形 15 print(Girl.__dict__['_Girl__age']) 16 if hasattr(g,'_Girl__age'): 17 print(getattr(g,'_Girl__age'))
在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。
注意
1 ''' 2 1.这种机制也并没有真正意义上限制我们从外部直接访问属性, 3 知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N 4 2.变形的过程只在类的定义是发生一次,在定义后的赋值操作,不会变形 5 ''' 6 7 class A: 8 __a = 10 9 b = 20 10 def __foo(self): 11 print('from A') 12 13 def test(self): 14 self.__foo() 15 16 class B(A): 17 def __foo(self):#在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的 18 print('from B') 19 20 a = A() 21 a.__b = 20 22 print(a._A__a) 23 print(a.__dict__) 24 25 b = B() 26 b.test()
属性
property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值
def bmi(self):
1 class People: 2 def __init__(self,name,weight,height): 3 self.name=name 4 self.weight=weight 5 self.height=height 6 @property #property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值 7 def bmi(self): 8 return self.weight / (self.height**2) 9 10 p1=People('egon',75,1.85) 11 print(p1.bmi)
1 ''' 2 python并没有在语法上public、protected、private机制, 3 在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取, 4 在python中通过property方法可以实现 5 ''' 6 class People: 7 def __init__(self,val): 8 self.__NAME=val #将所有的数据属性都隐藏起来 9 10 @property 11 def name(self): 12 return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置) 13 14 @name.setter 15 def name(self,value): 16 if not isinstance(value,str): #在设定值之前进行类型检查 17 raise TypeError('%s must be str' %value) 18 self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME 19 20 @name.deleter 21 def name(self): 22 raise TypeError('Can not delete') 23 24 f=People('egon') 25 print(f.name) 26 # f.name=10 #抛出异常'TypeError: 10 must be str' 27 del f.name #抛出异常'TypeError: Can not delete'
面向对象高级
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
issubclass(sub, super)检查sub类是否是 super 类的派生类
1 class People: 2 name = 'wingsmm' 3 def __init__(self,val): 4 self.name=val 5 6 p = People('zhangsan') 7 print(p.name) 8 9 #检测是否含有某属性 10 print(hasattr(p,'name')) 11 12 #获取属性 13 print(getattr(p,'name')) 14 print(getattr(p,'aaaaaaaa','不存在啊')) 15 16 #设置属性 17 setattr(p,'sb',True) 18 print(p.__dict__) 19 20 #删除属性 21 delattr(p,'sb') 22 print(p.__dict__)
1 class Ftpserver: 2 def __init__(self,host,port): 3 self.host=host 4 self.port=port 5 6 def run(self): 7 while True: 8 cmd=input('>>: ').strip() 9 if not cmd:continue 10 if hasattr(self,cmd): 11 func=getattr(self,cmd) 12 func() 13 def get(self): 14 print('get func') 15 16 def put(self): 17 print('put func') 18 19 f=Ftpserver('192.168.1.2',21) 20 f.run()
1 class Foo: 2 def __getitem__(self, item): 3 print('=====>get') 4 return self.__dict__[item] 5 6 def __setitem__(self, key, value): 7 self.__dict__[key]=value 8 # setattr(self,key,value) 9 10 def __delitem__(self, key): 11 self.__dict__.pop(key) 12 13 f=Foo() 14 f.x=1 15 print(f.x) 16 print(f.__dict__) 17 18 f['x']=123123123123 19 20 # del f['x'] 21 22 print(f['x'])
1 class People: 2 def __init__(self,name,age,sex): 3 self.name=name 4 self.age=age 5 self.sex=sex 6 7 def __str__(self): #在对象被打印时触发执行 8 return '<name:%s age:%s sex:%s>' %(self.name,self.age,self.sex) 9 10 p=People('zhangsan',18,'male') 11 print(p)
1 class Foo: 2 def __init__(self,x): 3 self.x=x 4 5 def __del__(self): #在对象资源被释放时触发 6 print('-----del------') 7 print(self) 8 9 f=Foo(100000) 10 del f 11 print('=======================>')
异常处理
1 class EgonException(BaseException): 2 def __init__(self,msg): 3 self.msg=msg 4 def __str__(self): 5 return '<%s>' %self.msg 6 7 8 class Person: 9 def __init__(self,name): 10 if isinstance(name,str): 11 self.__name = name 12 else: 13 raise EgonException('name') 14 15 p = Person(10)
网络编程
ssh服务器:
服务器:
1 import socket 2 import subprocess 3 4 host = '127.0.0.1' 5 port = 8080 6 listen_max = 5 7 recv_max = 1024 8 9 server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 10 server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 11 server.bind((host,port)) 12 server.listen(listen_max) 13 14 while True: 15 conn,clint_addr = server.accept() 16 print(clint_addr) 17 while True: 18 try: 19 cmd = conn.recv(recv_max) 20 if not cmd:continue 21 22 #只能从管道里读一次结果 23 #编码是以当前所在的系统为准的 24 #如果是windows,那么res.stdout.read()读出的就是GBK编码的 在接收端需要用GBK解码 25 res = subprocess.Popen(cmd.decode('utf-8'),shell = True,stdout=subprocess.PIPE, stderr=subprocess.PIPE) 26 # 既有正确stdout结果,又有错误stderr结果 27 stdout = res.stdout.read() 28 stderr = res.stderr.read() 29 conn.send(stdout + stderr) 30 except Exception as e: 31 break 32 conn.close() 33 34 server.close()
客户端:
1 import socket 2 3 host = '127.0.0.1' 4 port = 8080 5 listen_max = 5 6 recv_max = 1024 7 8 client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 9 client.connect((host,port)) 10 11 while True: 12 cmd = input('>>: ').strip() 13 if not cmd:continue 14 client.send(cmd.encode('utf-8')) 15 cmd_rec = client.recv(recv_max) 16 print(cmd_rec.decode('utf-8')) 17 18 client.close()
粘包:
只有TCP有粘包现象,UDP永远不会粘包。
所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。
1 #client 2 3 import socket 4 import struct 5 6 host = '127.0.0.1' 7 port = 8080 8 listen_max = 5 9 recv_max = 64 10 11 client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 12 client.connect((host,port)) 13 14 while True: 15 cmd = input('>>: ').strip() 16 if not cmd:continue 17 client.send(cmd.encode('utf-8')) 18 header = client.recv(4) 19 total_size = struct.unpack('i',header)[0] 20 21 recv_size = 0 22 recv_data = b'' 23 while recv_size < total_size: 24 data = client.recv(recv_max) 25 recv_size += len(data) 26 recv_data += data 27 print(recv_data.decode('utf-8')) 28 29 client.close() 30 31 32 33 #server 34 35 import socket 36 import subprocess 37 import struct 38 39 host = '127.0.0.1' 40 port = 8080 41 listen_max = 5 42 recv_max = 64 43 44 server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 45 server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 46 server.bind((host,port)) 47 server.listen(listen_max) 48 49 while True: 50 conn,coon_addr = server.accept() 51 print(coon_addr) 52 while True: 53 try: 54 cmd = conn.recv(recv_max) 55 if not cmd:continue 56 57 res = subprocess.Popen(cmd.decode('utf-8'),shell = True,stdout=subprocess.PIPE, stderr=subprocess.PIPE) 58 stdout = res.stdout.read() 59 stderr = res.stderr.read() 60 61 header = struct.pack('i',len(stdout) + len(stderr)) 62 conn.send(header) 63 conn.send(stdout + stderr) 64 except Exception as e: 65 break 66 conn.close() 67 68 server.close()
socket并发
1 import socketserver 2 3 host = '127.0.0.1' 4 port = 8080 5 listen_max = 5 6 recv_max = 1024 7 8 class MyTcphandler(socketserver.BaseRequestHandler): 9 def handle(self): 10 while True: #通信循环 11 data=self.request.recv(recv_max) 12 self.request.send(data.upper()) 13 if __name__ == '__main__': 14 #取代链接循环 15 server=socketserver.ThreadingTCPServer((host,port),MyTcphandler) 16 server.serve_forever
定制报头+并发
1 import socketserver 2 import subprocess 3 import struct 4 import json 5 6 host = '127.0.0.1' 7 port = 8080 8 listen_max = 5 9 recv_max = 1024 10 11 class MyTcphandler(socketserver.BaseRequestHandler): 12 def handle(self): 13 while True: #通信循环 14 try: 15 cmd = self.request.recv(recv_max) 16 if not cmd: continue 17 18 res = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 19 stdout = res.stdout.read() 20 stderr = res.stderr.read() 21 22 # 制作报头 23 header_dict = {'totalSize': len(stdout) + len(stderr), 'md5': None} 24 header_bytes = json.dumps(header_dict).encode('utf-8') 25 26 # 先发报头的长度(固定4个bytes) 27 self.request.send(struct.pack('i', len(header_bytes))) 28 29 # 先发报头 30 self.request.send(header_bytes) 31 32 # 再发真实的数据 33 self.request.send(stdout + stderr) 34 except Exception as e: 35 break 36 37 38 if __name__ == '__main__': 39 #取代链接循环 40 server=socketserver.ThreadingTCPServer((host,port),MyTcphandler) 41 server.serve_forever()
1 import socket 2 import struct 3 import json 4 5 host = '127.0.0.1' 6 port = 8080 7 listen_max = 5 8 recv_max = 64 9 10 client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 11 client.connect((host,port)) 12 13 while True: 14 15 cmd = input('>>: ').strip() 16 if not cmd:continue 17 # 发命令 18 client.send(cmd.encode('utf-8')) 19 20 # 先收报头的长度 21 header = client.recv(4) 22 header_size = struct.unpack('i',header)[0] 23 print('header_size: %d' % header_size) 24 25 # 再收报头 26 header_bytes = client.recv(header_size) 27 header_dict = json.loads(header_bytes.decode('utf-8')) 28 29 # 再收命令的执行结果 30 total_size = header_dict['totalSize'] 31 recv_size = 0 32 recv_data = b'' 33 while recv_size < total_size: 34 data = client.recv(recv_max) 35 recv_size += len(data) 36 recv_data += data 37 38 # 打印结果 39 print(recv_data.decode('utf-8')) 40 41 client.close()

浙公网安备 33010602011771号