@@ -129,6 +129,9 @@ msgid ""
129
129
" x = 5 # Regular class attribute\n"
130
130
" y = Ten() # Descriptor instance"
131
131
msgstr ""
132
+ "class A:\n"
133
+ " x = 5 # 一般類別屬性\n"
134
+ " y = Ten() # 描述器實例"
132
135
133
136
#: ../../howto/descriptor.rst:62
134
137
msgid ""
@@ -145,6 +148,11 @@ msgid ""
145
148
">>> a.y # Descriptor lookup\n"
146
149
"10"
147
150
msgstr ""
151
+ ">>> a = A() # 建立類別 A 的實例\n"
152
+ ">>> a.x # 一般屬性查找\n"
153
+ "5\n"
154
+ ">>> a.y # 描述器查找\n"
155
+ "10"
148
156
149
157
#: ../../howto/descriptor.rst:73
150
158
msgid ""
@@ -202,6 +210,19 @@ msgid ""
202
210
" def __init__(self, dirname):\n"
203
211
" self.dirname = dirname # Regular instance attribute"
204
212
msgstr ""
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 # 一般實例屬性"
205
226
206
227
#: ../../howto/descriptor.rst:109
207
228
msgid ""
@@ -225,6 +246,15 @@ msgid ""
225
246
"updated\n"
226
247
"2"
227
248
msgstr ""
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"
228
258
229
259
#: ../../howto/descriptor.rst:122
230
260
msgid ""
@@ -288,6 +318,31 @@ msgid ""
288
318
" def birthday(self):\n"
289
319
" self.age += 1 # Calls both __get__() and __set__()"
290
320
msgstr ""
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__()"
291
346
292
347
#: ../../howto/descriptor.rst:172
293
348
msgid ""
@@ -325,6 +380,28 @@ msgid ""
325
380
"INFO:root:Accessing 'age' giving 40\n"
326
381
"40"
327
382
msgstr ""
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"
328
405
329
406
#: ../../howto/descriptor.rst:206
330
407
msgid ""
@@ -389,6 +466,36 @@ msgid ""
389
466
" def birthday(self):\n"
390
467
" self.age += 1"
391
468
msgstr ""
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"
392
499
393
500
#: ../../howto/descriptor.rst:256
394
501
msgid ""
@@ -508,17 +615,18 @@ msgstr ""
508
615
509
616
#: ../../howto/descriptor.rst:326
510
617
msgid "Complete Practical Example"
511
- msgstr ""
618
+ msgstr "完整實用範例 "
512
619
513
620
#: ../../howto/descriptor.rst:328
514
621
msgid ""
515
622
"In this example, we create a practical and powerful tool for locating "
516
623
"notoriously hard to find data corruption bugs."
517
624
msgstr ""
625
+ "在這個範例中,我們建立一個實用且強大的工具,用於找出惡名昭彰且難以發現的資料損壞錯誤。"
518
626
519
627
#: ../../howto/descriptor.rst:333
520
628
msgid "Validator class"
521
- msgstr ""
629
+ msgstr "驗證器類別 "
522
630
523
631
#: ../../howto/descriptor.rst:335
524
632
msgid ""
@@ -527,12 +635,14 @@ msgid ""
527
635
"restrictions. If those restrictions aren't met, it raises an exception to "
528
636
"prevent data corruption at its source."
529
637
msgstr ""
638
+ "驗證器是用於受管理屬性存取的描述器。在儲存任何資料之前,它會驗證新數值是否符合各種型別和範圍限制。如果不符合這些限制,它會引發例外以防止資料在源頭被損壞。"
530
639
531
640
#: ../../howto/descriptor.rst:340
532
641
msgid ""
533
642
"This :class:`!Validator` class is both an :term:`abstract base class` and a "
534
643
"managed attribute descriptor:"
535
644
msgstr ""
645
+ "這個 :class:`!Validator` 類別既是 :term:`抽象基底類別 <abstract base class>` 也是受管理屬性描述器:"
536
646
537
647
#: ../../howto/descriptor.rst:343
538
648
msgid ""
@@ -577,26 +687,29 @@ msgid ""
577
687
"Custom validators need to inherit from :class:`!Validator` and must supply "
578
688
"a :meth:`!validate` method to test various restrictions as needed."
579
689
msgstr ""
690
+ "自訂驗證器需要繼承自 :class:`!Validator` 並且必須提供 :meth:`!validate` 方法來依需要測試各種限制。"
580
691
581
692
#: ../../howto/descriptor.rst:368
582
693
msgid "Custom validators"
583
- msgstr ""
694
+ msgstr "自訂驗證器 "
584
695
585
696
#: ../../howto/descriptor.rst:370
586
697
msgid "Here are three practical data validation utilities:"
587
- msgstr ""
698
+ msgstr "以下是三個實用的資料驗證工具: "
588
699
589
700
#: ../../howto/descriptor.rst:372
590
701
msgid ""
591
702
":class:`!OneOf` verifies that a value is one of a restricted set of options."
592
703
msgstr ""
704
+ ":class:`!OneOf` 驗證數值是否為限制選項集合中的其中一個。"
593
705
594
706
#: ../../howto/descriptor.rst:374
595
707
msgid ""
596
708
":class:`!Number` verifies that a value is either an :class:`int` "
597
709
"or :class:`float`. Optionally, it verifies that a value is between a given "
598
710
"minimum or maximum."
599
711
msgstr ""
712
+ ":class:`!Number` 驗證數值是否為 :class:`int` 或 :class:`float`。可選地,它會驗證數值是否在給定的最小值或最大值之間。"
600
713
601
714
#: ../../howto/descriptor.rst:378
602
715
msgid ""
@@ -605,6 +718,7 @@ msgid ""
605
718
"`predicate <https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)>`_ "
606
719
"as well."
607
720
msgstr ""
721
+ ":class:`!String` 驗證數值是否為 :class:`str`。可選地,它會驗證給定的最小或最大長度。它還可以驗證使用者定義的 `述詞 <https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)>`_。"
608
722
609
723
#: ../../howto/descriptor.rst:383
610
724
msgid ""
@@ -664,11 +778,11 @@ msgstr ""
664
778
665
779
#: ../../howto/descriptor.rst:439
666
780
msgid "Practical application"
667
- msgstr ""
781
+ msgstr "實際應用 "
668
782
669
783
#: ../../howto/descriptor.rst:441
670
784
msgid "Here's how the data validators can be used in a real class:"
671
- msgstr ""
785
+ msgstr "以下展示如何在真實類別中使用資料驗證器: "
672
786
673
787
#: ../../howto/descriptor.rst:443
674
788
msgid ""
@@ -686,7 +800,7 @@ msgstr ""
686
800
687
801
#: ../../howto/descriptor.rst:456
688
802
msgid "The descriptors prevent invalid instances from being created:"
689
- msgstr ""
803
+ msgstr "描述器防止建立無效的實例: "
690
804
691
805
#: ../../howto/descriptor.rst:458
692
806
msgid ""
@@ -714,6 +828,28 @@ msgid ""
714
828
"\n"
715
829
">>> c = Component('WIDGET', 'metal', 5) # Allowed: The inputs are valid"
716
830
msgstr ""
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) # 允許:輸入有效"
717
853
718
854
#: ../../howto/descriptor.rst:484
719
855
msgid "Technical Tutorial"