一、面向对象进阶-高级语法
1.多态【上节回顾】
python中不存在多态方法,但是我们可以自己实现多态的功能
2.类中的装饰器
1)classmethod
类方法,不能访问实例变量class Animal(object): c_name = 100 def __init__(self,name): self.name = name @classmethod #类方法 def eat(self): #使用self来调用类变量 print("%s is eating..." % self.c_name) #可以调用类变量 #print("%s is eating..." % self.name) #错误,不能调用实例变量
2)staticmethod
静态方法,不能访问类变量和实例变量 【用途】:没啥用,作为类的“工具箱”,作为一种组织形式class Animal(object): c_name = 100 def __init__(self,name): self.name = name @staticmethod def sleep(): print("staticmethod ...") #print("%s is eating..." % self.c_name) #不能调用类变量 #print("%s is eating..." % self.name) #也不能调用实例变量
3)property
把方法变成属性, 不需要加括号调用 可以访问类变量和实例变量 不能传值,如果要传值,使用.setter的方法 【用途】:私有化在类变量前面加__:实现变量的私有化,外部实例不能访问该变量
非要访问:**_类名称__变量名**
3.多继承:广度优先
针对不同的类有点区别:
1)新式类(如class Animal(object)):广度优先
2)经典类(如class Animal):深度优先(python2.x),广度优先(python3.x)多继承中的优先选择策略:由深度优先向广度优先发展,在python2.x经典类中还使用深度优先的方式,到python3.x中已经全部采用广度优先的方式了,下面是一个广度优先的例子:
class A(object): n = 100 def f1(self): #BC父类f1方法 print("f1 from A")class B(A): n = 100 def f1(self): #D的父类f1方法 print("f1 from B")class C(A): n = 100 def f1(self): #D的父类f1方法 print("f1 from C")class D(B,C): n = 100 def f1(self): #D的f1方法 print("f1 from D")d = D()d.f1()
D的实例需要访问f1方法的时候,优先选择顺序如下:
D --> B --> C --> A自身方法-->父类1方法-->父类2方法-->父类的父类方法
下面的情形为怎么样?
class A1(object): n = 100 def f1(self): print("f1 from A1")class A2(object): n = 100 def f1(self): print("f1 from A2")class B(A1): n = 100 # def f1(self): # print("f1 from B")class C(A2): n = 100 def f1(self): print("f1 from C")class D(B,C): n = 100 # def f1(self): # print("f1 from D")d = D()d.f1()
揭晓答案:
#D-->B-->A1-->C-->A2f1 from A1
4.类的特殊成员
1)new:
class A(object): def __init__(self): print("____init___") def __new__(cls, *args, **kwargs): print("___new___")a = A()#___new___
2)call:
class A(object): def __init__(self): pass def __call__(self, *args, **kwargs): print("__call__")a = A()a()#__call__
3)__doc__等其他:
class A(object): ""这是一个测试类"" c_name = "alex" def __init__(self): self.name = "f" self.age = 12 self.job = "ITer"a = A()print(a.__doc__) #类注释信息print(a.__module__) #模块名称print(a.__class__) #模块名称.类名称print(a.__dict__) #实例变量字典
这是一个测试类__main__{'age': 12, 'job': 'ITer', 'name': 'f'}
5.反射
bogon:day07 yangfeilong$ more attr_test.py import sysclass WebServer(object): def __init__(self,name,host): self.name = name self.host = host def start(self): print("server is starting...") def stop(self): print("server is stoping...") def restart(self): self.stop() self.start()def run(name): print("%s is running..." % name)if __name__ == '__main__': server = WebServer("server","localhost") server2 = WebServer("server2","backupserver") #判断属性和获取属性 if hasattr(server,sys.argv[1]): func = getattr(server,sys.argv[1]) func() #修改属性 setattr(server,"s_run",run) server.s_run("hhha") #删除属性 delattr(server,"s_run") #server.s_run("hhha") #删除方法 #删除属性 print(server.name) delattr(server,"name") #print(server.name) #删除变量bogon:day07 yangfeilong$ python3 attr_test.py restartserver is stoping...server is starting...hhha is running...server
二、socket编程
编写一个类shell
服务器端:import socketimport timeimport subprocess ip_port = ('127.0.0.1',9998)sk = socket.socket()sk.bind(ip_port)sk.listen(5)while True: print('server waiting...') conn,addr = sk.accept() print(addr) while True: client_data = conn.recv(1024) if not client_data:break print("recv cmd:",str(client_data,'utf8')) cmd = str(client_data,"utf8").strip() cmd_call = subprocess.Popen(cmd,shell=True, stdout=subprocess.PIPE) cmd_result = cmd_call.stdout.read() if len(cmd_result) == 0: cmd_result = b"cmd execution has no output.." ack_msg = bytes("CMD_RESULT_SIZE|%s" %len(cmd_result) ,"utf8") conn.send(ack_msg) client_ack = conn.recv(50) if client_ack.decode() == 'CLIENT_READY_TO_RECV': conn.send(cmd_result ) conn.close()
客户端:#!/usr/bin/env python# -*- coding:utf-8 -*-import socketip_port = ('127.0.0.1',9998)sk = socket.socket()sk.connect(ip_port)while True: user_input = input("cmd:").strip() if len(user_input) == 0:continue if user_input == 'q':break sk.send(bytes(user_input,'utf8')) #ack_msg = b"CMD_RESULT_SIZE|%s" % len(cmd_result) server_ack_msg = sk.recv(100) cmd_res_msg = str(server_ack_msg.decode()).split("|") print("server response:",cmd_res_msg) if cmd_res_msg[0] =="CMD_RESULT_SIZE": cmd_res_size = int(cmd_res_msg[1]) sk.send(b"CLIENT_READY_TO_RECV") res = '' received_size = 0 while received_size < cmd_res_size: data = sk.recv(500) received_size += len(data) res += str(data.decode()) else: print(str(res)) print('-------recv done----')sk.close()