标签:
本节内容:
1. 面向对象高级语法部分
1.1 静态方法、类方法、属性方法
1.2 类的特殊方法
1.3 反射
2. 异常处理
3. Socket开发基础
1) 静态方法
通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法。普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法。
1 class Dog(object): 2 3 def __init__(self, name): 4 5 self.name = name 6 7 8 9 @staticmethod # 把eat方法变为静态方法 10 11 def eat(self): 12 13 print("%s is eating" % self.name) 14 15 16 17 18 19 d = Dog("taidi") 20 21 d.eat()
上面的调用会出以下错误,说是eat需要一个self参数,但调用时却没有传递,没错,当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了。
1 <span style="color: #ff0000;">Traceback (most recent call last): 2 3 File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/静态方法.py", line 9, in <module> 4 5 d.eat() 6 7 TypeError: eat() missing 1 required positional argument: ‘self‘ 8 9 </span>
想让上面的代码可以正常工作有两种办法:
1 class Dog(object): 2 3 4 5 def __init__(self,name): 6 7 self.name = name 8 9 10 11 @staticmethod 12 13 def eat(): 14 15 print(" is eating") 16 17 18 19 d = Dog("taidi") 20 21 d.eat() 22
2) 类方法
类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量。
1 class Dog(object): 2 3 def __init__(self, name): 4 5 self.name = name 6 7 8 9 @classmethod 10 11 def eat(self): 12 13 print("%s is eating" % self.name) 14 15 16 17 18 19 d = Dog("taidi") 20 21 d.eat()
执行报错如下,说Dog没有name属性,因为name是个实例变量,类方法是不能访问实例变量的.
1 Traceback (most recent call last): 2 3 File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/类方法.py", line 16, in <module> 4 5 d.eat() 6 7 File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/类方法.py", line 11, in eat 8 9 print("%s is eating" % self.name) 10 11 AttributeError: type object ‘Dog‘ has no attribute ‘name‘
此时可以定义一个类变量,也叫name,看下执行效果:
1 class Dog(object): 2 3 name = "我是类变量" 4 5 6 7 def __init__(self, name): 8 9 self.name = name 10 11 12 13 @classmethod 14 15 def eat(self): 16 17 print("%s is eating" % self.name) 18 19 20 21 22 23 d = Dog("taidi") 24 25 d.eat() 26 27 28 29 # 执行结果 30 31 32 33 我是类变量 is eating 34
3) 属性方法
属性方法的作用就是通过@property把一个方法变成一个静态属性
1 class Dog(object): 2 3 def __init__(self, name): 4 5 self.name = name 6 7 8 9 @property 10 11 def eat(self): 12 13 print(" %s is eating" % self.name) 14 15 16 17 18 19 d = Dog("taidi") 20 21 d.eat()
调用会出以下错误,说NoneType is not callable, 因为eat 此时已经变成一个静态属性,不是方法了,想调用已经不需要加()号了,直接d.eat就可以.
d = Dog("taidi") d.eat
输出
taidi is eating
属性方法实例--查询航班
1 class Flight(object): 2 def __init__(self, name): 3 self.flight_name = name 4 5 def checking_status(self): 6 print("checking flight %s status" % self.flight_name) 7 return 1 8 9 @property 10 def flight_status(self): 11 status = self.checking_status() 12 if status == 0: 13 print("航班取消。。。") 14 elif status == 1: 15 print("航班到达") 16 elif status == 2: 17 print("航班延迟") 18 else: 19 print("无法确定航班状态") 20 21 f = Flight("CA980") 22 f.flight_status
现在我只能查询航班状态, 既然这个flight_status已经是个属性了, 那我能否给它赋值呢?
f = Flight("CA980") f.flight_status f.flight_status = 2
输出结果说不能更改这个属性:
1 checking flight CA980 status 2 flight is arrived... 3 Traceback (most recent call last): 4 File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/属性方法.py", line 58, in <module> 5 f.flight_status = 2 6 AttributeError: can‘t set attribute
通过@proerty.setter装饰器再装饰一下就可以改了,此时需要一个新方法对这个flight_status进行更改:
1 class Flight(object): 2 def __init__(self, name): 3 self.flight_name = name 4 5 def checking_status(self): 6 print("checking flight %s status" % self.flight_name) 7 return 1 8 9 @property 10 def flight_status(self): 11 status = self.checking_status() 12 if status == 0: 13 print("航班取消。。。") 14 elif status == 1: 15 print("航班到达") 16 elif status == 2: 17 print("航班延迟") 18 else: 19 print("无法确定航班状态") 20 @flight_status.setter # 修改属性方法 21 def flight_status(self, status): 22 status_dic = { 23 0: "取消", 24 1: "到达", 25 2: "延迟", 26 } 27 print("\033[31;1m修改航班状态为%s\033[;0m" % status_dic.get(status)) 28 @flight_status.deleter #删除 29 def flight_status(self): 30 print("删除航班状态") 31 32 f = Flight("CA980") 33 f.flight_status 34 35 f.flight_status = 2 # 触发@flight_status.setter 36 del f.flight_status # 触发@flight_status.deleter
1)__doc__ 表示类的描述信息
1 class Foo: 2 """ 描述类信息,这是定义狗的类 """ 3 4 def func(self): 5 pass 6 7 8 print 9 Foo.__doc__ 10 # 输出:类的描述信息
View Code
2) __module__ 和 __class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
class C: def __init__(self): self.name = ‘Jack‘
View Code
调用C类:
from lib.aa import C obj = C() print obj.__module__ # 输出 lib.aa,即:输出模块 print obj.__class__ # 输出 lib.aa.C,即:输出类
View Code
3) __init__ 构造方法,通过类创建对象时,自动触发执行。
略
4)__del__
析构方法,当对象在内存中被释放时,自动触发执行。
5) __call__ 对象后面加括号,触发执行。
1 class Foo: 2 def __init__(self): 3 pass 4 5 def __call__(self, *args, **kwargs): 6 print 7 ‘__call__‘ 8 9 10 obj = Foo() # 执行 __init__ 11 obj() # 执行 __call__ 12 13
6) __dict__ 查看类或对象中的所有成员
1 class Province: 2 country = ‘China‘ 3 4 def __init__(self, name, count): 5 self.name = name 6 self.count = count 7 8 def func(self, *args, **kwargs): 9 print 10 ‘func‘ 11 12 13 # 获取类的成员,即:静态字段、方法、 14 print 15 Province.__dict__ 16 # 输出:{‘country‘: ‘China‘, ‘__module__‘: ‘__main__‘, ‘func‘: <function func at 0x10be30f50>, ‘__init__‘: <function __init__ at 0x10be30ed8>, ‘__doc__‘: None} 17 18 obj1 = Province(‘HeBei‘, 10000) 19 print 20 obj1.__dict__ 21 # 获取 对象obj1 的成员 22 # 输出:{‘count‘: 10000, ‘name‘: ‘HeBei‘} 23 24 obj2 = Province(‘HeNan‘, 3888) 25 print 26 obj2.__dict__ 27 # 获取 对象obj1 的成员 28 # 输出:{‘count‘: 3888, ‘name‘: ‘HeNan‘}
View Code
7)__str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
1 class Foo: 2 def __str__(self): 3 return ‘alex li‘ 4 5 6 obj = Foo() 7 print 8 obj 9 # 输出:alex li
View Code
8)__getitem__、__setitem__、__delitem__
用于索引操作,如字典。以上分别表示获取、设置、删除数据
1 class Foo(object): 2 def __getitem__(self, key): 3 print(‘__getitem__‘, key) 4 5 def __setitem__(self, key, value): 6 print(‘__setitem__‘, key, value) 7 8 def __delitem__(self, key): 9 print(‘__delitem__‘, key) 10 11 12 obj = Foo() 13 14 result = obj[‘k1‘] # 自动触发执行 __getitem__ 15 obj[‘k2‘] = ‘alex‘ # 自动触发执行 __setitem__ 16 del obj[‘k1‘] 17 18
9) __new__ \ __metaclass__
1 obj = Foo() 2 obj["name"] = "Tom" 3 #obj["name"] 4 print(obj.data) 5 6 7 class Foo(object): 8 def __init__(self, name): 9 self.name = name 10 11 12 f = Foo("alex")
上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象。
如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。
print type(f) # 输出:<class ‘__main__.Foo‘> 表示,obj 对象由Foo类创建
print type(Foo) # 输出:<type ‘type‘>
表示,Foo类对象由 type 类创建
所以,f对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。
那么,创建类就可以有两种方式:
a) 普通方式
1 class Foo(object): 2 def func(self): 3 print 4 ‘hello Jack‘
b) 特殊方式
1 def func(self): 2 print 3 ‘hello wupeiqi‘ 4 5 6 Foo = type(‘Foo‘, (object,), {‘func‘: func}) 7 # type第一个参数:类名 8 # type第二个参数:当前类的基类 9 # type第三个参数:类的成员
加上构造方法:
1 def func(self): 2 print("hello %s"%self.name) 3 4 def __init__(self,name,age): 5 self.name = name 6 self.age = age 7 Foo = type(‘Foo‘,(object,),{‘func‘:func,‘__init__‘:__init__}) 8 9 f = Foo("jack",22) 10 f.func()
通过字符串映射或修改程序运行时的状态、属性、方法, 有以下4个方法:
1) getattr(object, name, default=None)
1 def getattr(object, name, default=None): # known special case of getattr 2 """ 3 getattr(object, name[, default]) -> value 4 5 Get a named attribute from an object; getattr(x, ‘y‘) is equivalent to x.y. 6 When a default argument is given, it is returned when the attribute doesn‘t 7 exist; without it, an exception is raised in that case. 8 """ 9 pass
2) hasattr(object,name)
判断object中有没有一个name字符串对应的方法或属性
3) setattr(x, y, v)
1 def setattr(x, y, v): # real signature unknown; restored from __doc__ 2 """ 3 Sets the named attribute on the given object to the specified value. 4 5 setattr(x, ‘y‘, v) is equivalent to ``x.y = v‘‘
4) delattr(x, y)
1 def delattr(x, y): # real signature unknown; restored from __doc__ 2 """ 3 Deletes the named attribute from the given object. 4 5 delattr(x, ‘y‘) is equivalent to ``del x.y‘‘ 6 """ 7 8
反射代码示例
1 class Foo(object): 2 def __init__(self): 3 self.name = ‘Jack‘ 4 5 def func(self): 6 return ‘func‘ 7 8 9 obj = Foo() 10 11 # #### 检查是否含有成员 #### 12 hasattr(obj, ‘name‘) 13 hasattr(obj, ‘func‘) 14 15 # #### 获取成员 #### 16 getattr(obj, ‘name‘) 17 getattr(obj, ‘func‘) 18 19 # #### 设置成员 #### 20 setattr(obj, ‘age‘, 18) 21 setattr(obj, ‘show‘, lambda num: num + 1) 22 23 # #### 删除成员 #### 24 delattr(obj, ‘name‘) 25 delattr(obj, ‘func‘)
在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户看见大黄页!!!
1 try: 2 pass 3 except Exception as e: 4 pass
需求:将用户输入的两个数字相加
1 while True: 2 num1 = raw_input(‘num1:‘) 3 num2 = raw_input(‘num2:‘) 4 try: 5 num1 = int(num1) 6 num2 = int(num2) 7 result = num1 + num2 8 except Exception as e: 9 print ‘出现异常,信息如下:‘ 10 print(e)
2.2 异常种类
常用异常:
更多异常
1 ArithmeticError 2 3 AssertionError 4 5 AttributeError 6 7 BaseException 8 9 BufferError 10 11 BytesWarning 12 13 DeprecationWarning 14 15 EnvironmentError 16 17 EOFError 18 19 Exception 20 21 FloatingPointError 22 23 FutureWarning 24 25 GeneratorExit 26 27 ImportError 28 29 ImportWarning 30 31 IndentationError 32 33 IndexError 34 35 IOError 36 37 KeyboardInterrupt 38 39 KeyError 40 41 LookupError 42 43 MemoryError 44 45 NameError 46 47 NotImplementedError 48 49 OSError 50 51 OverflowError 52 53 PendingDeprecationWarning 54 55 ReferenceError 56 57 RuntimeError 58 59 RuntimeWarning 60 61 StandardError 62 63 StopIteration 64 65 SyntaxError 66 67 SyntaxWarning 68 69 SystemError 70 71 SystemExit 72 73 TabError 74 75 TypeError 76 77 UnboundLocalError 78 79 UnicodeDecodeError 80 81 UnicodeEncodeError 82 83 UnicodeError 84 85 UnicodeTranslateError 86 87 UnicodeWarning 88 89 UserWarning 90 91 ValueError 92 93 Warning 94 95 ZeroDivisionError
实例:IndexError
1 dic = ["Jack", ‘Rose‘] 2 try: 3 dic[10] 4 except IndexError as e: 5 print(e)
实例:KeyError
1 dic = {‘k1‘:‘v1‘} 2 try: 3 dic[‘k20‘] 4 except KeyError as e: 5 print(e)
实例:ValueError
1 s1 = ‘hello‘ 2 try: 3 int(s1) 4 except ValueError as e: 5 print(e)
写程序时需要考虑到try代码块中可能出现的任意异常,可以这样写:
1 s1 = ‘hello‘ 2 try: 3 int(s1) 4 except IndexError as e: 5 print e 6 except KeyError as e: 7 print e 8 except ValueError as e: 9 print(e)
万能异常 在python的异常中,有一个万能异常:Exception,他可以捕获任意异常,即:
s1 = ‘hello‘ try: int(s1) except Exception as e: print(e)
对于特殊处理或提醒的异常需要先定义,最后定义Exception来确保程序正常运行。
1 s1 = ‘hello‘ 2 try: 3 int(s1) 4 except KeyError as e: 5 print(‘键错误‘) 6 except IndexError as e: 7 print(‘索引错误‘) 8 except Exception as e: 9 print(‘错误’)
1 try: 2 # 主代码块 3 pass 4 except KeyError as e: 5 # 异常时,执行该块 6 pass 7 else: 8 # 主代码块执行完,执行该块 9 pass 10 finally: 11 # 无论异常与否,最终执行该块 12 pass
try: raise Exception(‘错误了。。。‘) except Exception as e: print(e)
1 class MyException(Exception): 2 def __init__(self, msg): 3 self.message = msg 4 5 def __str__(self): 6 return self.message 7 8 9 try: 10 raise MyException(‘我的异常‘) 11 except MyException as e: 12 print(e)
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用【打开】【读写】【关闭】模式来操作。socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)
socket和file的区别:
socket server 端代码:
1 import socket 2 3 ip_port = (‘127.0.0.1‘,9999) 4 5 sk = socket.socket() 6 sk.bind(ip_port) 7 sk.listen(5) 8 9 while True: 10 print(‘server waiting...‘) 11 conn,addr = sk.accept() 12 13 client_data = conn.recv(1024) 14 print(client_data) 15 conn.sendall(‘不要回答‘) 16 17 conn.close()
socket client 端代码:
1 import socket 2 ip_port = (‘127.0.0.1‘, 9999) 3 4 sk = socket.socket() 5 sk.connect(ip_port) 6 7 sk.sendall(‘请求占领地球‘) 8 9 server_reply = sk.recv(1024) 10 print(server_reply) 11 12 sk.close()
web服务应用:
1 import socket 2 3 4 def handle_request(client): 5 buf = client.recv(1024) 6 client.send("HTTP/1.1 200 OK\r\n\r\n") 7 client.send("Hello, World") 8 9 10 def main(): 11 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 12 sock.bind((‘localhost‘, 8080)) 13 sock.listen(5) 14 15 while True: 16 connection, address = sock.accept() 17 handle_request(connection) 18 connection.close() 19 20 21 if __name__ == ‘__main__‘: 22 main()
更多功能:
sk = 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 ,则系统就会根据地址格式和套接类别,自动选择一个合适的协议。
Python自动化 【第七篇】:Python基础-面向对象高级语法、异常处理、Scoket开发基础
标签:
原文地址:http://www.cnblogs.com/ZhPythonAuto/p/5855864.html