美文网首页Python语言_七月在线
(2018-03-24) 0006.Python基础入门班_第6

(2018-03-24) 0006.Python基础入门班_第6

作者: lyh165 | 来源:发表于2018-03-24 22:43 被阅读9次

    上一篇文章:(2018-03-23)0005.Python基础入门班_第5课、文件访问与函数式编程入门

    关于本人

    个人信息:微博
    写作区:个人博客简书开源中国豆瓣、掘金、CSDN
    代码管理区:码云GitHubGitBookPython_NoteBook(这个仅仅限于自己的本地搭建)
    我的网络制作书籍:Python3Book(基于廖雪峰的Python教程编写成书)
    july_Oneline(基于七月在线培训机构的教程编写成书)LineCode刷题总结__GitBookEditor网络书籍


    推荐网站


    推荐软件


    推荐书籍


    第6课 面向对象基础


    一、slots
    slots作用

    自身理解

    英文意思:插槽;老虎机(slot的复数)
    

    代码展示

    # 一、__slots__
    print('一、__slots__')
    import traceback #处理异常的时候打印信息
    from types import MethodType # 怎么动态添加一个方法
    
    class MyClass(object):
         #__slots__是限制添加哪些变量,#对于子类 不起继承作用
    
         #__系统都叫模数变量,系统内用来实现某些特定功能的
        __slots__ = ['name','set_name']
    
    
        pass
    def set_name(self,name):
        self.name = name
    cls = MyClass()
    cls.name = 'L'
    cls.set_name = MethodType(set_name,cls)
    cls.set_name('HH')
    print(cls.name)
    
    # 捕获异常
    # try:
    #   cls.age = 30 # AttributeError: 'MyClass' object has no attribute 'age'
    
    # except AttributeError: # 属性错误
    #       traceback.print_exc()
    
    class ExtMyClass(MyClass):
            pass
    ext_cls = ExtMyClass()
    ext_cls.age = 30
    print(ext_cls.age)
    
    #1.2 @property属性
    
    import traceback
    
    class Student:
        @property 
        def score(self):
            return self._score
    
        @score.setter
        def score(self,value):
            if not isinstance(value,int):
                raise ValueError('not int')
            elif (value < 0) or (value > 100):
                raise ValueError('not between 0 ~ 100')
            self._score = value
        @property 
        def double_score(self):
            return self._score * 2
    
    
    s = Student()
    s.score = 75
    print(s.score)
    try: 
        s.score = 'abc'
    except ValueError: # 这里是捕获 raise ValueError的错误
        traceback.print_exc()
    # except Exception: # 这里是捕获异常所有的错误
    
    try:
        s.score = 101
    except:
        traceback.print_exc()
    
    print(s.double_score)
    try:
        s.double_score = 150
    except AttributeError: # 这里是因为知道捕获什么类型的error,如果不知道就捕获所有的错误Exception
        traceback.print_exc() # AttributeError: can't set attribute 说明只读不能写的
    
    
    #1.3 @property实现
    '''
    课后百度 什么事描述其 以及 详细的应用
    实现了 __set__/__get__/__del__方法的类 为描述器
    '''
    print('1.3 @property实现')
    class MyProperty:
        def __init__(self,fget = None,fset = None,fdel = None):
            print('__init__',fget)  # <function Student.score at 0x01282420>
    
            self.fget = fget
            self.fset = fset
            self.fdel = fdel
    
        def __get__(self,isinstance,cls):
            if self.fget:
                print('__get__')
                return self.fget(isinstance)
    
        def __set__(self,isinstance,value):
            if self.fset:
                print('__set__')
                return self.fset(isinstance,value)
    
        def __del__(self,isinstance):
            if self.fdel:
                return self.fdel(isinstance)
        '''
        def getter(self,fn):
            self.fget = fn
        '''
        def setter(self,fn):
            print('setter',fn)
            self.fset = fn
        '''
        def deler(self,fn):
            self.fdel = fn
        '''
    
    class Student:
        @MyProperty
        def score(self):
            print(self._score)
            return self._score
        @score.setter
        def set_score(self,value):
            print(value)
            self._score = value
    
    
    s = Student()
    s.score = 95
    print(s.score)
    print('!end!\n')
    

    控制台打印

    一、__slots__
    HH
    30
    75
    Traceback (most recent call last):
      File "C:\Users\Hasee\Desktop\Python_七月在线\01-Python课程___Python基础入门班\Code\第6课 高级面向对象\高级面向对象.py", line 82, in <module>
        s.score = 'abc'
      File "C:\Users\Hasee\Desktop\Python_七月在线\01-Python课程___Python基础入门班\Code\第6课 高级面向对象\高级面向对象.py", line 69, in score
        raise ValueError('not int')
    ValueError: not int
    Traceback (most recent call last):
      File "C:\Users\Hasee\Desktop\Python_七月在线\01-Python课程___Python基础入门班\Code\第6课 高级面向对象\高级面向对象.py", line 88, in <module>
        s.score = 101
      File "C:\Users\Hasee\Desktop\Python_七月在线\01-Python课程___Python基础入门班\Code\第6课 高级面向对象\高级面向对象.py", line 71, in score
        raise ValueError('not between 0 ~ 100')
    ValueError: not between 0 ~ 100
    150
    Traceback (most recent call last):
      File "C:\Users\Hasee\Desktop\Python_七月在线\01-Python课程___Python基础入门班\Code\第6课 高级面向对象\高级面向对象.py", line 94, in <module>
        s.double_score = 150
    1.3 @property实现
    AttributeError: can't set attribute
    __init__ <function Student.score at 0x01414C48>
    setter <function Student.set_score at 0x01414C90>
    __set__
    95
    __get__
    95
    95
    !end!
    

    二、类的特殊方法 和 类的定制
    代码展示

    #二、类的特殊方法 和 类的定制
    '''
    字符串
    '''
    print('#二、类的特殊方法 和 类的定制')
    class MyClass:
        def __init__(self,name):
            self.name = name
        def __str__(self):
            print('print will call __str__ first.')
            return ' Hello ' + self.name + '!'
    print(__name__)
    print(MyClass('Tom'))
    
    
    
    # 作业
    '''
    实现一个类,支持以下方式输出小于1000的所有素数
    自己去查资料,通过实现 __getitem__ 支持切片操作
    '''
    class Fib100:
        def  __init__(self):
            self._1, self._2 = 0,1
    
        def __iter__(self):
            return self
    
        def __next__(self):
            self._1,self._2 = self._2,self._1 + self._2
            if self._1 > 100:
                raise StopIteration()
            return self._1
    for i in Fib100():
        print(i)
    
    
    # 
    class Fib2:
        # getitem 是修改类的行为
        def __getitem__(self,n):
            # print(type(n))
            a,b = 1,1
            for i in range(n):
                a,b = b,a+b
            return a
    
    f  = Fib2()
    print(f[1])
    print(f[5])
    print(f[10])
    # print(f[1:2:3])
    
    class MyClass:
    
        def __call__(self):
            print('you can call cls() directly.!')
    cls = MyClass()
    cls()
    # callable 是不是可以调用的
    print(callable(cls))
    print(callable(max)) # 函数 是可以调用的
    print(callable([1,2,3]))
    print(callable(None))
    print(callable('str'))
    
    print('!end\n')
    

    控制台打印

    #二、类的特殊方法 和 类的定制
    __main__
    print will call __str__ first.
     Hello Tom!
    1
    1
    2
    3
    5
    8
    13
    21
    34
    55
    89
    1
    8
    89
    you can call cls() directly.!
    True
    True
    False
    False
    False
    !end
    

    三、枚举
    百度维基

    在数学和计算机科学理论中,
    一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。
    这两种类型经常(但不总是)重叠。[1]
      是一个被命名的整型常数的集合,枚举在日常生活中很常见,
    例如表示星期的SUNDAY、MONDAY、TUESDAY、WEDNESDAY、
    THURSDAY、FRIDAY、SATURDAY就是一个枚举。
    

    代码展示

    #三、枚举
    print('三、枚举')
    from enum import Enum
    
    Month = Enum('Month',('Jan','Feb','Mar','Apr'))
    for name,member in Month.__members__.items():
            print(name,'=>',member,',',member.value)
    
    jan = Month.Jan
    print(jan)
    print('!end!\n')
    

    控制台打印

    三、枚举
    Jan => Month.Jan , 1
    Feb => Month.Feb , 2
    Mar => Month.Mar , 3
    Apr => Month.Apr , 4
    Month.Jan
    !end!
    

    四、元类
    百度维基

    代码展示

    #四、元类
    '''
    python是一个动态类型的语言
    '''
    print('四、元类')
    def init(self,name):
        self.name = name
    def say_hello(self):
        print('Hello, %s!'% self.name)
    # 动态生成一个类, 
    #使用type 第一个参数是这个类的名字,第二个参数是继承那个类,第三个参数是这个类有哪些方法
    
    
    # Hello = type('Hello',(object,),dict(__init__=init,hello=say_hello))
    Hello = type('Hello',(object,),{'__init__':init,'hello':say_hello})
    
    '''
    type('Hello',(object),dict(__init__=init,hello=say_hello)) # TypeError: type() argument 2 must be tuple, not type
    
    type('Hello',(object,),dict(__init__=init,hello=say_hello))
    
    object这个是一个基类的列表
    必须要传递一个列表
    等价于
    class Hello:
        def __init__(..)
        def hello(...)
    '''
    h = Hello('l')
    h.hello()
    
    # 元类添加额外的属性和方法
    '''
    元类一定是type继承下来的
    ''' 
    def add(self,value):
        self.append(value)
    
    class ListMetaclass(type):
        def __new__(cls,name,bases,attrs):
            # print(cls)
            # print(name)
            # print(bases)
            print(type(bases)) # 这是一个只读的
            print(type(attrs)) # attrs 其实就是一张哈希表
            # attrs 哈希表 实现一个add 函数
            # attrs['add'] = lambda self,value: self.append(value)
            attrs['add'] = add
            attrs['name'] = 'Li'
            return type.__new__(cls,name,bases,attrs)
    class MyList(list,metaclass = ListMetaclass ): # 额外增加add方法,实际等价于append
        pass
    
    mli = MyList()
    mli.add(1)
    mli.add(2)
    mli.add(3)
    print(mli)
    print(mli.name)
    

    控制台打印

    四、元类
    Hello, l!
    <class 'tuple'>
    <class 'dict'>
    [1, 2, 3]
    Li
    

    五、写一个框架的数据库

    代码展示

    # 五、写一个框架的数据库
    '''
    极大的方便操作数据库
    '''
    # fField 列 有两个类型 一个是名字、一个是数据类型
    print('五、写一个框架的数据库')
    class Field:
        def __init__(self,name,col_type):
            self.name = name
            self.col_type = col_type
    
    class IntegerField(Field):
        def __init__(self,name):
            super(IntegerField,self).__init__(name,'integer')
    class StringField(Field):
        def __init__(self,name):
            super(StringField,self).__init__(name,'varchar(1024)') # 调用父类的初始化函数
    
    class ModelMetaclass(type):
        def __new__(cls,name,bases,attrs):
            if name == 'Model':
                return type.__new__(cls,name,bases,attrs)
            print('Model name:%s' %name)
            print('attrs :',attrs)
            mappings = {} # 先定义一个字典
            '''
            key = value
            id = IntegerField('id')
            name = StringField('name')
            '''
            # 判断这些属性 是不是filed属性
            # 数据库的每一列的数据是放在mapping里面的
            # k 是这一列的名字
            # v 是列的名字 和列的类型
            for k,v in attrs.items():
                if isinstance(v,Field):
                    print('Field name :%s'% k)
                    mappings[k] = v # 如果是filed 就加到mappings里面去
            # 为什么要从attrs弹出来
            '''
            因为列的名字 和 列的类型 就是放在attrs里面的
    
            后面的
            u.id = 100 这些当作正常的去访问
            所以attrs不需要 就 把他扔掉
            '''
            for k in mappings.keys():
                attrs.pop(k) # 从attr删除
            attrs['__mappings__'] = mappings
            attrs['__table__'] = name
            # print(attrs['__mappings__'])
            return type.__new__(cls,name,bases,attrs)
    class Model(dict,metaclass = ModelMetaclass):
        def __init__(self,**kvs):
            super(Model,self).__init__(**kvs)
        def __getattr__(self,key):
            try:
                return self[key]
            except KeyError:
                raise AttributeError('Model object has no attribute %s'%key)
    
        def __setattr__(self,key,value):
            print('__setattr__')
            self[key] = value
        def save(self):
            fields = []
            params = []
            args = []
            for k,v in self.__mappings__.items():
                # print('__mappings__ %s' %k)
                fields.append(v.name)
                params.append('?')
                args.append(getattr(self,k,None))
            sql = 'insert into %s(%s) values(%s)' % (self.__table__,','.join(fields),','.join(params))
            print('sql:',sql)
            print('args:',args)
    
    
    class User(Model):
        id = IntegerField('id')
        name = StringField('name')
    
    u = User()
    u.id = 100
    u.name = 'Tom'
    u.save()
    print('!end!\n')
    

    控制台打印

    五、写一个框架的数据库
    Model name:User
    attrs : {'__module__': '__main__', 'id': <__main__.IntegerField object at 0x014265B0>, '__qualname__': 'User', 'name': <__main__.StringField object at 0x014265D0>}
    Field name :id
    Field name :name
    __setattr__
    __setattr__
    sql: insert into User(name,id) values(?,?)
    args: ['Tom', 100]
    !end!
    

    六、单元测试 和 异常处理
    单元测试异常处理

    自身理解

    进行应用的测试
    代码出错,可以使用异常处理语句进行过滤做操作
    
    

    代码展示

    # 六、单元测试 和 异常处理
    '''
    logging使用与配置 自己百度
    '''
    print('六、单元测试 和 异常处理')
    import traceback
    try:
        r = 10 / 1
    except ZeroDivisionError as e:
        print(e) # 打印异常的信息
        r = 1
    else:
        print('没有异常')
    finally:
        # r = 1 # 不管异常 发布发生 都会执行
        print('不管有没有异常都会执行')
    
    print(r)
    
    # 单元测试 (必须引入 unittest 包)
    '''
    用的是反射机制
    查看有哪些类是由当前unit test继承下来的
    然后把继承下来的那些类都执行了一遍
    '''
    import unittest
    
    class MyDict(dict):
        pass
    
    class TestMyDict(unittest.TestCase):
        def setUp(self):
            print('测试前准备')
        def tearDown(self):
            print('测试后清理')
    
        def test_init(self):
            md = MyDict(one = 1, two = 2)
            self.assertEqual(md['one'],1)
            self.assertEqual(md['two'],2)
            # self.assertEqual(md['two'],3)
         
        def test_nothing(self):
            pass
    if __name__ == '__main__':
        unittest.main()
    
    
    '''
    cmd 执行命令
    python test_module.py
    python -m unittest test_module
    python -m unittest test_module.test_class
    python -m unittest test_module.test_class
    python -m unittest test_module.test_class.test_method
    
    '''
    

    控制台打印

    六、单元测试 和 异常处理
    没有异常
    不管有没有异常都会执行
    10.0
    测试前准备
    测试后清理
    .测试前准备
    测试后清理
    .
    ----------------------------------------------------------------------
    Ran 2 tests in 0.001s
    
    OK
    [Finished in 0.3s]
    

    代码:l6me

    明天将会更新→0007.Python基础入门班_第7课、并发编程以及系统常用模块

    代码都是上传百度云

    相关文章

      网友评论

        本文标题:(2018-03-24) 0006.Python基础入门班_第6

        本文链接:https://www.haomeiwen.com/subject/cauqcftx.html