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()

 

posted @ 2017-08-19 23:55  wingsmm  阅读(140)  评论(0)    收藏  举报