(2018-03-24) 0006.Python基础入门班_第6课、面向对象基础

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

关于本人

个人信息:微博
写作区:个人博客、、开源中国、豆瓣、掘金、CSDN
代码管理区:码云、GitHub、GitBook、Python_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)  # 

        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 
    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 
    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 
    s.double_score = 150
1.3 @property实现
AttributeError: can't set attribute
__init__ 
setter 
__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!


[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课、面向对象基础)