@@ -129,6 +129,9 @@ msgid ""
129129" x = 5 # Regular class attribute\n"
130130" y = Ten() # Descriptor instance"
131131msgstr ""
132+ "class A:\n"
133+ " x = 5 # 一般類別屬性\n"
134+ " y = Ten() # 描述器實例"
132135
133136#: ../../howto/descriptor.rst:62
134137msgid ""
@@ -145,6 +148,11 @@ msgid ""
145148">>> a.y # Descriptor lookup\n"
146149"10"
147150msgstr ""
151+ ">>> a = A() # 建立類別 A 的實例\n"
152+ ">>> a.x # 一般屬性查找\n"
153+ "5\n"
154+ ">>> a.y # 描述器查找\n"
155+ "10"
148156
149157#: ../../howto/descriptor.rst:73
150158msgid ""
@@ -202,6 +210,19 @@ msgid ""
202210" def __init__(self, dirname):\n"
203211" self.dirname = dirname # Regular instance attribute"
204212msgstr ""
213+ "import os\n"
214+ "\n"
215+ "class DirectorySize:\n"
216+ "\n"
217+ " def __get__(self, obj, objtype=None):\n"
218+ " return len(os.listdir(obj.dirname))\n"
219+ "\n"
220+ "class Directory:\n"
221+ "\n"
222+ " size = DirectorySize() # 描述器實例\n"
223+ "\n"
224+ " def __init__(self, dirname):\n"
225+ " self.dirname = dirname # 一般實例屬性"
205226
206227#: ../../howto/descriptor.rst:109
207228msgid ""
@@ -225,6 +246,15 @@ msgid ""
225246"updated\n"
226247"2"
227248msgstr ""
249+ ">>> s = Directory('songs')\n"
250+ ">>> g = Directory('games')\n"
251+ ">>> s.size # songs 目錄有二十個檔案\n"
252+ "20\n"
253+ ">>> g.size # games 目錄有三個檔案\n"
254+ "3\n"
255+ ">>> os.remove('games/chess') # 刪除一個遊戲\n"
256+ ">>> g.size # 檔案數量自動更新\n"
257+ "2"
228258
229259#: ../../howto/descriptor.rst:122
230260msgid ""
@@ -288,6 +318,31 @@ msgid ""
288318" def birthday(self):\n"
289319" self.age += 1 # Calls both __get__() and __set__()"
290320msgstr ""
321+ "import logging\n"
322+ "\n"
323+ "logging.basicConfig(level=logging.INFO)\n"
324+ "\n"
325+ "class LoggedAgeAccess:\n"
326+ "\n"
327+ " def __get__(self, obj, objtype=None):\n"
328+ " value = obj._age\n"
329+ " logging.info('Accessing %r giving %r', 'age', value)\n"
330+ " return value\n"
331+ "\n"
332+ " def __set__(self, obj, value):\n"
333+ " logging.info('Updating %r to %r', 'age', value)\n"
334+ " obj._age = value\n"
335+ "\n"
336+ "class Person:\n"
337+ "\n"
338+ " age = LoggedAgeAccess() # 描述器實例\n"
339+ "\n"
340+ " def __init__(self, name, age):\n"
341+ " self.name = name # 一般實例屬性\n"
342+ " self.age = age # 呼叫 __set__()\n"
343+ "\n"
344+ " def birthday(self):\n"
345+ " self.age += 1 # 同時呼叫 __get__() 和 __set__()"
291346
292347#: ../../howto/descriptor.rst:172
293348msgid ""
@@ -325,6 +380,28 @@ msgid ""
325380"INFO:root:Accessing 'age' giving 40\n"
326381"40"
327382msgstr ""
383+ ">>> mary = Person('Mary M', 30) # 初始的 age 更新被記錄\n"
384+ "INFO:root:Updating 'age' to 30\n"
385+ ">>> dave = Person('David D', 40)\n"
386+ "INFO:root:Updating 'age' to 40\n"
387+ "\n"
388+ ">>> vars(mary) # 實際資料在私有屬性中\n"
389+ "{'name': 'Mary M', '_age': 30}\n"
390+ ">>> vars(dave)\n"
391+ "{'name': 'David D', '_age': 40}\n"
392+ "\n"
393+ ">>> mary.age # 存取資料並記錄查找\n"
394+ "INFO:root:Accessing 'age' giving 30\n"
395+ "30\n"
396+ ">>> mary.birthday() # 更新也會被記錄\n"
397+ "INFO:root:Accessing 'age' giving 30\n"
398+ "INFO:root:Updating 'age' to 31\n"
399+ "\n"
400+ ">>> dave.name # 一般屬性查找不會被記錄\n"
401+ "'David D'\n"
402+ ">>> dave.age # 只有受管理的屬性會被記錄\n"
403+ "INFO:root:Accessing 'age' giving 40\n"
404+ "40"
328405
329406#: ../../howto/descriptor.rst:206
330407msgid ""
@@ -389,6 +466,36 @@ msgid ""
389466" def birthday(self):\n"
390467" self.age += 1"
391468msgstr ""
469+ "import logging\n"
470+ "\n"
471+ "logging.basicConfig(level=logging.INFO)\n"
472+ "\n"
473+ "class LoggedAccess:\n"
474+ "\n"
475+ " def __set_name__(self, owner, name):\n"
476+ " self.public_name = name\n"
477+ " self.private_name = '_' + name\n"
478+ "\n"
479+ " def __get__(self, obj, objtype=None):\n"
480+ " value = getattr(obj, self.private_name)\n"
481+ " logging.info('Accessing %r giving %r', self.public_name, value)\n"
482+ " return value\n"
483+ "\n"
484+ " def __set__(self, obj, value):\n"
485+ " logging.info('Updating %r to %r', self.public_name, value)\n"
486+ " setattr(obj, self.private_name, value)\n"
487+ "\n"
488+ "class Person:\n"
489+ "\n"
490+ " name = LoggedAccess() # 第一個描述器實例\n"
491+ " age = LoggedAccess() # 第二個描述器實例\n"
492+ "\n"
493+ " def __init__(self, name, age):\n"
494+ " self.name = name # 呼叫第一個描述器\n"
495+ " self.age = age # 呼叫第二個描述器\n"
496+ "\n"
497+ " def birthday(self):\n"
498+ " self.age += 1"
392499
393500#: ../../howto/descriptor.rst:256
394501msgid ""
@@ -508,17 +615,18 @@ msgstr ""
508615
509616#: ../../howto/descriptor.rst:326
510617msgid "Complete Practical Example"
511- msgstr ""
618+ msgstr "完整實用範例 "
512619
513620#: ../../howto/descriptor.rst:328
514621msgid ""
515622"In this example, we create a practical and powerful tool for locating "
516623"notoriously hard to find data corruption bugs."
517624msgstr ""
625+ "在這個範例中,我們建立一個實用且強大的工具,用於找出惡名昭彰且難以發現的資料損壞錯誤。"
518626
519627#: ../../howto/descriptor.rst:333
520628msgid "Validator class"
521- msgstr ""
629+ msgstr "驗證器類別 "
522630
523631#: ../../howto/descriptor.rst:335
524632msgid ""
@@ -527,12 +635,14 @@ msgid ""
527635"restrictions. If those restrictions aren't met, it raises an exception to "
528636"prevent data corruption at its source."
529637msgstr ""
638+ "驗證器是用於受管理屬性存取的描述器。在儲存任何資料之前,它會驗證新數值是否符合各種型別和範圍限制。如果不符合這些限制,它會引發例外以防止資料在源頭被損壞。"
530639
531640#: ../../howto/descriptor.rst:340
532641msgid ""
533642"This :class:`!Validator` class is both an :term:`abstract base class` and a "
534643"managed attribute descriptor:"
535644msgstr ""
645+ "這個 :class:`!Validator` 類別既是 :term:`抽象基底類別 <abstract base class>` 也是受管理屬性描述器:"
536646
537647#: ../../howto/descriptor.rst:343
538648msgid ""
@@ -577,26 +687,29 @@ msgid ""
577687"Custom validators need to inherit from :class:`!Validator` and must supply "
578688"a :meth:`!validate` method to test various restrictions as needed."
579689msgstr ""
690+ "自訂驗證器需要繼承自 :class:`!Validator` 並且必須提供 :meth:`!validate` 方法來依需要測試各種限制。"
580691
581692#: ../../howto/descriptor.rst:368
582693msgid "Custom validators"
583- msgstr ""
694+ msgstr "自訂驗證器 "
584695
585696#: ../../howto/descriptor.rst:370
586697msgid "Here are three practical data validation utilities:"
587- msgstr ""
698+ msgstr "以下是三個實用的資料驗證工具: "
588699
589700#: ../../howto/descriptor.rst:372
590701msgid ""
591702":class:`!OneOf` verifies that a value is one of a restricted set of options."
592703msgstr ""
704+ ":class:`!OneOf` 驗證數值是否為限制選項集合中的其中一個。"
593705
594706#: ../../howto/descriptor.rst:374
595707msgid ""
596708":class:`!Number` verifies that a value is either an :class:`int` "
597709"or :class:`float`. Optionally, it verifies that a value is between a given "
598710"minimum or maximum."
599711msgstr ""
712+ ":class:`!Number` 驗證數值是否為 :class:`int` 或 :class:`float`。可選地,它會驗證數值是否在給定的最小值或最大值之間。"
600713
601714#: ../../howto/descriptor.rst:378
602715msgid ""
@@ -605,6 +718,7 @@ msgid ""
605718"`predicate <https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)>`_ "
606719"as well."
607720msgstr ""
721+ ":class:`!String` 驗證數值是否為 :class:`str`。可選地,它會驗證給定的最小或最大長度。它還可以驗證使用者定義的 `述詞 <https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)>`_。"
608722
609723#: ../../howto/descriptor.rst:383
610724msgid ""
@@ -664,11 +778,11 @@ msgstr ""
664778
665779#: ../../howto/descriptor.rst:439
666780msgid "Practical application"
667- msgstr ""
781+ msgstr "實際應用 "
668782
669783#: ../../howto/descriptor.rst:441
670784msgid "Here's how the data validators can be used in a real class:"
671- msgstr ""
785+ msgstr "以下展示如何在真實類別中使用資料驗證器: "
672786
673787#: ../../howto/descriptor.rst:443
674788msgid ""
@@ -686,7 +800,7 @@ msgstr ""
686800
687801#: ../../howto/descriptor.rst:456
688802msgid "The descriptors prevent invalid instances from being created:"
689- msgstr ""
803+ msgstr "描述器防止建立無效的實例: "
690804
691805#: ../../howto/descriptor.rst:458
692806msgid ""
@@ -714,6 +828,28 @@ msgid ""
714828"\n"
715829">>> c = Component('WIDGET', 'metal', 5) # Allowed: The inputs are valid"
716830msgstr ""
831+ ">>> Component('Widget', 'metal', 5) # 被阻止:'Widget' 不是全大寫\n"
832+ "Traceback (most recent call last):\n"
833+ " ...\n"
834+ "ValueError: Expected <method 'isupper' of 'str' objects> to be true for "
835+ "'Widget'\n"
836+ "\n"
837+ ">>> Component('WIDGET', 'metle', 5) # 被阻止:'metle' 拼寫錯誤\n"
838+ "Traceback (most recent call last):\n"
839+ " ...\n"
840+ "ValueError: Expected 'metle' to be one of {'metal', 'plastic', 'wood'}\n"
841+ "\n"
842+ ">>> Component('WIDGET', 'metal', -5) # 被阻止:-5 是負數\n"
843+ "Traceback (most recent call last):\n"
844+ " ...\n"
845+ "ValueError: Expected -5 to be at least 0\n"
846+ "\n"
847+ ">>> Component('WIDGET', 'metal', 'V') # 被阻止:'V' 不是數字\n"
848+ "Traceback (most recent call last):\n"
849+ " ...\n"
850+ "TypeError: Expected 'V' to be an int or float\n"
851+ "\n"
852+ ">>> c = Component('WIDGET', 'metal', 5) # 允許:輸入有效"
717853
718854#: ../../howto/descriptor.rst:484
719855msgid "Technical Tutorial"