Python学习-day7 类 部分socket
这周还是继续关于类的学习,在面向对象的学习过程中又学习了网络编程,并且提交了编写FTP的作业。
复习一下类的相关概念和定义
类
属性
实例变量:内存中
类变量: 类的内存,实例共享
私有属性__var
方法
构造方法: 初始化
析构方法: 实例销毁的时候
私有方法
静态方法:只是名义上的归类管理,实际上在静态方法中无法访问类中的任何属性。
属性方法:把一个方法变成静态属性
类方法:可以使用类变量,不能访问实例中的变量
对象:一个类的实例
封装
把一些功能的实现细节,不对外暴露
继承
代码的重用
单集成
多继承
2.7 经典类,深度优先 新式类,广度优先
3.x 均是广度优先
class Foo(object)
def __init__(self,name,age,sex,salary,course):
super(Foo,self).__init__(name,age,sex)
self.salary = salary
self.course = course
多态
接口的重用,一种接口,多种实现
下面是一个Socket通信的实例:
Server端
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#Authon Ivor import socket import json import os ip = ('localhost',9999) s = socket.socket() s.bind(ip) s.listen(5) while True: print("等待连接中....") conn,client_addr = s.accept() print("有用户主动接入:", conn, client_addr) while True: data = conn.recv(4096) data = json.loads(data.decode('utf-8')) if data.get('action') is not None: if data['action'] == 'put': file_obj = open(data['file_name'],'wb') receive_size = 0 file_size = data['file_size'] while receive_size < file_size: recv = conn.recv(4096) file_obj.write(recv) receive_size += len(recv) print(file_size,receive_size) file_obj.close() print("File receive complete!") elif data['action'] == 'get': pass
Client端
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#Authon Ivor import os import json import socket client = socket.socket() client.connect(('localhost',9999)) while True: choice = input(">>>:") if len(choice) == 0:continue cmd_list = choice.split() if cmd_list[0] == 'put': if cmd_list[-1]: file_name = cmd_list[-1] if os.path.isfile(file_name): base_filename = file_name.split("/")[-1] file_size = os.path.getsize(file_name) file_obj = open(file_name,'rb') data_header = { "action":"put", "file_name":base_filename, "file_size":file_size } client.send(json.dumps(data_header).encode('utf-8')) for line in file_obj: client.send(line) print("File send complete.".center(50,'-')) else: print("File is not exists.") else: print("Need a file...") elif cmd_list[0] == 'get': pass else: print("Wrong input.")
如果想要实现多并发连接也很简单,Socket自带了多线程的TCP服务
需要定义一个继承socketserver.BaseRequestHandler的Handler,
并且重定义handler函数,通过self.request.recv()/self.request.send()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#Authon Ivor import socketserver class MyHandelclass(socketserver.BaseRequestHandler): def handle(self): while True: self.data = self.request.recv(4096) print(self.client_address) print(self.data) self.request.sendall(self.data.upper()) if __name__ == '__main__': server = socketserver.ThreadingTCPServer(('localhost',9999),MyHandelclass) server.serve_forever()
Client端不需要变动
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#Authon Ivor import os import json import socket client = socket.socket() client.connect(('localhost',9999)) while True: choice = input(">>>:") if len(choice) == 0:continue client.send(choice.encode('utf-8')) data =client.recv(1024) print(data)
下一个重要的知识点,反射,通过字符串判断类中是否存在这个方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#Authon Ivor def bark(self): print("%s is yelling!" % self.name ) class Dog(object): def __init__(self,name): self.name = name def eat(self): print("%s is eating!" % self.name) d= Dog("Wangwang") choice = input(">>>:") if hasattr(d,choice): func = getattr(d,choice) func() else: setattr(d,choice,bark) #d.choice = bark func = getattr(d,choice) func(d)
异常处理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#Authon Ivor name = [0,1,2] dic = {} try: name[3] except IndexError as e : print(e) try: dic['666'] except KeyError as e: print("KeyError",e) except Exception as e: print("可以抓到任何错误!") else: print("没有错误时我会运行!") finally: print("不管怎么样,我都会运行!") # 常用异常 # AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x # IOError 输入/输出异常;基本上是无法打开文件 # ImportError 无法引入模块或包;基本上是路径问题或名称错误 # IndentationError 语法错误(的子类) ;代码没有正确对齐 # IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] # KeyError 试图访问字典里不存在的键 # KeyboardInterrupt Ctrl+C被按下 # NameError 使用一个还未被赋予对象的变量 # SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) # TypeError 传入对象类型与要求的不符合 # UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, # 导致你以为正在访问它 # ValueError 传入一个调用者不期望的值,即使值的类型是正确的
类的其他特殊成员方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#Authon Ivor class Foo(object): #定义类的原类 __metaclass__ = type #类中所有的方法和属性 #__dict__ #构造函数,创建对象时调用 def __init__(self,name,age): super(Foo,self).__init__() self.age = age self.name = name #定义对象的调用方式 def __call__(self, *args, **kwargs): print("I'm the __call__ .") #打印对象时,使用这个函数的返回值 def __str__(self): return "%s" % self.name def __new__(cls, *args, **kwargs): print("I'm the __new__!") return object.__new__(cls) def __del__(self): pass f = Foo("ivor",27) f() #类的第二种定义方法,一切皆对象,类也是对象,源于type def func(self): print("hello %s"%self.name) def __init__(self,name,age): self.name = name self.age = age Foo = type('Foo',(object,),{'func':func,'__init__':__init__}) f = Foo("jack",22) f.func()
以下是这次作业的ReadMe
程序说明:
1.启动服务端
./FTP_Server/bin/ftp_server.py start
端口号为9999,写入了settings的配置文件里。
2.启动客户端
./FTP_Client/ftp_client -s localhost -p 9999 -u Ivor -P abc123
Ivor abc123 / Jack abc123
用户名密码也可以连接后输入,有两个用户,写在了accounts里。
3.连接成功后,用户默认所在目录为家目录。
程序功能:
1.put --md5(可选)
向服务器上传文件,服务器会检验是否超过了分配空间,有空间则上传,空间不足则返回错误。md5一致性检验为可选项
2.get --md5(可选)
从服务器下载文件。md5一致性检验为可选项
3.ls
列出当前目录的文件。试用于linux系统
4.dir
列出当前目录的文件。试用于linux系统和windows系统