What you see here is an instance of a problem that's commonly known as a time bomb.
A time bomb is infection in the code that's just waiting to explode into your face as a failure.
Here's something that's definitely wrong and it's in there and it's sleeping.
It can be there for million of cycles.
Only when it's being accessed or processed that's when the time bomb explodes
and this is hard to debug because you have to figure out
where the time bomb originally was planted and set -- that's where assertions save the day.
An assertion prohibits time bomb by checking whether the data is sane
at the very moment it is being stored.
When we are creating a timedobject, we could for instance use assertions
to make sure that the arguments actually are all within specified ranges.
For instance, we could say the hour must be between 0 and 23.
At the same time, we give a hint to the user that time uses 24-hour format.
We also want to make sure that the minutes and the seconds are within the proper ranges
between 0 and 59, respectively.
This special syntax you see over here is a speciality of Python
which allows to coerce multiple comparisons into one.
Actually now that I think of it, 59 is not correct here.
There's years in which there's leap seconds and if there's a leap second,
then there can actually be 61 seconds in a minute.
So, in order to be perfectly correct, this needs to be 60 up here.
This is still a very simplistic time class, it just assumes, say local time for instance.
We don't care about time zones or calendars or daylight saving times or anything at this point.
The real time class is way more complicated than this one.
Now, let's see whether these assertions help us in avoiding time bombs.
We still have the string passed in here.
Let's see whether our assertion catches this. Again, press and run.
And see, as we put in 2 minutes after midnight as a string, the assertion fails
because the string is not between the values of 0 and 23.
What happens if it pass negative values in here say hours is valid, minutes is negative,
seconds is valid, press on run, and again we get a failing assertion--
now, we get the failing assertion that the minutes is not within the right range,
which is exactly what we wanted to catch.
With these assertions up here, any attempt to set any time object
to an illegal state will immediately be detected.
Quello che vedi qui e' un esempio di un problema comunemente noto come "bomba a orologeria".
Una bomba a orologeria e' un'infezione del codice che sta solo aspettando di esploderti in faccia.
C'e' qualcosa di tremendamente sbagliato ed e' li' e sta dormendo.
Puo' rimanere li' per milioni di cicli.
Solo quando ci si accede o la si elabora succede che la bomba a orologeria esplode
ed e' difficile da debuggare perche' devi capire
dove la bomba e' stata inizialmente collocata e accesa -- ecco quando diventano indispensabili le asserzioni.
Un asserzione inibisce le bombe a orologeria, verificando che i dati abbiano senso
nel momento stesso in cui vengono immagazzinati.
Quando creiamo un oggetto Time, potremmo per esempio usare le asserzioni
per assicurarci che gli argomenti siano effettivamente tutti entro gli intervalli indicati.
Per esempio, potremmo dire che le ore devono stare tra 0 e 23.
Allo stesso tempo informeremo l'utente che l'ora e' nel formato a 24 ore.
Vogliamo anche essere sicuri che i minuti e i secondi stiano nei giusti intervalli,
rispettivamente tra 0 e 59.
Questa particolare sintassi che vedi qui e' una specialita' di Python
che permette di raggruppare confronti multipli in uno solo.
Pero' ora che ci penso, il 59 qui non e' giusto:
ci sono anni in cui c'e' il "secondo intercalare" e se c'e' il secondo intercalare
ci potrebbero essere 61 secondi in un minuto.
Quindi per essere perfettamente esatto, bisogna che ci sia 60 qui.
Questa rimane una classe orario semplice, tiene conto soltanto dell'ora locale, per fare un esempio.
A noi non interessano le timezone o i calendari o le ore legali o niente altro a questo punto.
Un classe orario realistica e' molto piu' complicata di questa qui.
Adesso vediamo se queste asserzioni ci aiutano ad evitare le bombe a orologeria.
Abbiamo ancora la stringa passata qui:
vediamo se la nostra asserzione la cattura. Premiamo di nuovo Run...
...e vediamo che dopo aver messo 2 minuti dopo la mezzanotte nella stringa, l'asserzione si blocca
perche' la stringa non e' tra i valori 0 e 23.
Che succede se passiamo dei valori negativi qui, diciamo, l'ora giusta, i minuti in negativo,
i secondi giusti...premiamo Run e di nuovo abbiamo un asserzione che si blocca.
Ora abbiamo un asserzione in cui i minuti non sono nel giusto intervallo,
il che e' esattamente cio' che volevamo catturare.
Con queste asserzioni quassu', ogni tentativo di portare l'oggetto Time
ad uno stato illegittimo verra' immediatamente rilevato.
これは不合格の例です 一般的に時限爆弾として知られています
時限爆弾はコードの感染です 不具合として爆発するのを待っています
ここに明らかにおかしい箇所があります 今は眠っています
無数のサイクルのためにそこにいます
アクセスまたは処理された時だけ時限爆弾が爆発します
これはデバッグするのが難しいです なぜなら時限爆弾が
仕掛けられた元を見つけ出さなければいけないからです ここでアサーションが役立ちます
アサーションはデータが記憶されたら 瞬時にそれが健全かをチェックし
時限爆弾を防いでいます
Timeオブジェクト作成の際にアサーションを使用し
すべての引数が指定した長さになっているか 確認することもできます
たとえばhoursは0から23の間にあることを指定します
同時にTimeは24時間フォーマットを 使用していることをユーザに暗示します
またminutesとsecondsがそれぞれ 0から59の範囲にあることを
確認します
ここに確認できる特別な構文は
多重比較を強制するPython特有のものです
今思うとここの59は正しくありません
うるう秒がある年があります 該当する年では
1分を61秒にするとよいでしょう
完璧に正確にするため ここまで60であるべきです
これはとても単純なTimeクラスです たとえば現地時間に指定することも想定しています
タイムゾーンやカレンダーやサマータイムなどは ここでは考慮していません
本当のTimeクラスはこれよりもずっと複雑です
ではアサーションが時限爆弾を防いでくれたか 確認してみましょう
ここにまだ文字列が指定されています
アサーションがこれを検出するかどうか 再度確認しましょう
見て下さい 文字列として "Two minutes after midnight"を置くと失敗します
これは文字列が0と23の値にないからです
負の値をここに指定すると hoursは有効 minutesはネガティブ
secondsは有効です 実行するとまたアサーションが失敗します
minutesの長さが正しくなかったので アサーションが失敗したのです
これがまさに検出してほしいことでした
違反している状態に Timeオブジェクトを設定しようとすると
これらのアサーションがすぐにそれを検出します
你看到的这个问题，就是众所周知的时间炸弹。
时间炸弹就是代码版的《潜伏》，随时想要炸你个满脸花。
在代码中存在着传说中的错误，只是它一般陷于沉睡。
可能之前的几百万次循环运行都没打扰到它。
只是一旦它苏醒后，时间炸弹一爆炸了，
就很难调试出来，因为你必须得找出
这个时间炸弹最初的藏身之处--这正是断言大展神威之时，它可以节约你的宝贵光阴。
因为断言能阻止时间炸弹，它可以检查数据是否合理有效，
主要是在要被存储起来的时候，需要检查。
当我们new一个时间对象时，就可以用断言
来确保参数都处于有效的范围。
比如，小时一定是在0-23之间，48小时的去死！
同时，还给用户一个提醒，提醒他们现在用的是24小时制。
还要确保秒和分钟都在正确的范围内，
也就是0到59啦！
这个特殊的句法是Python的一大亮点，
它允许将多个比较强制合成一个。
现在我认为，59也不正确了。
有些年份里会有几秒被跳过（没听说过），如果某一秒跳过了，
那一分钟就等于有61秒了。
所以，为了彻底地正确，这里的上限应该改成60……
这仍是个非常简单的时间类，它只假设用到本地时间。
此时，我们不关心时区、日历或白天黑夜还是别的什么。
实际的时间类比这复杂得多。呃，扯远了，这些人经常扯远，
废话少说，来看看这些断言是否能帮助我们避免时间炸弹。
这里还是传递了一个字符串。
看看断言是否能捉住它。来，点一下，运行！
看！我们输入的是"Two minutes after midnight"字符串，断言失败鸟，
因为它不在0-23的范围之内。
如果把负值传递过去会如何呢？比如小时数有效，分钟为负数，
秒也有效，点运行，嗯，还是引发了失败。
我们看到是这个断言错误，即分钟不在正确的范围内，
这正是我们想要捉住的bug。
所以，有了上述的断言，任何企图设置时间对象
为非法状态的行为，都将遭到严厉的谴责，错了，都将立即被发现。