标签:
本章学习要点:
要在类中使用静态方法,需在类成员函数前面加上@staticmethod标记符,以表示下面的成员函数是静态函数。使用静态方法的好处是,不需要定义实例即可使用这个方法。另外,多个实例共享此静态方法。
类方法与普通的成员函数和静态函数有不同之处,在接触的语言中好像也没见过这种语义,看它的定义:
一个类方法就可以通过类或它的实例来调用的方法, 不管你是用类来调用这个方法还是类实例调用这个方法,该方法的第一个参数总是定义该方法的类对象。
记住:方法的第一个参数都是类对象而不是实例对象.
按照惯例,类方法的第一个形参被命名为 cls.任何时候定义类方法都不是必须的(类方法能实现的功能都可以通过定义一个普通函数来实现,只要这个函数接受一个类对象做为参数就可以了).
python中实现静态方法和类方法都是依赖于python的修饰器来实现的。 对象方法有self参数,类方法有cls参数,静态方法是不需要这些附加参数的。
class TestClassMethod(object): METHOD = ‘method hoho‘ def __init__(self): self.name = ‘leon‘ def test1(self): print(‘test1‘) print(self) @classmethod def test2(cls): print(cls) print(‘test2‘) print(TestClassMethod.METHOD) print(‘----------------‘) @staticmethod def test3(): print(TestClassMethod.METHOD) print(‘test3‘) if __name__ == ‘__main__‘: a = TestClassMethod() a.test1() a.test2() a.test3() TestClassMethod.test3()
输出:
test1为实例方法
test2为类方法,第一个参数为类本身
test3为静态方法,可以不接收参数
类方法和静态方法皆可以访问类的静态变量(类变量),但不能访问实例变量,test2、test3是不能访问self.name的,而test1则可以
test1 <__main__.TestClassMethod object at 0x0061BD30> <class ‘__main__.TestClassMethod‘> test2 method hoho ---------------- method hoho test3 method hoho test3
属性方法的作用就是通过@property把一个方法变成一个静态属性
Python内置的@property
装饰器就是负责把一个方法变成属性调用的:
class Student(object): @property def score(self): return self._score @score.setter def score(self, value): if not isinstance(value, int): raise ValueError(‘score must be an integer!‘) if value < 0 or value > 100: raise ValueError(‘score must between 0 ~ 100!‘) self._score = value
@property
的实现比较复杂,我们先考察如何使用。把一个getter方法变成属性,只需要加上@property
就可以了,此时,@property
本身又创建了另一个装饰器@score.setter
,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作:
>>> s = Student() >>> s.score = 60 # OK,实际转化为s.set_score(60) >>> s.score # OK,实际转化为s.get_score() 60 >>> s.score = 9999 Traceback (most recent call last): ... ValueError: score must between 0 ~ 100!
注意到这个神奇的@property
,我们在对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过getter和setter方法来实现的。
还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性:
class Student(object): @property def birth(self): return self._birth @birth.setter def birth(self, value): self._birth = value @property def age(self): return 2016 - self._birth
上面的birth
是可读写属性,而age
就是一个只读属性,因为age
可以根据birth
和当前时间计算出来。
class Foo: """ 描述类信息,这是用于看片的神奇 """ def func(self): pass print Foo.__doc__ #输出:类的描述信息
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
class C: def __init__(self): self.name = ‘wupeiqi‘
from lib.aa import C obj = C() print obj.__module__ # 输出 lib.aa,即:输出模块 print obj.__class__ # 输出 lib.aa.C,即:输出类
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的
5. __call__ 对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print ‘__call__‘ obj = Foo() # 执行 __init__ obj() # 执行 __call__
class Province: country = ‘China‘ def __init__(self, name, count): self.name = name self.count = count def func(self, *args, **kwargs): print ‘func‘ # 获取类的成员,即:静态字段、方法、 print Province.__dict__ # 输出:{‘country‘: ‘China‘, ‘__module__‘: ‘__main__‘, ‘func‘: <function func at 0x10be30f50>, ‘__init__‘: <function __init__ at 0x10be30ed8>, ‘__doc__‘: None} obj1 = Province(‘HeBei‘,10000) print obj1.__dict__ # 获取 对象obj1 的成员 # 输出:{‘count‘: 10000, ‘name‘: ‘HeBei‘} obj2 = Province(‘HeNan‘, 3888) print obj2.__dict__ # 获取 对象obj1 的成员 # 输出:{‘count‘: 3888, ‘name‘: ‘HeNan‘}
class Foo: def __str__(self): return ‘alex li‘ obj = Foo() print obj # 输出:alex li
用于索引操作,如字典。以上分别表示获取、设置、删除数据
class Foo(object): def __getitem__(self, key): print(‘__getitem__‘,key) def __setitem__(self, key, value): print(‘__setitem__‘,key,value) def __delitem__(self, key): print(‘__delitem__‘,key) obj = Foo() result = obj[‘k1‘] # 自动触发执行 __getitem__ obj[‘k2‘] = ‘alex‘ # 自动触发执行 __setitem__ del obj[‘k1‘]
class Foo(object): def __init__(self,name): self.name = name f = Foo("alex")
通过字符串映射或修改程序运行时的状态、属性、方法, 有以下4个方法
class Foo(object): def __init__(self): self.name = ‘wupeiqi‘ def func(self): return ‘func‘ obj = Foo() # #### 检查是否含有成员 #### hasattr(obj, ‘name‘) hasattr(obj, ‘func‘) # #### 获取成员 #### getattr(obj, ‘name‘) getattr(obj, ‘func‘) # #### 设置成员 #### setattr(obj, ‘age‘, 18) setattr(obj, ‘show‘, lambda num: num + 1) # #### 删除成员 #### delattr(obj, ‘name‘) delattr(obj, ‘func‘) 反射代码示例
Python标准异常
异常名称 描述 BaseException 所有异常的基类 SystemExit 解释器请求退出 KeyboardInterrupt 用户中断执行(通常是输入^C) Exception 常规错误的基类 StopIteration 迭代器没有更多的值 GeneratorExit 生成器(generator)发生异常来通知退出 StandardError 所有的内建标准异常的基类 ArithmeticError 所有数值计算错误的基类 FloatingPointError 浮点计算错误 OverflowError 数值运算超出最大限制 ZeroDivisionError 除(或取模)零 (所有数据类型) AssertionError 断言语句失败 AttributeError 对象没有这个属性 EOFError 没有内建输入,到达EOF 标记 EnvironmentError 操作系统错误的基类 IOError 输入/输出操作失败 OSError 操作系统错误 WindowsError 系统调用失败 ImportError 导入模块/对象失败 LookupError 无效数据查询的基类 IndexError 序列中没有此索引(index) KeyError 映射中没有这个键 MemoryError 内存溢出错误(对于Python 解释器不是致命的) NameError 未声明/初始化对象 (没有属性) UnboundLocalError 访问未初始化的本地变量 ReferenceError 弱引用(Weak reference)试图访问已经垃圾回收了的对象 RuntimeError 一般的运行时错误 NotImplementedError 尚未实现的方法 SyntaxError Python 语法错误 IndentationError 缩进错误 TabError Tab 和空格混用 SystemError 一般的解释器系统错误 TypeError 对类型无效的操作 ValueError 传入无效的参数 UnicodeError Unicode 相关的错误 UnicodeDecodeError Unicode 解码时的错误 UnicodeEncodeError Unicode 编码时错误 UnicodeTranslateError Unicode 转换时错误 Warning 警告的基类 DeprecationWarning 关于被弃用的特征的警告 FutureWarning 关于构造将来语义会有改变的警告 OverflowWarning 旧的关于自动提升为长整型(long)的警告 PendingDeprecationWarning 关于特性将会被废弃的警告 RuntimeWarning 可疑的运行时行为(runtime behavior)的警告 SyntaxWarning 可疑的语法的警告 UserWarning 用户代码生成的警告
捕捉异常可以使用try/except语句。
try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。
如果你不想在异常发生时结束你的程序,只需在try里捕获它。
语法:
以下为简单的try....except...else的语法:
try: <语句> #运行别的代码 except <名字>: <语句> #如果在try部份引发了‘name‘异常 except <名字>,<数据>: <语句> #如果引发了‘name‘异常,获得附加的数据 else: <语句> #如果没有异常发生
try的工作原理是,当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到这里,try子句先执行,接下来会发生什么依赖于执行时是否出现异常。
下面是简单的例子,它打开一个文件,在该文件中的内容写入内容,且并未发生异常:
#!/usr/bin/python # -*- coding: UTF-8 -*- try: fh = open("testfile", "w") fh.write("这是一个测试文件,用于测试异常!!") except IOError: print "Error: 没有找到文件或读取文件失败" else: print "内容写入文件成功" fh.close()
以上程序输出结果:
$ python test.py 内容写入文件成功 $ cat testfile # 查看写入的内容 这是一个测试文件,用于测试异常!!
下面是简单的例子,它打开一个文件,在该文件中的内容写入内容,但文件没有写入权限,发生了异常:
#!/usr/bin/python # -*- coding: UTF-8 -*- try: fh = open("testfile", "w") fh.write("这是一个测试文件,用于测试异常!!") except IOError: print "Error: 没有找到文件或读取文件失败" else: print "内容写入文件成功" fh.close()
在执行代码前为了测试方便,我们可以先去掉 testfile 文件的写权限,命令如下:
chmod -w testfile
再执行以上代码:
$ python test.py Error: 没有找到文件或读取文件失败
你可以不带任何异常类型使用except,如下实例:
try: 正常的操作 ...................... except: 发生异常,执行这块代码 ...................... else: 如果没有异常执行这块代码
以上方式try-except语句捕获所有发生的异常。但这不是一个很好的方式,我们不能通过该程序识别出具体的异常信息。因为它捕获所有的异常。
你也可以使用相同的except语句来处理多个异常信息,如下所示:
try: 正常的操作 ...................... except(Exception1[, Exception2[,...ExceptionN]]]): 发生以上多个异常中的一个,执行这块代码 ...................... else: 如果没有异常执行这块代码
try-finally 语句无论是否发生异常都将执行最后的代码。
try: <语句> finally: <语句> #退出try时总会执行 raise
#!/usr/bin/python # -*- coding: UTF-8 -*- try: fh = open("testfile", "w") fh.write("这是一个测试文件,用于测试异常!!") finally: print "Error: 没有找到文件或读取文件失败"
如果打开的文件没有可写权限,输出如下所示:
$ python test.py Error: 没有找到文件或读取文件失败
同样的例子也可以写成如下方式:
#!/usr/bin/python # -*- coding: UTF-8 -*- try: fh = open("testfile", "w") try: fh.write("这是一个测试文件,用于测试异常!!") finally: print "关闭文件" fh.close() except IOError: print "Error: 没有找到文件或读取文件失败"
当在try块中抛出一个异常,立即执行finally块代码。
finally块中的所有语句执行后,异常被再次触发,并执行except块代码。
参数的内容不同于异常
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
Python 中,我们用 socket()函数来创建套接字,语法格式如下:
socket.socket([family[, type[, proto]]])
SOCK_STREAM
或SOCK_DGRAM
一个简单的server/client程序
server端
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = (‘127.0.0.1‘,9999) sk = socket.socket() sk.bind(ip_port) sk.listen(5) while True: print ‘server waiting...‘ conn,addr = sk.accept() client_data = conn.recv(1024) print client_data conn.sendall(‘不要回答,不要回答,不要回答‘) conn.close()
client端
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = (‘127.0.0.1‘,9999) sk = socket.socket() sk.connect(ip_port) sk.sendall(‘请求占领地球‘) server_reply = sk.recv(1024) print server_reply sk.close()
进击的Python【第七章】:Python的高级应用(四)面向对象编程进阶
标签:
原文地址:http://www.cnblogs.com/yunweiqiang/p/5854992.html