Python教程8-10

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)


转载于:https://my.oschina.net/sii/blog/659253

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值