このブログは廖雪峰python教程の練習問題を記録している(六)
22574 ワード
列挙クラスの使用
2つのコードを貼りましょう.
2つ目の例では、Enumを継承するクラスを定義できます.
最後に、「Studioのgenderプロパティを列挙タイプに変更すると、文字列の使用を避けることができます.」という宿題を書きます.
メタクラスの使用
まずhelloを書きます.pyファイル(モジュール)は、次のように書かれています.
次に、右側のコンソールに次のように入力します.
では、type()関数を使用してクラスを動的に作成するにはどうすればいいのでしょうか.type()関数は、class Hello(object)を使用することなく、type()関数を使用してHelloクラスを作成することができます.コードは次のとおりです.
エラー、デバッグ、テスト
エラー処理
身につける必要があるExcept...の使い方:
実際には、ValueError、ZeroDivisionErrorなど、さまざまなタイプのエラーをキャプチャするために複数のexceptを返すこともできます.
関数間呼び出しに遭遇した場合は適切な関数でエラーをキャプチャするだけでよい
複数の関数に呼び出し関係がある場合、ある関数がエラーになる可能性があります.上位で呼び出す関数を一つ一つキャプチャする必要はありません.適切な階層でエラーをキャプチャするだけでいいです.
エラーキャプチャを行わないと、メイン関数でエラーが実行されると、次のように実行されません.
再main()関数の最初のprint文がvalueの値を印刷するとエラーが発生することを知っています.value自体に問題があるint(‘0’)が0 func 1に戻って10/int(‘0’)を計算するとエラーが発生し、func 2がエラーになります.main()が間違っているので、後のprint(‘End’)も実行されません.
エラーメッセージは次のとおりです.
しかし、エラーと同時にエラー情報を投げ出し、プログラムを実行し続けるにはloggingを使用します.
コンソールは次のように動作します.
ここではエラー情報を記録するだけで、以前のようにめちゃくちゃなエラー情報を投げ出すことはなく(プログラムを見るとエラーが発生するようなものは、実は自分で上記の2つの関数を実行してコンソール出力の形式を比較することができます)、プログラムの実行を保証することができるので、try except関数以外の最後のprint文を出力します
最後にもう一つの作業を書きます.「次のコードを実行し、異常情報に基づいて分析し、エラーのソースを特定し、修復します.」
このコードの実行後に表示されるエラーは次のとおりです.
コードは次のように変更されます.
それからsplitを復習します.
寮に帰りました.
2つのコードを貼りましょう.
>>> 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
2つ目の例では、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>
最後に、「Studioの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()関数は、class Hello(object)を使用することなく、type()関数を使用してHelloクラスを作成することができます.コードは次のとおりです.
>>> 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'>
エラー、デバッグ、テスト
エラー処理
身につける必要がある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()
実際には、ValueError、ZeroDivisionErrorなど、さまざまなタイプのエラーをキャプチャするために複数のexceptを返すこともできます.
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 func 1に戻って10/int(‘0’)を計算するとエラーが発生し、func 2がエラーになります.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!!
ここではエラー情報を記録するだけで、以前のようにめちゃくちゃなエラー情報を投げ出すことはなく(プログラムを見るとエラーが発生するようなものは、実は自分で上記の2つの関数を実行してコンソール出力の形式を比較することができます)、プログラムの実行を保証することができるので、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']
>>>
寮に帰りました.