这篇博客记录廖雪峰python教程的习题(六)

使用枚举类

贴两个代码吧:

>>> from enum import Enum
>>> Month1=Enum('Month2',('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'))
>>> Month1.Jan   #首先要注意这里的名字要与刚开始的Month1(就是等号前面的那个)保持一致,虽然我也不知道Enum()括号里面的Month2是干嘛的,,,,
1>
>>> Month2.Feb   #你看,当使用Month2调用时就会出错
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'Month2' is not defined
>>> Month1.Sep  
9>
>>> for name,member in Month1.__members__.items():  #另外还可以使用for in循环进行遍历访问其中的元素
...     print(name,'-->',member,member.value)
...
Jan --> Month2.Jan 1   分别是name(就是Enum括号里面的),member(就是Month1.name返回的值) 以及对应的member.value的值
Feb --> Month2.Feb 2
Mar --> Month2.Mar 3
Apr --> Month2.Apr 4
May --> Month2.May 5
Jun --> Month2.Jun 6
Jul --> Month2.Jul 7
Aug --> Month2.Aug 8
Sep --> Month2.Sep 9
Oct --> Month2.Oct 10
Nov --> Month2.Nov 11
Dec --> Month2.Dec 12

对于第二个例子,我们可以定义一个类,用来继承Enum

>>> from enum import Enum,unique
>>> @unique
... class Weekday(Enum):
...     Sun=0
...     Mon=1
...     Thu=2
...     Wed=3
...     Thr=4
...     Fri=5
...     Sat=6
...
>>> Weekday.Mon
1>
>>> Weekday['Mon']
1>
>>> Weekday(1)
1>

最后写一个作业题:
“把Student的gender属性改造为枚举类型,可以避免使用字符串:”

>>> from enum import Enum,unique
>>> @unique
... class Gender(Enum):
...     male=0
...     female=1
...
>>> class Student(object):
...     def __init__(self,name,gender):
...         self.name=name
...         self.gender=gender
...
>>> xuan=Student('Zhangxuan',Gender.female)
>>> xuan.gender==Gender.female
True
>>>

使用元类

首先写一个hello.py文件(模块)
在里面写:

 class Hello(object):
...     def hello(self,name='Zhangxuan'):
...         print("hello,%s."%name)
...
>>>

然后在右边的控制台输入:

from hello import Hello

h=Hello()   #表明h是类Hello的一个实例

h.hello()    #实例h调用方法(函数)hello() 
hello,Zhangxuan.

type(Hello)
Out[158]: type  #Hello是一个类 它的类型就是

type(h)
Out[159]: hello.Hello

那么如何通过type()函数动态创建类呢,type()函数可以返回一个对象的类型又可以创建出一个新的类型,比如我们可以通过type()函数创建出一个Hello类,而无需通过class Hello(object):….
代码如下:

>>> def fn(self,name='World'):
...     print("Hello,%s."%name)
...
>>> Hello=type('Hello',(object,),dict(hello=fn))
>>> h=Hello()
>>> h.hello()
Hello,World.
>>> type(Hello)
'type'>
>>> type(h)
'__main__.Hello'>
>>>
```要想创建一个class类, type()函数需要传入三个参数:
1.类的名称
2.类所继承的类,注意tuple()中单个元素的写法需要加,
3.class里面的方法,这里我们吧函数fn绑定要方法hello上





这里写代码片
“`

>>> Hello1=type('Hello2',(object,),dict(hello=fn))
>>> h=Hello2()   #所以要注意类是前面被赋值的那个Hello1!!! 而不是后面type()里面的,可是Hello2 我也不知道是干嘛的,,,
Traceback (most recent call last):
  File "", line 1, in <module>
NameError: name 'Hello2' is not defined
>>> h=Hello1()
>>> h.hello()
hello,Zhangxuan.
>>> type(Hello1)
<class 'type'>
>>> type(h)
<class '__main__.Hello2'>

错误,调试和测试

错误处理

需要掌握try..except…的用法:

def func(n):
    try:
        print("Trying....")
        value=10/n
        #print("the value is{}".format(value))
    except ZeroDivisionError as e:
        print("error",e)
    else:
        print("No error!")
        print("the value is{}".format(value))
    finally:
        print("Finally.....")

def main():

    func(10)

main()

其实也可以返回多个except 用来捕捉多种类型的错误:(比如ValueError,ZeroDivisionError等等)

def func(s):
    try:
        print("Trying!")
        value=10/int(s)
        print("the value is {}".format(value))
    except ValueError as e:
        print("error1:",e)
    except ZeroDivisionError as e:
        print("error2:",e)
    finally:
        print("Finally!")

def main():
    #func('xixi')  #会抛出第一种错误
    func('0') #会抛出第二种错误

main()

如果遇到函数之间调用的只需要在恰当的函数里捕捉错误就可以了

def func1(s):
        value=10/int(s)
        return value

def func2(s):  #func2 调用func1
    return func1(s)*2

def main():   #main 函数调用func2
    s='xixi'
    #s='0'
    try:
        print("Trying!")
        value=func2(s)+100
        print("the value is {}".format(value))
    except ValueError as e:
        print("Error1:",e)
    except ZeroDivisionError as e:
        print("Error2:",e)
    else:
        print("There is no error!")
    finally:
        print("Finally!")

    print('End!')

main()

当多个函数有调用关系时某一个函数可能出错,不需要在上级调用它的函数都一一捕捉,只需要在合适的层次捕捉错误就可以了

