类的方法进阶:
静态方法:在类的方法前面加上装饰器@staticmethod,类的内置方法变为静态方法。变为静态方法后,下面的方法变成了函数,需要传入参数self,与类关系不大。示例如下:
1 class Dog(object): 2 def __init__(self,name): 3 self.name=name 4 5 @staticmethod#变为静态方法后,下面的方法变成了函数,需要传入参数self,与类关系不大 6 def eat(self,food): 7 print('%s is eating %s'%(self.name,food)) 8 d1=Dog('wangcai') 9 d2=Dog('shamo') 10 d1.eat(self=d1,food='chicken')#调用形式和类差不多,self需要传参数 11 d1.eat(d2,'gourou')
类方法:在类的方法前面加上装饰器@classmethod,类的内置方法变为类方法。类方法,只能访问类变量,无法访问实例变量,self=类名Dog。示例如下:
#类方法:只能访问类变量,不能访问实例变量 class Dog(object): name='哈士奇' def __init__(self,name): self.name=name @classmethod#类方法,只能访问类变量,无法访问实例变量,self=类名Dog def eat(self,food): print('%s is eating %s'%(self.name,food)) d1=Dog('wangcai') d2=Dog('shamo') d2.eat('chicken') d1.eat('gourou')
属性方法:在类的方法前加上装饰器@property,将类的方法变为一个静态属性。属性方法把一个方法变成静态属性,隐藏实现细节,不能调用,不能传入参数。传入参数,需要添加一个带装饰器@静态属性名.setter的方法,此时给静态属性赋值,相当于传参。示例如下:
#属性方法:把一个方法变成静态属性,隐藏实现细节 class Dog(object): name='哈士奇' def __init__(self,name): self.name=name self.__food=None self.__character=None @property#属性方法,此时.eat作为一个变量,但不能赋值,也不能传参数 def eat(self): print("%s is eating %s."%(self.name,self.__food)) @eat.setter#此时可以传入一个参数,可通过给属性赋值 def Eat(self,food): print('set food to:%s'%food) self.__food=food @eat.deleter def EAT(self): del self.__food print('You have deleted "eat".') d1=Dog('wangcai') d2=Dog('shamo') #d1.eat(food='rou') #d2.eat(food='chicken') #d1.eat(food='gourou') d1.eat d1.Eat=d2.name#调用属性eat,传入参数d2.name d1.eat #删除属性方法定义的属性,默认无法删除 #del d1.EAT#没有定义@eat.deleter时会报错,定义后可以删除
class Flight(object): def __init__(self,name): self.flight_name = name def checking_status(self): print("checking flight %s status " % self.flight_name) return 1 @property def flight_status(self): status = self.checking_status() if status == 0 : print("flight got canceled...") elif status == 1 : print("flight is arrived...") elif status == 2: print("flight has departured already...") else: print("cannot confirm the flight status...,please check later") f = Flight("CA980") f.flight_status
__mateclass__方法:其用来表示该类由谁来实例化创建。
类的生成 调用 顺序依次是 __new__ --> __init__ --> __call__
def __new__(cls, *args, **kwargs),会在类实例化的时候自动执行,执行顺序在__init__()之前,是用来创建实例的
class MyType(type): def __init__(self,*args,**kwargs): print("Mytype __init__",*args,**kwargs) def __call__(self, *args, **kwargs):#通过call创建new print("Mytype __call__", *args, **kwargs) obj = self.__new__(self) print("obj ",obj,*args, **kwargs) print(self) self.__init__(obj,*args, **kwargs) return obj def __new__(cls, *args, **kwargs): print("Mytype __new__",*args,**kwargs) return type.__new__(cls, *args, **kwargs) print('here...') class Foo(object,metaclass=MyType): #class Foo(object): #__metatype__=MyType def __init__(self,name): self.name = name print("Foo __init__") def __new__(cls, *args, **kwargs):#不写默认继承object.__new__,写了就会重构 print("Foo __new__",cls, *args, **kwargs) return object.__new__(cls)#缺少这一句构造函数不会执行,通过__new__来实例化,new调用init。 #return调用父类的new方法,cls传递一个类 f = Foo("Alex") # print("f",f) # print("fname",f.name)
类的定义方式:分为普通定义方式和特殊定义方式。
#创建类的方式 #普通方式定义类 class Foo(object): def __init__(self,name): self.name=name f=Foo('wulihuang') #特殊方式定义类 def func(self,number): print('hehe',self.name,self.age) print('number:%s'%number) def __init__(self,name,age): self.name=name self.age=age Foo1=type('Foo1',(object,),{'hello':func, '__init__':__init__})#type为类的类 #type的三个参数,第一个为类名,第二个为类的基类,第三个为类的成员,可以加入构造函数等 f1=Foo1('diaocan',18) f1.hello(15)
类的字典操作:
#__getitem__获取数据 # __setitem__设置数据 # __delitem__删除数据 class Foo(object): def __init__(self): self.data={'k1':'zhaoyu'} def __getitem__(self, key): print('__getitem__', key) return self.data.get(key) def __setitem__(self, key, value): print('__setitem__', key, value) self.data[key]=value def __delitem__(self, key): print('__delitem__', key) del self.data[key] obj = Foo() print(obj['k1']) # 自动触发执行 __getitem__ obj['k2'] = 'alex' # 自动触发执行 __setitem__ print(obj.data) del obj['k1'] print(obj.data)
反射:
通过字符串映射或修改程序运行时的状态、属性、方法, 实现动态的内存装配,有以下4个方法:
hasattr(obj, name, /) 判断一个对象里是否有叫’name‘的属性或方法。
getattr(object, name[, default]) -> value 从对象获取命名属性; getattr(x,'y')相当于x.y,如果给出了默认参数,则在属性不存在时返回它; 没有它,在这种情况下会引发Exception。
setattr(obj, name, value, /), 将给定对象的命名属性设置为指定值,setattr(x,'y',v)相当于``x.y = v''
delattr(x,'y')从对象x里删除属性,相当于del x.y
#反射:通过字符串映射或修改程序运行时的状态、属性、方法, 实现动态的内存装配,有以下4个方法 #hasattr(obj, name, /) 判断一个对象里是否有叫’name‘的属性或方法。 #getattr(object, name[, default]) -> value 从对象获取命名属性; getattr(x,'y')相当于x.y,如果给出了默认参数,\ # 则在属性不存在时返回它; 没有它,在这种情况下会引发Exception。 #setattr(obj, name, value, /), 将给定对象的命名属性设置为指定值,setattr(x,'y',v)相当于``x.y = v'' #delattr(x,'y')从对象x里删除属性,相当于del x.y 。 def burk(self): print('%s is barking'%self.name) class Dog(object): def __init__(self,name,sex): self.name=name self.sex=sex def eat(self,food): print('%s is eating %s'%(self.name,food)) d1=Dog('wangcai','M') choice=input('>>:').strip() print(hasattr(d1,choice))#判断d1中是否有属性或方法choice print(getattr(d1,choice,'noexist'))#打印的d1.choice内存地址,不存在时返回noexist if hasattr(d1,choice): getattr(d1,choice)('gutou') else: setattr(d1,choice,burk) getattr(d1,choice)(d1)#需要传入参数self # delattr(d1,choice) # print(d1.name)
异常处理:
异常处理作用:在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户看见大黄页!!!
常用的异常:
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常
FileNotFoundError 找不到文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
示例:
#异常处理作用: #在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户看见大黄页!!! #示例 list1=['zhaoyu','nvbu','wusong'] dict1={} try:#出现第一个异常后便执行except,后面的异常无法判断 dict1['name'] list1[6] open('hheh.txt', 'r', encoding='uft-8') except IndexError as e:#except (IndexError,KeyError) as e:同时判断两种异常 print('列表序号错误,超出最大序号',e) except KeyError as e:#可以写多次 print('这个key %s 不存在'%e) except Exception as e:#能抓住大部分错误,但是无法定位错误 print('未知错误',e) else:#没出错的时候执行 print('一切正常') finally: print('finally 不管有没有错都执行') #常用的异常 # AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x # IOError 输入/输出异常 #FileNotFoundError 找不到文件 # ImportError 无法引入模块或包;基本上是路径问题或名称错误 # IndentationError 语法错误(的子类) ;代码没有正确对齐 # IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] # KeyError 试图访问字典里不存在的键 # KeyboardInterrupt Ctrl+C被按下 # NameError 使用一个还未被赋予对象的变量 # SyntaxError Python代码非法,代码不能编译 # TypeError 传入对象类型与要求的不符合 # UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, # 导致你以为正在访问它 # ValueError 传入一个调用者不期望的值,即使值的类型是正确的 #自定义异常 class UserDifinedException(Exception):#自定义异常类,继承Exception def __init__(self, msg): self.message = msg def __str__(self):#继承了Exception,可以不重构__str__ return self.message try: raise UserDifinedException('自定义异常')#主动触发,raise触发 except UserDifinedException as e: print(e)
动态导入模块:
动态导入模块方法1: __import__ 说明: 1. 函数功能用于动态的导入模块,主要用于反射或者延迟加载模块。 2. __import__(module)相当于import module 举例说明: 首先创建一个模块目录lib,然后在目录内创建一个模块为:aa.py 模块代码为: class c(object): def __str__(self): return 'C language' 在lib目录平级新建一个测试的模块,使用 __import__ 动态以字符串形式导入lib下的aa模块。 lib = __import__('lib.aa') # 相当于import lib c = lib.aa.c() print(c) 动态导入模块方法2:import importlib 实例还是上面的lib.aa模块,这里使用importlib进行动态导入(这个方法好理解,也是官方建议使用的) import importlib aa = importlib.import_module('lib.aa') c = aa.c() print(c)
Socket网络编程:
网络协议:http网站,smtp email,dns把域名解析成IP地址,ftp下载上传文件,ssh,snmp简单网络通信协议,
icmp ping包测试网路通不通,dhcp IP地址分配
数据通信:通过通信协议进行发和收,send和receive,数据流交换
OSI(Open System Interconnection)七层模型:从上到下如下
应用层:网络服务与最终用户的一个接口,协议有:HTTP FTP TFTP SMTP SNMP DNS。
表示层:数据的表示、安全、压缩。(在五层模型里面已经合并到了应用层),格式有,JPEG、ASCll、DECOIC、加密格式等。
会话层:建立、管理、终止会话。(在五层模型里面已经合并到了应用层)。对应主机进程,指本地主机与远程主机正在进行的会话。
传输层:定义传输数据的协议端口号,以及流控和差错效验。协议有:TCP和UDP,数据包一旦离开网卡即进入网络传输层。
网络层:进行逻辑地址寻址,实现不同网络之间的路径选择。协议有:ICMP IGMP IP(IPV4 IPV6) ARP RARP(地址簇)。识别IP地址,
数据链路层 (Link):建立逻辑连接、进行硬件地址寻址、差错效验等功能。(由底层网络定义协议)。\
将比特组合成字节进而组合成帧,用MAC地址访问介质,错误发现但不能纠正。不认识IP地址。MAC地址:物理地址,16进制
物理层(Physical Layer):建立、维护、断开物理连接。(由底层网络定义协议)。
TCP/IP通信:三次握手,四次断开
TCP/IP连接
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,\
此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,\
客户端和服务器进入ESTABLISHED状态,完成三次握手。
TCP/IP断开
1、建立连接后,任意一方调用close()函数后,向对方发生FIN=M数据包,进入FIN_WAIT_1状态。FIN(finish缩写)
2、被动关闭端收到FIN数据包后,检测到设置了FIN标志位,发送一个ACK=M+1给主动关闭端,被动端进入CLOSE_WAIT状态。
3、被动端发送一个FIN=k数据包给主动端,被动端进入FIN_WAIT_2状态。
4、主动断开端收到被动端的FIN数据包,进入TIME_WAIT状态,发生一个ACK=k+1给被动端,被动端进入CLOSE状态。
UDP协议:
UDP协议并不提供数据传送的保证机制。如果在从发送方到接收方的传递过程中出现数据报的丢失,/
协议本身并不能做出任何检测或提示。因此,通常人们把UDP协议称为不可靠的传输协议。UDP具有TCP所望尘莫及的速度优势。
socket:将数据的send、receive等数据流交换进行封装,调用的接口。
一台机器:总共开放的port数为65535。Nginx(网站)默认为port80,Mysql默认为3306
IP地址:定位计算机
port:定位计算机上的程序
实现通信,需要IP加端口port
Socket Families(地址簇)
socket.AF_UNIX unix本机进程间通信
socket.AF_INET IPV4
socket.AF_INET6 IPV6
Socket Types
socket.SOCK_STREAM #for tcp
socket.SOCK_DGRAM #for udp
socket.SOCK_RAW #原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;\
其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
socket.SOCK_RDM #是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,\
在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
示例:
#socket客户端 import socket #socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)#第一参数为数据簇,默认为IPV4,第二个为协议类型,默认为TCP client=socket.socket()#定义数据簇和协议类型,socket在socket.py里是一个类,进行实例化 client.connect(('localhost',8002))#只能接受一个参数,需要IP地址和端口号1,所以以元组形式传入,连接服务器端 #client.send(data,flags=None)向服务端传输data,data必须为字符串型 client.send(b'hello world!')#向服务器端传输数据字符串‘hello world!’,python3里发送类型必须为bytes。 client.send('吴礼辉'.encode('utf-8'))#中文转化为bytes类型 n=1 while n<2: msg=input('>>:').strip() if len(msg)==0:continue client.send(msg.encode('utf-8')) #bytes只能转化ASCLL的数据类型 #client.recv(buffersize,flags=None)接受来自服务器端的数据,buffersize定义接受字节的数量 data=client.recv(1024000000)#最多接收1024个字节(1kb),超过的部分留在缓冲区排队,下次继续接收 print('recv: ',data.decode()) if msg=='q': n=2 client.close()
#socket 服务器端 import socket server=socket.socket()#定义数据簇和协议类型,socket在socket.py里是一个类,进行实例化 #server.bind(address)捆绑socket到固定地址,对于IP sockets,地址是数据对(host,port) server.bind(('localhost',8002))#绑定要监听的端口 #server.listen(backlog=None)#使服务器接受连接,不自定义backlog会自动选择合适的值 server.listen(5)#监听,5表示最大允许5个连接挂起 print('等待连接') while True:#一个客户端断开后,等待另一个客户端连接 #server.accept()等待传入连接。 return正在连接的新socket实例以及客户端的address。 对于IP套接字,地址信息是一对(hostaddr,端口)。 conn,addr=server.accept()#等待连接 #conn是客户端连接过来后,服务器端为其生成的连接实例 print(conn,'\r\n',addr) print('连接成功') while True:#实现客户端与服务端的多个数据交互 data=conn.recv(10240000)#不选择server.recv(),这样可以同时连入多个客户端 print('server recv:',data.decode()) if not data: print('客户端连接失败') break conn.send(data.upper()) server.close()