您的位置:首页 > 编程语言 > Python开发

Python教程8-10

2016-04-14 13:46 507 查看

8.面向对象高级编程

8.1.__slots__

class可以在运行过程中,动态的添加属性和方法
s.name = 'Michael' # 动态给实例绑定一个属性
def set_age(self, age): pass #添加的方法
s.set_age = MethodType(set_age, s, Student) # 给 s 实例绑定一个方法
Student.set_score = MethodType(set_score, None, Student)
给所有实例都绑定方法,
__slots__ = ('name', 'age')
限制该class能添加的属性,不能限制类变量的增加
student.myscore = 12

8.2.@property

封装get,set属性,private的值通过 property自动设置 get,set属性
@property #get方法
def score(self):
return self._score
@score.setter #set方法
def score(self, value):
self._score = value
>>> s = Student()
>>> s.score = 60 # OK,实际转化为s.set_score(60)
>>> s.score # OK,实际转化为s.get_score()
--60

8.3.多重继承

class Dog(Mammal, Runnable):一个子类就可以同时获得多个父类的所有功能。
Mixin: Mixin的目的就是给一个类增加多个功能,类似"接口"
class Dog(Mammal, RunnableMixin, CarnivorousMixin):

8.4.定制类

__str__:
>>> print Student('Michael')
<__main__.Student object at 0x109afb190>
def __str__(self):
return 'Student object (name: %s)' % self.name
>>> print Student('Michael')
--Student object (name: Michael)
变量调用的是 __repr__().所以:
__repr__ = __str__
__iter__:
该方法返回一个迭代对象,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。
class Student(object):
def __init__(self): #初始化
self.x=1
def __iter__(self): ###
return self
def next(self): #调用的 next()方法
self.x+=1
if self.x>20: #判断循环次数
raise StopIteration()
return "name",self.x
for x in Student(): #调用,输出
print x
('name', 2)
('name', 3)
('name', 4)...
__getitem__:
像list那样按照下标取出元素
class Fib(object):
def __getitem__(self, n):
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
>>> f = Fib()
>>> f[0]
1
>>> f[1]
1
>>> f[2]
2
>>> f[3]
3
切片
判断传入的是否是切片对象
if isinstance(n, int):
...
if isinstance(n, slice):
start = n.start
stop = n.stop
L=[]
..
for x in range(stop):
...
return L
>>> f = Fib()
>>> f[0:5]
[1, 1, 2, 3, 5]
__setitem__()方法,把对象视作list或dict来对集合赋值。
__delitem__()方法,用于删除某个元素
__getattr__:
调用类的不存在的方法和属性时,
def __getattr__(self, attr): #attr,不存在的属性
if attr=='score':
return 99
__call__:
直接对实例进行调用。
class Student(object):
def __init__(self, name):
self.name = name
def __call__(self):
print('My name is %s.' % self.name)
>>> s = Student('Michael')
>>> s()
My name is Michael.
Callable:判断一个对象是否是“可调用”对象。
callable(Student())

8.5.使用元类

type():
type()函数可以查看一个类型或变量的类型
print(type(Hello))
可以创建出新的类型
def fn(self,name='World'):
print "Hello",name
Hello=type('Hello',(object,),dict(hello=fn))
h=Hello()
h.hello()
3个参数
class的名称;
继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。

9.错误、调试和测试

9.1.错误处理

try...except...finally...
常见的错误类型和继承关系
raise :抛出错误

9.2.调试