当我们不进行错误捕捉时,一旦在主函数中运行出错就不会再继续往下运行了,就像这样:

def func(s):
    value=10/int(s)
    return value

def func2(s):
    return func(s)*2

def main():
    s='0'
    value=func2(s)
    print("the value is {}".format(value))
    print('End')  #在控制台就没有输出,,,

main()

我们知道再main()函数的第一个print 语句打印value的值时就会运行出错,因为value本身有问题int(‘0’)返回一个0 func1里面计算10/int(‘0’)会出错,继而func2会出错,main()错
所以后面的print(‘End’)也不会被继续执行

报错信息如下:


  File "E:/pyhtonworkspace/py3-pratice/bymyself_practice/python_Liaoxuefeng/20180211/hello.py", line 116, in 
    main()

  File "E:/pyhtonworkspace/py3-pratice/bymyself_practice/python_Liaoxuefeng/20180211/hello.py", line 112, in main
    value=func2(s)

  File "E:/pyhtonworkspace/py3-pratice/bymyself_practice/python_Liaoxuefeng/20180211/hello.py", line 108, in func2
    return func(s)*2

  File "E:/pyhtonworkspace/py3-pratice/bymyself_practice/python_Liaoxuefeng/20180211/hello.py", line 104, in func
    value=10/int(s)

ZeroDivisionError: division by zero

但是如果我们想让出错的同时抛出错误信息,同时程序可以继续运行,我们可以使用logging


import logging

def func(s):
    value=10/int(s)
    return value

def main():
    try:
        value=func('0')
        print("the value is {}".format(value)) #这句可不会执行,因为本来try except 就是一旦try部分出现错 就不再继续执行 直接跳到except部分执行
    except ZeroDivisionError as e:
        logging.exception(e)

    print('End!!看看我能不能输出')  #当使用logging时 抛出错误时仍然会继续执行剩下的语句,保证程序继续执行

main(

控制台运行如下:

ERROR:root:division by zero
Traceback (most recent call last):
  File "E:/pyhtonworkspace/py3-pratice/bymyself_practice/python_Liaoxuefeng/20180211/hello.py", line 128, in main
    value=func('0')
  File "E:/pyhtonworkspace/py3-pratice/bymyself_practice/python_Liaoxuefeng/20180211/hello.py", line 123, in func
    value=10/int(s)
ZeroDivisionError: division by zero
End!!看看我能不能输出

可以看到这里只是把错误信息记录下来,并没有像之前那样抛出一些乱七八糟的错误信息(一看程序就出错的那种,其实自己可以运行上面两种函数对比一下控制台输出的形式),而且可以保证程序继续执行,所以会输出try except函数外的最后一条print语句

最后再写一个作业:
“运行下面的代码,根据异常信息进行分析,定位出错误源头,并修复:”

#这个程序是有错误的现在要根据这段错误代码抛出的异常信息,定位错误,并修改

from functools import reduce

def str2num(s):
    return int(s)

def calc(exp):
    ss = exp.split('+')
    ns = map(str2num, ss)
    return reduce(lambda acc, x: acc + x, ns)

def main():
    r = calc('100 + 200 + 345')
    print('100 + 200 + 345 =', r)
    r = calc('99 + 88 + 7.6')
    print('99 + 88 + 7.6 =', r)

main()

这段代码运行之后显示的错误如下:

  File "E:/pyhtonworkspace/py3-pratice/bymyself_practice/python_Liaoxuefeng/20180211/hello.py", line 157, in 
    main()

  File "E:/pyhtonworkspace/py3-pratice/bymyself_practice/python_Liaoxuefeng/20180211/hello.py", line 154, in main
    r = calc('99 + 88 + 7.6')

  File "E:/pyhtonworkspace/py3-pratice/bymyself_practice/python_Liaoxuefeng/20180211/hello.py", line 149, in calc
    return reduce(lambda acc, x: acc + x, ns)

  File "E:/pyhtonworkspace/py3-pratice/bymyself_practice/python_Liaoxuefeng/20180211/hello.py", line 144, in str2num
    return int(s)

ValueError: invalid literal for int() with base 10: ' 7.6'

代码修改如下:



from functools import reduce

def str2num(s):
    #return int(s)   #这是原来的语句
    try:
        number=int(s)

    except:   #注意这个地方的写法 是在except里面再写一个try except 而不是并且的写except!!有点类似于if else 里面的嵌套if else
        try:
            number=float(s)
        except:
            print("what you input is not a number!!!")

    finally:

        return number



def calc(exp):
    ss = exp.split('+')  #这里是把calc()里面的字符串以+号分割 剩下的都是单个的字符 '100' ,'200' split之后返回的时list
    ns = map(str2num, ss)#这里借助map函数把上面自己定义的str2num函数(也就是把字符转换成整数的函数)依次作用于ss这个由字符串组成的列表!
    return reduce(lambda acc, x: acc + x, ns)  #再使用reduce函数把两个数相加的函数依次作用于一个map返回的可迭代对象(里面全是数字类型的)

def main():
    r = calc('100 + 200 + 345')
    print('100 + 200 + 345 =', r)
    r = calc('99 + 88 + 7.6')
    print('99 + 88 + 7.6 =', r)

main()   

然后再复习一下 split:

>>>
>>> s='100+200+300'
>>> L=s.split('+')   #split之后返回的是一个列表
>>> L
['100', '200', '300']
>>>

回宿舍了

你可能感兴趣的:(python,python_practice)