目录:
- 面向对象
- 反射
- socket
一、面向对象
方法
方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。
普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
静态方法:由类调用;无默认参数;
class Aniaml: count = 10 def __init__(self,name): self.name = name self.num = None hobbie = ‘meat‘ @classmethod #类方法,不能访问实例变量 def talk(self): print(‘%s is talking ...‘%self.hobbie ) @staticmethod #静态方法,不能访问类变量及实例变量 def walk(): print(‘is walking ...‘) @property #把方法变属性 def habbit(self): print(‘%s habit is sss‘%self.name) @property def total_players(self): return self.num @total_players.setter def total_players(self,num): self.num = num print(‘total players:‘,self.num) @total_players.deleter def total_players(self): print(‘total player got deleted.‘) del self.num Aniaml.hobbie Aniaml.talk() d = Aniaml(‘hahah‘) print(d.total_players) d.total_players = 3 类的特殊成员,内部模块 class A: n = ‘A‘ def f2(self): print(‘f2 from A‘) class B(A): n = ‘B‘ def __init__(self): pass def f1(self): print(‘f1 from B‘) def f2(self): print(‘f2 from B‘) def __del__(self): print(‘del ....‘) def __call__(self, *args, **kwargs): print(‘__cal__‘) class C(A): n = ‘C‘ def f2(self): print(‘f2 from C‘) class D(B,C): pass d = D() d.f1() d.f2() print(B.__doc__) print(B.__dict__) print(B.__class__) print(B.__module__) B.__del__ obj = B() obj()
二、反射
Python中的反射功能由以下四个内置函数提供:
- hasattr() 检查是否包含某成员
- getattr() 获取成员
- setattr() 设置成员
- delattr() 删除成员
1、从前我们最开始在写一些输入选项的时候会使用简单的if … else..来实现:
raw = input(‘输入您的选择:’).strip() if raw == ‘start’: pass else raw == ‘stop’: pass …
2、后来学习了字典以后,我们发现原来可以精简一些:
menu_dic = {‘1‘:‘start’,‘2‘:‘stop‘,‘3‘:‘restart‘} raw = input(‘请输入您的选择: ‘).strip() if raw in menu_dic: print(menu_dic[raw])
3、再后来学习了反射后,我们发现原来还可以再精简一些:
import sys class WebServer(object): def __init__(self,host,port): self.host = host self.port = port def start(self): print(‘Server is stating ...‘) def stop(self): print(‘Server is stopping ...‘) def restart(self): self.stop() self.start() print(‘Server is restarting ...‘) if __name__ == ‘__main__‘: server = WebServer(‘localhost‘,80) #hasatter 判断输入参数是否包含在class WebServer() if hasattr(server,sys.argv[1]): #如果包含,获取该成员 func = getattr(server,sys.argv[1]) func() $ python3 day07.py start Server is stating ...
如果要设置一个新的成员,则需要使用setattr(),删除的话则要使用delattr(),修改为:
def test_run(self,name): print(‘Test_running ...‘,name,self.host) if __name__ == ‘__main__‘: server = WebServer(‘localhost‘,80) if hasattr(server,sys.argv[1]): func = getattr(server,sys.argv[1]) func() setattr(server,‘run‘,test_run) server.run(server,‘haha’) #运行结果 Server is stating … Test_running ... haha localhost
三、socket
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。
socket和file的区别:
file模块是针对某个指定文件进行【打开】【读写】【关闭】
socket模块是针对 服务器端 和 客户端Socket 进行【打开】【读写】【关闭】
具体状态:
sk.bind(address)
将套接字绑定到地址。adress地址的格式取决于地址族。以元组(host,port)的形式表示地址。
sk.listen(backlog)
开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。
backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5.这个值不能无限大,因为内核中维护连接队列。
sk.setblock(bool)
是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。
sk.accept()
接受连接并返回(conn,address)其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。
接收TCP客户的连接(阻塞式)等待连接的到来。
sk.connect(adress)
连接到address处的套接字。address格式为元组。如果连接出错,返回socket.error错误。
sk.connect_ex(address)
同上,区别是有返回值。连接成功返回0,失败则返回其他编码。
sk.close()
关闭套接字
sk.recv(bufsize)
接收套接字的数据。数据以字符串形式返回,bufsize可以指定最多可以接收的数量。
sk.send(string)
将str中的数据发送到连接的套接字。返回值是要发送的字节数量。
sk.sendall(string)
将str中的数据发送到连接的套接字,但在返回之前会尝试发送所有的数据。成功返回None,失败则抛出异常。
sk.sendto(string,address)
将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是是发送的字节数。该函数主要用于UDP协议。
sk.settimeout(timeout)
设置套接字操作的超时时间,最好在刚创建套接字时设置。
sk.getpeername()
返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)
sk.getsockname()
返回套接字自己的地址。
sk.fileno()
套接字的文件描述符。
执行流程
server 端:
1、创建套接字,绑定套接字到本地IP和端口
ip_port = (‘127.0.0.1‘,9998) sk = socket.socket() sk.bind(ip_port)
2、开始监听
sk.listen(5)
3、进入循环,不断接受客户端的连接请求
while True: print(‘Server is waiting ... ‘) conn,addr = sk.accept()
4、然后接收传来的数据,并发送给对方数据
client_data = conn.recv(1024) print(str(client_data,‘utf-8’)) conn.sendall(bytes(‘这是 server !‘,‘utf-8’))
5、传输完毕,关闭套接字
sk.close()
clinet端:
1、创建套接字,绑定套接字到本地IP和端口
ip_port = (‘127.0.0.1‘,9998) sk = socket.socket() sk.bind(ip_port)
2、连接后发送数据和接受数据
sk.sendall()
sk.recv()
3、传输完毕后,关闭套接字()
sk.close()
代码示例:实现client输入发送信息,server返回client输入的信息。
#server端 import socket ip_port = (‘127.0.0.1‘,9998) sk = socket.socket() sk.bind(ip_port) sk.listen(5) while True: print(‘Server is waiting ... ‘) conn,addr = sk.accept() client_data = conn.recv(1024) print(str(client_data,‘utf-8‘)) conn.sendall(bytes(‘这是 server !‘,‘utf-8‘)) while True: client_data = conn.recv(1024) print(‘revv:‘,str(client_data,‘utf8‘)) if not (client_data):break conn.sendall(client_data) #client端 import socket ip_port = (‘127.0.0.1‘,9998) sk = socket.socket() sk.connect(ip_port) sk.sendall(bytes(‘这是 client !‘,‘utf-8‘)) server_replay = sk.recv(1024) print(str(server_replay,‘utf-8‘)) while True: client_raw = input(‘:‘).strip() sk.sendall(bytes(client_raw,‘utf-8‘)) server_replay = sk.recv(1024) print(str(server_replay,‘utf-8‘)) sk.close()
代码示例:聊天工具
#server端import socket ip_port = (‘127.0.0.1‘,9998) sk = socket.socket() sk.connect(ip_port) sk.sendall(bytes(‘这是 client !‘,‘utf-8‘)) server_replay = sk.recv(1024) print(str(server_replay,‘utf-8‘)) while True: #区别在这里,增加输入,然后返回 client_raw = input(‘>> ‘).strip() sk.sendall(bytes(client_raw,‘utf-8‘)) server_replay = sk.recv(1024) print(‘server:‘,str(server_replay,‘utf-8‘)) sk.close()