assert: 断言
assert n != 0, 'n is zero!' #表达式n!=0应该是True
如果断言失败,assert语句本身就会抛出AssertionError:
AssertionError: n is zero!
启动Python解释器时可以用-O参数来关闭assert:
python -O err.py
logging:
eg:
import logging
#输出 INFO以上级别的信息
logging.basicConfig(level=logging.INFO) #1
s = '0'
n = int(s)
logging.info('n = %d' % n)
print 10 / n
写入文件,在上例的 #1
1)
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)s %(levelname)s %(message)s', #文件格式
filename='myapp.log', #文件名称
filemode='a') #写入模式
--2016-03-04 19:44:18,075 root INFO n = 0
2)
import logging
# 创建一个logger
logger = logging.getLogger('mylogger')
logger.setLevel(logging.DEBUG)
# 创建一个handler,用于写入日志文件
fh = logging.FileHandler('test.log')
fh.setLevel(logging.DEBUG)
# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# 定义handler的输出格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# 给logger添加handler
logger.addHandler(fh)
logger.addHandler(ch)
s = '0'
n = int(s)
# 记录一条日志
logger.info('n = %d' % n)
print 10 / n
--2016-03-04 19:44:18,075 root INFO n = 0
pdb
命令行启动:python -m pdb err.
py让程序以单步方式运行
l #查看代码
n #单步执行代码
p 变量名 #查看变量
q #结束调试
pdb.set_trace()
import pdb
在可能出错的地方放一个pdb.set_trace(),就可以设置一个断点
程序会自动在pdb.set_trace()暂停并进入pdb调试环境,可以用命令p查看变量
用命令c继续运行:

9.3.单元测试

import unittest
# 包含要测试的文件与class名
from mydict import Dict
#从unittest.TestCase继承。
class TestDict(unittest.TestCase):
#test开头的方法不被认为是测试方法
def test_init(self):
# 断言函数返回的结果与1相等
self.assertEquals(abs(-1), 1)
#抛出指定类型的Error
with self.assertRaises(KeyError):
value = d['empty']
运行单元测试:
# 1)最后加入
if __name__ == '__main__':
unittest.main()
# 2)命令行通过参数-m unittest直接运行单元测试:
python -m unittest mydict_test
#这样可以一次批量运行很多单元测试,并且,有很多工具可以自动来运行这些单元测试。
setUp与tearDown
setUp() #在测试方法前运行
tearDown() #在测试方法后运行
class TestDict(unittest.TestCase):
def setUp(self):
print 'setUp...'
def tearDown(self):
print 'tearDown...'

9.4.文档测试

自动执行写在注释中的代码
def abs(n):
'''
Function to get absolute value of number.
Example:
>>> abs(1)
1
>>> abs(-1)
1
>>> abs(0)
0
'''
return n if n >= 0 else (-n)
if __name__=='__main__':
import doctest
doctest.testmod()
当模块正常导入时,doctest不会被执行。
只有在命令行运行时,才执行doctest。

10.IO编程

10.1.文件读写

with open('/path/to/file', 'r') as f:
print f.read()
二进制文件
读取二进制文件,比如图片、视频,用'rb'模式
字符编码
读取非ASCII编码的文本文件,就必须以二进制模式打开,在解码
Python还提供了一个codecs模块帮我们在读文件时自动转换编码,直接读出unicode:
import codecs
with codecs.open('/Users/michael/gbk.txt', 'r', 'gbk') as f:
f.read() # u'\u6d4b\u8bd5'

10.2.操作文件和目录

import os
os.path.abspath('.') #查看当前目录的绝对路径:
os.path.join('/Users/michael', 'testdir') #连接路径
os.mkdir('/Users/michael/testdir') #创建一个目录:
os.rmdir('/Users/michael/testdir') # 删掉一个目录:
os.path.split('/Users/michael/testdir/file.txt') #分割目录与文件
('/Users/michael/testdir', 'file.txt')
os.path.splitext('/path/to/file.txt') #分割文件与扩展名
os.rename('test.txt', 'test.py') # 对文件重命名:
os.remove('test.py') # 删掉文件:
shutil 是 os模块的补充

10.3.序列化

pickle
把变量从内存中变成可存储或传输的过程称之为序列化
cPickle和pickle #实现序列化
pickle.dumps(d) #把任意对象序列化成一个str
pickle.dump(d, f) #直接把对象序列化后写入f文件
pickle.loads(str) #反序列化出对象
pickle.load(f) #从一个文件直接反序列化出对象
JSON
import json
json.dumps(d) #返回一个str
json.dump(d,f)方法可以直接把JSON写入一个文件
json.loads(str) #反序列化出对象,默认都是unicode
json.load(f) #从一个文件直接反序列化出对象
JSON进阶
#把任意class的实例变为dict:
json.dumps(s, default=lambda obj: obj.__dict__)
#反序列化为一个Student对象实例
def dict2student(d):
return Student(d['name'], d['age'], d['score'])
json.loads(json_str, object_hook=dict2student)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: