目录
- 面向对象高级语法部分
- 静态方法、类方法、属性方法
- 类的特殊方法
- 反射
- 异常处理
- Socket开发基础
静态方法
静态方法只是名义上归类管理,实际上在静态方法里访问不了类或实例中的任何属性
关键字:@staticmethod
作用:当在一个类中的某个方法上面加了@staticmethod关键字,那么这个方法就成为了静态方法,这个方法和类的唯一的关联关系就是在调用的时候需要通过实例化的类名进行调用,既然和类没有了关系,那么自然self关键字也不会被自动传入进去了。eg1:
需要注意的是:静态方法是不可以访问实例变量或类变量的,静态方法使一个实例里面得方法变为静态方法,此方法写的时候,如果还想用self的时候,在调用实例变量的时候,需要手动传入类名字eg2:
eg1:
class perople(object): def __init__(self,name,age): self.name = name self.age = age @staticmethod def eat(food): print('%s eat %s' %('Chenronghua',food))p1 = perople('chenronghua',28)p1.eat('baozi')
eg2:
class perople(object): def __init__(self,name,age): self.name = name self.age = age @staticmethod def eat(self,food): print('%s eat %s' %(self.name,food))p1 = perople('chenronghua',28)p1.eat(p1,'baozi')
静态方法是无法直接通过self调用类变量以及实例变量的
class perople(object): a = 123 def __init__(self,name,age): self.name = name self.age = age @staticmethod def eat(self,food): print('%s eat %s' %(self.a,food))p1 = perople('chenronghua',28)p1.eat('baozi') #输出
Traceback (most recent call last):
File "/Users/sean/python/s14/课堂/d7/静态类.py", line 29, in <module> p1.eat('baozi')TypeError: eat() missing 1 required positional argument: 'food'类方法
类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量
关键字:@classmethod
作用:类方法只能调用类变量,不能调用实例变量,实例变量为实例化一个实例的时候,传入的变量值称为类变量;隐藏实现细节
class perople(object): name = '我是类变量' def __init__(self,name,age): self.name = name self.age = age @classmethod def eat(self,food): print('%s eat %s' %(self.name,food))p1 = perople('chenronghua',28)p1.eat('baozi')
属性方法
关键字:@property
作用:属性方法可以理解为,把一个过程封装起来,对外调用的时候 编程一个变量的过程,不需再加上括号进行方法调用了
应用:举一个例子,假如要查一个航班信息的时候,客户查询的过程只需要调用这个属性就行,不需要调用这个方法,因为这里已经把这个方法变成一个属性了
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
eg2:
# Author:Sean sirclass Dog(object): def __init__(self,name): self.name = name self.__food = None @property def eat(self): print('%s eating %s!' %(self.name,self.__food)) @eat.setter def eat(self,food): print('food:%s' %food) self.__food = foodd = Dog('ChenRongHua')d.eat = 'baozi'd.eat'''输出food:baoziChenRongHua eating baozi!'''
删除属性,个人认为这里删除的并不是eat这个方法,而是删除的food这个传入的值
# Author:Sean sirclass Dog(object): def __init__(self,name): self.name = name self.__food = None @property def eat(self): print('%s eating %s!' %(self.name,self.__food)) @eat.setter def eat(self,food): print('food:%s' %food) self.__food = food @eat.deleter def eat(self): del self.__food print('删除成功')d = Dog('ChenRongHua')d.eat = 'baozi'd.eatdel d.eat'''删除属性#输出food:baoziChenRongHua eating baozi!删除成功'''
类的特殊成员方法
1. __doc__ 表示类的描述信息
# Author:Sean sirclass Dog(object): ''' 对这个类的进行描述,讲解类的作用 ''' def __init__(self,name): self.name = name self.__food = None @property def eat(self): print('%s eating %s!' %(self.name,self.__food)) @eat.setter def eat(self,food): print('food:%s' %food) self.__food = food @eat.deleter def eat(self): del self.__food print('删除成功')d = Dog('ChenRongHua')print(d.__doc__)'''输出 对这个类的进行描述,讲解类的作用'''
2.__module__和__class__
这两个方法没什么卵用,可以忽略不计,但是知道还是最好
__module__:表示当前操作的对象在那个模块
__class__:表示当前操作的对象的类是什么
# Author:Sean sirclass C: def __init__(self): self.name = 'wupeiqi'
# Author:Sean sirfrom lib.aa import Cobj = C()print (obj.__module__ ) # 输出 lib.aa,即:输出模块print (obj.__class__) # 输出 lib.aa.C,即:输出类
3. __init__ 构造方法,通过类创建对象时,自动触发执行。
4.__del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的
5.__call__ 对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
# Author:Sean sirclass Dog(object): ''' 对这个类的进行描述,讲解类的作用 ''' def __init__(self,name): self.name = name self.__food = None @property def eat(self): print('%s eating %s!' %(self.name,self.__food)) @eat.setter def eat(self,food): print('food:%s' %food) self.__food = food @eat.deleter def eat(self): del self.__food print('删除成功') def __call__(self, *args, **kwargs): print('run call funaction...',args,kwargs)d = Dog('ChenRongHua')d(1,2,3,name='sean')# 输出run call funaction... (1, 2, 3) { 'name': 'sean'}
6.__dic__ 查看类或实例中所有成员
# Author:Sean sirclass Dog(object): ''' 对这个类的进行描述,讲解类的作用 ''' def __init__(self,name): self.name = name self.__food = None def eat(self): print('%s eating %s!' %(self.name,self.__food))d = Dog('ChenRongHua')print(d.__dict__) # 打印实例属性,不包括类属性print(Dog.__dict__) # 打印所以类属性,不包括实例属性# 输出{ 'name': 'ChenRongHua', '_Dog__food': None}{ '__init__':, '__dict__': , '__module__': '__main__', '__weakref__': , '__doc__': '\n 对这个类的进行描述,讲解类的作用\n ', 'eat': }
7.__str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值
# Author:Sean sirclass Dog(object): ''' 对这个类的进行描述,讲解类的作用 ''' def __init__(self,name): self.name = name self.__food = None def eat(self): print('%s eating %s!' %(self.name,self.__food)) def __str__(self): return '测试一下'd = Dog('ChenRongHua')print(d)# 输出测试一下
8.__new__ \ __metaclass__
创建类并实例化对象的两种方法:
1)普通方法
# Author:Sean sir# 创建一个类class Foo(object): def __init__(self,name): self.name = name def fun(self,age): print(self.name,age)# 实例化一个对象f = Foo('sean')f.fun(28)
2)装逼方法
def func(self): print('hello %s' %self)Foo = type( 'Foo', (object,), { 'func': func} )f = Foof.func('sean')
在加上init的构造方法就可以了
def func(self): print('hello %s' %self.name)def __init__(self,name,age): self.name = name self.age = ageFoo = type( 'Foo', (object,), { 'func': func,'__init__':__init__} )f = Foo('sean',28)f.func()
So ,孩子记住,类 是由 type 类实例化产生
反射
hasattr方法
作用:判断一个类中是否包含某个方法或属性
class Dog(object): def __init__(self,name): self.name = name def eat(self,food): print('%s eating %s' %(self.name,food))D1 = Dog('Niuhanyang')user_input = input('>>>:').strip()print(hasattr(D1,user_input))# 输出>>>:talkFalse
# Author:Sean sirclass Dog(object): def __init__(self,name): self.name = name def eat(self,food): print('%s eating %s' %(self.name,food))D1 = Dog('Niuhanyang')user_input = input('>>>:').strip()print(hasattr(D1,user_input))# 输出>>>:eatTrue
getattr
作用:获取类中某个方法的内存地址或变量值
# Author:Sean sirclass Dog(object): def __init__(self,name): self.name = name def eat(self,food): print('%s eating %s' %(self.name,food))D1 = Dog('Niuhanyang')user_input = input('>>>:').strip()if hasattr(D1,user_input): fun = getattr(D1,user_input) print(fun)else: print('输入的方法不存在!')# 输出>>>:eat>
既然我们能拿到这个方法的内存地址,那么我们给他加上括号是不是就可以执行了呢?当然
class Dog(object): def __init__(self,name): self.name = name def eat(self,food): print('%s eating %s' %(self.name,food))D1 = Dog('Niuhanyang')user_input = input('>>>:').strip()if hasattr(D1,user_input): fun = getattr(D1,user_input) fun('不薄皮的榴莲!')else: print('输入的方法不存在!')# 输出>>>:eatNiuhanyang eating 不薄皮的榴莲!
setattr
作用: 动态的为类增加一个外面的方法或属性。
实例:判断一个类中是否包含某个方法,如果不包含那么就动态的增加一个外面的方法,然后并调用
# Author:Sean sirclass Dog(object): def __init__(self,name): self.name = name def eat(self,food): print('%s eating %s' %(self.name,food))D1 = Dog('Niuhanyang')user_input = input('>>>:').strip()# 如果输入的方法名不存在,那么使用setattr增加一个方法(前提是外部要有一个方法),然后使用getattr调用这个方法。最后传入的D1相当于talk方法中self参数def talk(self): print('%s is wang!wang!' %self.name)if hasattr(D1,user_input): fun = getattr(D1,user_input) user_input_2 = input('输入参数>>>:') fun(user_input_2)else: setattr(D1,user_input,talk) fun = getattr(D1,user_input) fun(D1)# 输出>>>:aaaNiuhanyang is wang!wang!
实例二: 动态装配一个属性,如果存在重新赋值,如果不存在增加这个属性,属性值并设置成None
# Author:Sean sirclass Dog(object): def __init__(self,name): self.name = name def eat(self,food): print('%s eating %s' %(self.name,food))while True: D1 = Dog('Niuhanyang') user_input = input('>>>:').strip() # 如果输入的变量名存在那么重新赋值成hanyang,如果不存在那么增加这个属性,并且赋值成Noneif hasattr(D1,user_input): key = getattr(D1,user_input) setattr(D1,user_input,'Hanyang') print(D1.name) else: setattr(D1,user_input,None) key = getattr(D1,user_input) print(key)# 输出>>>:nameHanyang>>>:ageNone
delattr
作用:删除类中的方法或属性
# Author:Sean sirclass Dog(object): def __init__(self,name): self.name = name def eat(self,food): print('%s eating %s' %(self.name,food))D1 = Dog( 'Niuhanyang' )user_input = input( '>>>:' ).strip( )# 判断用户输入的属性值是否存在,如果存在那么删除这个属性,然后再打印,这个时候就报错了。抛出'attributeError错误'if hasattr(D1,user_input): delattr(D1,user_input)print(D1.name)# 输出>>>:nameTraceback (most recent call last): File "/Users/sean/python/s14/课堂/d7/反射.py", line 17, inprint(D1.name)AttributeError: 'Dog' object has no attribute 'name'
异常处理
作用:当程序出错后,可以不被用户发现,并且出错后,整个程序还不会中断
使用方法:
try: ...... 代码块 ...... except XXXX as ErrorName: ...... print(ErrorName) # 这里的ErrorName是报错的详细信息 代码块 #当出现这个错后,将执行这块代码块 ......
当然except可以写多个,可以同时抓多个错误,看代码:
如果不使用异常处理,那么程序将直接报错
# Author:Sean sirname_list = ['sean','Jack','Tom']print(name_list[3])# 输出Traceback (most recent call last): File "/Users/sean/python/s14/课堂/d7/异常处理.py", line 4, inprint(name_list[3])IndexError: list index out of range
如果使用异常处理,那么就是另一番天地了
第一种使用方法:
# Author:Sean sirname_list = ['sean','Jack','Tom']try: print(name_list[3])except IndexError as ErrorInfo: print(ErrorInfo)# 输出list index out of range
当然我们知道如果出现indexError错误的一般都是下标越界导致,那么我们可以自定义一些打印信息啦,
第二种使用方法:
# Author:Sean sirname_list = ['sean','Jack','Tom']try: print(name_list[3])except IndexError as ErrorInfo: print('您输入的下标越界了,请检查代码了!')# 输出您输入的下标越界了,请检查代码了!
我们再来同时抓多个错误异常
第三种使用方法
# Author:Sean sirname_list = ['sean','Jack','Tom']try: print(name_dic['Jack']) print( name_list[3] )except IndexError as ErrorInfo: print('您输入的下标越界了,请检查代码了!')except NameError as ErrorInfo: print(ErrorInfo)# 输出name 'name_dic' is not defined
同时判断多个错误也可以这样写,但是这种错误我们无法判断到底是那句代码块出现的错误,因此不到万不得已我们不使用这种方法,
既然python支持这种写法,那么肯定有它的用处,用处就是不管出现那种错误,采用的都是一种处理办法。
第四种使用方法
# Author:Sean sirname_list = ['sean','Jack','Tom']try: print(name_dic['Jack']) print( name_list[3] )except (IndexError,NameError) as ErrorInfo: print(ErrorInfo)# 输出name 'name_dic' is not defined
第五种使用方法
python还支持同时抓N种错误,能抓到所有的python报错信息,据说还是有一些极个别的错误信息抓取不到,不建议使用,但是python既然支持,就有他的用处,
当我们在前面预判了好多错误,还是没能抓到报错的情况下,我们就使用Exception来抓取所有的错误,进行打印。这个也类似于windows里面的“未知错误”
# Author:Sean sirname_list = ['sean','Jack','Tom']try: # print(name_dic['Jack']) # print( name_list[3] ) open('Test.txt','r')except IndexError as ErrorInfo: print('您输入的下标越界了,请检查代码了!')except NameError as ErrorInfo: print(ErrorInfo)except Exception as ErrorInfo: print('未知错误',ErrorInfo)# 输出未知错误 [Errno 2] No such file or directory: 'Test.txt'
第六种使用方法
当所有的错误都没抓取到,那么证明代码块没有报错,则直接打印“一切正常”,当然你可以不打印。用在当代码中没有错误,我们执行后面的代码块
# Author:Sean sirname_list = ['sean','Jack','Tom']try: print( name_list[0] )except IndexError as ErrorInfo: print('您输入的下标越界了,请检查代码了!')except NameError as ErrorInfo: print(ErrorInfo)except Exception as ErrorInfo: print('未知错误',ErrorInfo)else: print('代码没有错误,一切正常!')# 输出sean代码没有错误,一切正常!
第七种使用方法
不管有没有错误,只会执行的代码块
# Author:Sean sirname_list = ['sean','Jack','Tom']try: # print(name_dic['Jack']) print( name_list[0] ) # open('Test.txt','r')except IndexError as ErrorInfo: print('您输入的下标越界了,请检查代码了!')except NameError as ErrorInfo: print(ErrorInfo)except Exception as ErrorInfo: print('未知错误',ErrorInfo)else: print('代码没有错误,一切正常!')finally: print('不管代码块有没有错,这里都会执行!')# 输出sean代码没有错误,一切正常!不管代码块有没有错,这里都会执行!
# Author:Sean sirname_list = ['sean','Jack','Tom']try: print(name_dic['Jack']) # print( name_list[0] ) # open('Test.txt','r')except IndexError as ErrorInfo: print('您输入的下标越界了,请检查代码了!')except NameError as ErrorInfo: print(ErrorInfo)except Exception as ErrorInfo: print('未知错误',ErrorInfo)else: print('代码没有错误,一切正常!')finally: print('不管代码块有没有错,这里都会执行!')# 输出name 'name_dic' is not defined不管代码块有没有错,这里都会执行!
第八种使用方法
自定义错误异常,下面的例子实现的大概流程如下:
首先定义一个类,这个类里面初始化了一个msg的变量;然后还定义了一个str的方法,这方法是如果打印这个类的时候默认打印这个方法的返回值;
然后使用raise关键字触发WupeiqiException这个错误,这个错误正好是上面这个类,并把‘我的异常’当做一个变量值穿进去了,当触发了这个错误,
然后打印e,e就是str这个方法的返回值
# Author:Sean sirclass WupeiqiException(Exception): def __init__(self, msg): self.message = msg def __str__(self): return self.messagetry: raise WupeiqiException('我的异常')except WupeiqiException as e: print (e) # 输出我的异常
用法我们学会了,我们来看一下异常的种类:
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性xIOError 输入/输出异常;基本上是无法打开文件ImportError 无法引入模块或包;基本上是路径问题或名称错误IndentationError 语法错误(的子类) ;代码没有正确对齐IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]KeyError 试图访问字典里不存在的键KeyboardInterrupt Ctrl+C被按下NameError 使用一个还未被赋予对象的变量SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)TypeError 传入对象类型与要求的不符合UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它ValueError 传入一个调用者不期望的值,即使值的类型是正确的
ArithmeticErrorAssertionErrorAttributeErrorBaseExceptionBufferErrorBytesWarningDeprecationWarningEnvironmentErrorEOFErrorExceptionFloatingPointErrorFutureWarningGeneratorExitImportErrorImportWarningIndentationErrorIndexErrorIOErrorKeyboardInterruptKeyErrorLookupErrorMemoryErrorNameErrorNotImplementedErrorOSErrorOverflowErrorPendingDeprecationWarningReferenceErrorRuntimeErrorRuntimeWarningStandardErrorStopIterationSyntaxErrorSyntaxWarningSystemErrorSystemExitTabErrorTypeErrorUnboundLocalErrorUnicodeDecodeErrorUnicodeEncodeErrorUnicodeErrorUnicodeTranslateErrorUnicodeWarningUserWarningValueErrorWarningZeroDivisionError
Socket编程
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用【打开】【读写】【关闭】模式来操作。socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)
socket和file的区别:
- file模块是针对某个指定文件进行【打开】【读写】【关闭】
- socket模块是针对 服务器端 和 客户端Socket 进行【打开】【读写】【关闭】
上述内容摘抄自 银角大王博客 地址:http://www.cnblogs.com/wupeiqi/articles/5040823.html
具体的socket是怎么在互联网中建立通讯连接的我们这里不在阐述,我们来写一下一个server、一个client使用socket在python中是怎么实现的
首先来写一个server端口:
# Author:Sean sirimport socketserver = socket.socket()server.bind(('127.0.0.1',1024))server.listen()while True: print('我要开始等电话了') conn,add = server.accept() while True: print('电话来了') data = conn.recv(1024) if not len(data):break print('rec:',data) conn.send(data.upper()) server.close()
再来写一个client端口:
# Author:Sean sirimport socketclient = socket.socket()client.connect(('127.0.0.1',1024))while True: user_input = input('>>:').strip() if not len(user_input): continue client.send(user_input.encode('utf-8')) data = client.recv(1024) print(data.decode('utf-8'))client.close()
参数介绍:
1.client = socket.socket()
socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) 参数一:地址簇 socket.AF_INET IPv4(默认) socket.AF_INET6 IPv6 socket.AF_UNIX 只能够用于单一的Unix系统进程间通信参数二:类型 socket.SOCK_STREAM 流式socket , for TCP (默认) socket.SOCK_DGRAM 数据报式socket , 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.SOCK_SEQPACKET 可靠的连续数据包服务参数三:协议 0 (默认)与特定的地址家族相关的协议,如果是 0 ,则系统就会根据地址格式和套接类别,自动选择一个合适的协议
2.server.bind(('127.0.0.1',1024))
s.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。
3.server.listen(backlog)
开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。
backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5
这个值不能无限大,因为要在内核中维护连接队列默认为None,表示不限制
4.conn,add = server.accept()
接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。
接收TCP 客户的连接(阻塞式)等待连接的到来
5.data = conn.recv(1024)
接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。
6.conn.send(data.upper())
将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。
conn.sendall(string[,flag])
将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
内部通过递归调用send,将所有内容发送出去。
7.server.close()
关闭套接字
需要注意的是,在py中socket传输都必须使用bytis类型进行传输,所以发送的时候,要对发送的数据,进行endoce一下
说一些例子中没有用到的关键字
sk.setblocking(bool) 是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。
sk.connect_ex(address)
连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061
sk.sendto(string[,flag],address)
将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。
sk.settimeout(timeout)
设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s )
sk.getpeername()
返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)
sk.getsockname()
返回套接字自己的地址。通常是一个元组(ipaddr,port)
sk.fileno()
套接字的文件描述符
摘抄自 银角大王博客 地址:http://www.cnblogs.com/wupeiqi/articles/5040823.html
0