1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
# 1、保留字
"""
False, None, True, and, as, assert, break, class, continue, def
del, elif, else, except, finally, for, from, global, if, import
in, is, lambda, nonlocal, not, or, pass, raise, return, try, while
with, yield
"""
import math
import operator
from typing import Tuple




# 2、行与缩进
if True:
print(True)
else:
print(False)

# print("缩进不一致会运行错误")




# 3、多行语句
# 如果语句很长用 \ 来实现多行语句
item_one = "123"
item_two = "456"
item_three = "789"
total = item_one + \
item_two + \
item_three
print(total)




# 4、数字类型(Number)
"""
四种: 整数, 布尔, 浮点, 复数
int, 只有这一种整数类型,表示长整数
bool, 如True
float, 如1.23
complex, 如1+2j, 1.1+2.2j
"""




# 5、字符串(String)
"""
单引号'和双引号"使用完全相同
三引号'''和"""
"""
可以指定一个多行字符串
转义字符 \
使用r可以让反斜杠不转义。如r"this is a line with \n",\n会显示,并不是换行
可以按字面意思级联字符串, 如"this ""is"" string"会字段转换为this is string
字符串可以用 + 连接, 用 * 重复
字符串有两种索引方式, 从左往右以0开始,从右往左以-1开始
字符串本身不能改变, 重新赋值只是新创建了一个对象,原本的对象值没有改变
无单独的字符类型, 一个字符就是长度为1的字符串
字符串的截取语法: 变量[头下标:尾下标:步长] 注意不包含尾下标
"""
print(r"你好\n")
print("this ""is"" string")
print("a" + "b")
print("age" * 2)
name = "my name is zs"
print(name[0], name[-1])
name = "my name is ww"
print(name)
print(name[1:-2:2])
name = """
大家好, 我是🐎牛逼
我喜欢吹牛
"""
print(name)




# 6、空行
"""
函数之间或类的方法之间用空行分隔, 表示一段新的代码开始。
类和函数入口之间也用一行空行分隔, 以突出函数入口的开始。
空行和代码缩进不同, 空行不是python语法的一部分。
书写时不插入空行, python解释器也不会出错。但是空行的作
用在于分隔两段不同功能或含义的代码, 便于日后代码的维护或重构
"""




# 7、等待用户输入
"""
以下代码, \n\n在结果输出前会输出两个新的空行。
一旦用户按下enter键时, 程序将退出。
"""
input("\n\n按下enter键后退出")




# 8、同一行显示多条语句
"""
语句之间使用; 隔开
"""
import sys; x = "runoob"; sys.stdout.write(x + "\n")




# 9、print输出
"""
print默认输出是换行的, 如果要实现不换行需要在末尾加上 end=""
"""
print("a")
print("b", end=" 8")




# 10、import 与 from...import
"""
在python用import或者from...import来导入相应的模块
将整个模块导入, 格式为: import somemoudle
从某个模块中导入某个函数, 格式为: from somemoudle import somefunction
从某个模块中导入多个函数, 格式为: from somemoudle import firstfunc, secondfunc, thirdfunc
将某个模块中的全部函数导入, 格式为: from somemoudle import *
"""
import sys
for i in sys.argv:
print(i)
print("\npython路径为", sys.path)

from sys import argv,path #导入特定的成员
print("path:", path)




# 11、命令行参数
"""
很多程序可以执行一些操作来查看一些基本信息, Python可以使用 -h 参数查看个参数帮助信息

$ python -h
usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ...
Options and arguments (and corresponding environment variables):
-c cmd : program passed in as string (terminates option list)
-d : debug output from parser (also PYTHONDEBUG=x)
-E : ignore environment variables (such as PYTHONPATH)
-h : print this help message and exit
[ etc. ]
"""




# 12、标准数据类型
"""
Python3中有6个标准的数据类型:
Number (数字)
String (字符串)
List (列表)
Tuple (元组)
Set (集合)
Dictionary (字典)

Python3的6个标准数据类型种:
不可变数据(3个) : Number(数字)、String(字符串)、Tuple(元组)
可变数据(3个) : List(列表)、Dictionary(字典)、Set(集合)
"""
a = b = c = 1
aa, bb, cc = 1, 2, "runoob"
print(a,b,c)
print(aa,bb,cc)
d, e, f, g = 20, 5.5, True, 4+3j

# <class 'int'> <class 'float'> <class 'bool'> <class 'complex'>
print(type(d), type(e), type(f), type(g))
print(isinstance(a, int)) # True

# isinstance 和 type 的区别在于
# type()不会认为子类是一种父类类型
# isinstance()会认为子类是一种父类类型
class A:
pass

class B(A):
pass

print(isinstance(A(), A)) #True
print(isinstance(B(), A)) #True
print(isinstance(B(), B)) #True
print(isinstance(A(), B)) #False
print(type(B()) == A) #False
print(type(B()) == B) #True

# Python3中, bool是int的子类, True和False可以和数字相加。
# True==1、False==0会返回True, 但可以通过is来判断类型
print(True == 1) #True
print(False == 0) #True
print(True + 1) #2
print(False + 1) #1
print(issubclass(bool, int)) #True

# 通过del删除单个或多个对象
var1 = 1; var2 = 2
print(var1, var2)
del var1, var2
# print(var1, var2) # 会报not defined
var3 = "we"
print(var3)
var3 = 12
print(var3)
var4 = 0xA0F # 十六进制
print(var4)
var4 = 0o37 # 八进制
print(var4)
var4 = 0b1010 # 二进制
print(var4)
var4d = [-1, 1, 66.25, 333, 1234.5]
del var4d[0]
print(var4d) # [1, 66.25, 333, 1234.5]
del var4d[2:4]
print(var4d) # [1, 66.25]
del var4d[:]
print(var4d) # []




# 13、数值运算
"""
在混合计算时, Python会把整型转换为浮点数

Python还支持复数, 复数由实数部分和虚数部分构成, 可以用a + bj,
或者complex(a, b)表示, 复数的实部a和虚部b都是浮点型
"""
print(5 + 4)
print(4.3 - 2)
print(3 * 7)
print(2 / 4) # 除法, 得到一个浮点数
print(2 // 4) # 除法, 得到一个整数
print(17 % 3) # 取余
print(2 ** 5) # 乘方
# //得到的并不一定是整数类型的数, 它与分母分子的数据类型有关系
var5 = 7//2.0
print(var5, type(var5)) # 3.0 <class 'float'>

# 在交互模式中, 最后被输出的表达式结果被赋值给变量 _ ,例如
"""
>>> tax = 12.5 / 100
>>> price = 100.50
>>> price * tax
12.5625
>>> price + _
113.0625
>>> round(_, 2)
113.06

# 此处, _ 变量应被用户视为只读变量
"""

comp = 2+3j; comp2=complex(2.34, 3.56)
print(comp, comp2)

# 数学函数
"""
abs(x) 返回数字的绝对值, 如abs(-10)返回10
ceil(x) 返回数字的上入整数, 如math.ceil(4.1) 返回5
cmp(x, y) 如果x<y返回-1, 如果x==y返回0, 如果x>y返回1。Python3已废弃, 使用(x>y)-(x<y)替换
exp(x) 返回e的x次幂(e^x), 如math.exp(1)返回2.718281828459045
fabs(x) 返回数字的绝对值, 如math.fabs(-10)返回10.0
floor(x) 返回数字的下舍整数, 如math.floor(4.9)返回4
log(x) 如math.log(math.e)返回1.0, math.log(100, 10)返回2.0, 这边这个参数10就是log底部数字
log10(x) 返回以10为基数的x的对数, 如math.log10(100)返回2.0
max(x1, x2, ...) 返回给定参数的最大值, 参数可以为序列
min(x1, x2, ...) 返回给定参数的最小值, 参数可以为序列
modf(x) 返回x的整数部分与小数部分(元组), 两部分的数值符号与x相同, 整数部分以浮点型表示
pow(x, y) x**y运算后的值
round(x[,n]) 返回浮点数x的四舍五入值, 如给出n值([]代表可选参数), 则代表舍入到小数点后的位数。准确的说是保留值将保留到离上一位更近的一端
sqrt(x) 返回数字x的平方根
"""
# 三角函数
"""
acos(x) 返回x的反余弦弧度值
asin(x) 返回x的反正弦弧度值
atan(x) 返回x的反正切弧度值
atan2(y, x) 返回给定的X及Y坐标值的反正切值
cos(x) 返回x的弧度的余弦值
hypot(x, y) 返回欧几里德范数sqrt(x*x + y*y)
sin(x) 返回的x弧度的正弦值
tan(x) 返回x弧度的正切值
degrees(x) 将弧度转换为角度, 如degrees(math.pi/2), 返回90.0
radians(x) 将角度转换为弧度
"""
# 数学常量
"""
pi 数学常量 pi (圆周率, 一般以π来表示)
e 数学常量 e, e即自然常数 (自然常数)
"""

# 海象运算符, 可在表达式内部为变量赋值。Python3.8新增运算符
if (num := len("abc"))>0:
print(num) # 3


# Python的逻辑运算符
"""
and x and y 布尔 "与" —— 如果x为False, x and y 返回x的值, 否则返回y的计算值
or x or y 布尔 "或" —— 如果x是True, 它返回x的值, 否则它返回y的计算值
not not x 布尔 "非" —— 如果x为True, 返回False。如果x为False, 它返回True
"""
num1 = 10
num2 = 20
print(num1 and num2) # 20
print(num1 or num2) # 10
print(not (num1 and num2)) # False
num1 = 0
if num1 and num2:
print("True")
else:
print("False") # False


# Python中的in 和 not in
"""
in 如果在指定的序列中找到返回True, 否则返回False。 如果x在y序列中返回True
not in 如果在指定的序列中没有找到返回True, 否则返回False。如果x不在y序列中返回True
"""
num3 = 10
num4 = 20
list1 = [1, 2, 3, 4, 5]
print(num3 in list1) # False
print(num3 not in list1) # True
num3 = 1
print(num3 in list1) # True


# Python身份运算符
"""
身份运算符用于比较两个对象的存储单元
is
is是判断两个标识符是不是引用自一个对象
x is y, 类似id(x)==id(y), 如果引用的是用一个对象则返回True, 否则返回False

is not
is not是判断两个标识符是不是引用自不同对象
x is not y, 类似id(x)!=id(y)。如果引用的不是同一个对象则返回结果True, 否则返回False
注: id()函数用于获取对象内存地址

is 与 == 的区别:
is 用于判断两个变量引用对象是否为同一个, == 用于判断引用变量的值是否相等
"""
num5 = 20
# num5 = 30
num6 = 20
if num5 is num6:
print("num5和num6有相同的标识")
else:
print("num5和num6没有相同的标识")

if id(num5) == id(num6):
print("num5和num6有相同的标识")
else:
print("num5和num6没有相同的标识")

list2 = [1, 2, 3]
list3 = list2
print(list2 is list3) # True
list3 = list2[:]
print(list2 is list3) # False


# Python 运算符优先级
"""
以下列表列出了从最高到最低优先级的所有运算符, 相同单元格内的运算符具有相同优先级。
运算符均指二元运算, 除非特别指出。相同单元格内的运算符从左至右分组 (除了幂运算是从右至左分组)

(expressions...),[expressions...],{key:value...},{expressions...} 圆括号表达式
x[index], x[index:index], x[arguments...], x.attribute 读取, 切片, 调用, 属性引用
await x await 表达式
** 乘方(指数)
+x, -x, ~x 正, 负, 按位非NOT
*, @, /, //, % 乘, 矩阵乘, 除, 整除, 取余
+, - 加和减
<<, >> 移位
& 按位与AND
^ 按位异或XOR
| 按位或OR
in, not in, is, is not, <, <=, >, >=, !=, == 比较运算, 包括成员检测和标识号检测
not x 逻辑非NOT
and 逻辑与AND
or 逻辑或OR
if —— else 条件表达式
lambda lambda表达式
:= 赋值表达式
"""

# 在这个例子中,首先使用 numpy 创建了两个不同形状的矩阵 A 和 B。
# 然后通过 @ 运算符计算它们的矩阵乘积,并将结果存储在 C 中。最后打印输出结果。
# 需要注意的是,为了使用 @ 运算符,你需要先安装 numpy 库,可以使用以下命令进行安装:
import numpy
A = numpy.array([[1, 2], [3, 4], [5, 6]])
B = numpy.array([[1, 2, 3], [4, 5, 6]])
C = A@B
print(C)


# 14、String字符串
strr = "Runoob"
print(strr[0:3]) #index不包含3 #Run
print(strr[-4:-1]) #index不包含-1 #noo
print(strr[1:-1]) #index不包含-1 #unoo
# 与C字符串不同的是,Python字符串不能被改变。
# 向一个索引位置赋值, 比如word[0] = "m"会导致错误
word = "Python"
print(word[0])
#word[0] = "b"
#print(word) # 输出不了, 后面的也不执行了


# Python支持格式化输出, 与C中sprintf函数一样的语法
"""
%c 格式化字符及其ASCII码
%s 格式化字符串
%d 格式化整数
%u 格式化无符号整数
%o 格式化无符号八进制数
%x 格式化无符号十六进制数
%X 格式化无符号十六进制数 (大写)
%f 格式化浮点数字, 可指定小数点后的精度
%e 用科学计数法格式化浮点数
%E 作用同%e, 用科学计数法格式化浮点数
%g %f和%e的简写
%G %f和%E的简写
%p 用十六进制数格式化变量的地址
"""
print("我叫 %s 今年 %d 岁!" % ("小明", 20))
# 格式化字符串辅助指令
"""
* 定义宽度或者小数点精度
- 用做左对齐
+ 在正数前面显示加号 (+)
<sp> 在正数前面显示空格
# 在八进制前面显示零("0"), 在十六进制前面显示"0x"或者"0X"(取决于用的是"x"还是"X")
0 显示的数字前面填充"0"而不是默认的空格
% "%%"输出一个单一的"%"
(var) 映射变量(字典参数)
m.n. m是现实的最小总宽度, n是小数点后的位数(如果可用的话)

Python2.6开始, 新增了一种格式化字符串的函数 str.format(), 它增强了字符串格式化的功能。
"""


# Python三引号
"""
python三引号允许一个字符串跨多行, 字符串中可以包含换行符、制表符及其他特殊字符
所以三引号可以帮助我们从特殊字符泥潭中走出, 所见即所得。
"""
para_str = """
这是一个多行字符的实例
多行字符串可以使用制表符TAB\t,也可以换行符\n
"""
print(para_str)


# f-string是python3.6之后的版本添加的称之为字面量格式化字符串, 是新的格式化字符串语法
name1 = "Runoob"
print("Hello %s" % name1) # Hello Runoob
# f-string以f开头, 后面跟着字符串, 字符串中的表达式用大括号{}包起来, 它会将变量或者表达式计算后的值替换进去
name2 = "Runoob"
print(f"Hello {name2}") # Hello Runoob
w = {"name":"Runoob", "url":"www.runoob.com"}
print(f"{w['name']}:{w['url']}") # Runoob:www.runoob.com
name3 = 1
print(f"{name3+1}") # 2
print(f"{name3+1=}") # name3+1=2


# Unicode字符串
"""
在Python2中, 普通字符串是以8位ASCII码进行存储的, 而Unicode字符串则存储为16位unicode字符串,
这样能够表示更多的字符集。使用的语法是在字符串前面加上前缀u。
在Python3中, 所有的字符串都是Unicode字符串
"""


# Python的字符串内建函数
"""
capitalize()
将字符串的第一个字符转换为大写

center(width, fillchar)
返回一个指定的宽度width居中的字符串, fillchar为填充的字符, 默认为空格

count(str, beg=0, end=len(string))
返回str在string里面出现的次数, 如果beg或者end指定则返回指定范围内str出现的次数

bytes.decode(encoding="utf-8", errors="strict")
Python3中没有decode方法, 但我们可以使用bytes对象的decode()方法来解码给定的bytes对象,
这个bytes对象可以由str.encode()来编码返回。

encode(encoding="UTF-8", errors="strict")
以encoding指定的编码格式编码字符串, 如果出错默认报一个ValueError的异常,
除非errors指定的是"ignore"或者"replace"

endswith(suffix, beg=0, end=len(string))
检查字符串是否以suffix结束, 如果beg或者end指定则检查指定的范围内是否以suffix结束,
如果是, 返回True, 否则返回False。

expandtabs(tabsize=8)
把字符串string中的tab符号转为空格, tab符号默认的空格数是8

find(str, beg=0, end=len(string))
检测str是否包含在字符串中, 如果指定范围beg和end, 则检查是否包含在指定范围内,
如果包含该字符串则返回开始的索引值, 否则返回-1

index(str, beg=0, end=len(string))
和find()方法一样, 只不过如果str不在字符串中会报一个异常

isalnum()
如果字符串至少有一个字符并且所有字符都是字母或数字则返回True, 否则返回False

isalpha()
如果字符串至少有一个字符并且所有字符都是字母或中文则返回True, 否则返回False

isdigit()
如果字符串只包含数字则返回True否则返回False

islower()
如果字符串中包含至少一个区分大小写的字符, 并且所有这些(区分大小写的)字符都是小写, 则返回True, 否则返回False

isnumeric()
如果字符串中只包含数字字符, 则返回True, 否则返回False

isspace()
如果字符串中只包含空白, 则返回True, 否则返回False

istitle()
如果字符串是标题化的(见title())则返回True, 否则返回False

isupper()
如果字符串中包含至少一个区分大小写的字符, 并且所有这些(区分大小写的)字符都是大写, 则返回True, 否则返回False

join(seq)
以指定字符串作为分隔符, 将seq中所有的元素(的字符串表示)合并为一个新的字符串

len(string) 返回字符串长度

ljust(width[,fillchar])
返回一个原字符串左对齐, 并使用fillchar填充至长度width的新字符, fillchar默认为空格

lower() 转换字符串中所有大写字符为小写

lstrip() 截掉字符串左边的空格或指定字符

maketrans()
创建字符映射的转换表, 对于接受两个参数的最简单的调用方式,
第一个参数是字符串, 表示需要转换的字符, 第二个参数也是字符串
表示转换的目标

max(str) 返回字符串str中最大的字母

min(str) 返回字符串str中最小的字母

replace(old, new [,max])
把字符串中的old替换成new, 如果max指定, 则替换不超过max次

rfind(str, beg=0, end=len(string))
类似于find()函数, 不过是从右边开始查找

rindex(str, beg=0, end=len(string))
类似于index(), 不过是从右边开始

rjust(width[,fillchar])
返回一个原字符串右对齐, 并使用fillchar(默认空格)填充至长度width的新字符串

rstrip() 删除字符串末尾的空格或指定字符

split(str="", num=string.count(str))
以str为分隔符截取字符串, 如果num有指定值, 则仅截取num+1个子字符串

splitlines([keepends])
按照行('\r','\r\n','\n')分隔, 返回一个包含各行作为元素的列表,
如果参数keepends为False, 不包含换行符, 如果为True, 则保留换行符

startswith(substr, beg=0, end=len(string))
检查字符串是否是以指定子字符串substr开头, 是则返回True, 否则返回False。
如果beg和end指定值, 则在指定范围内检查

strip([chars]) 在字符串上执行lstrip()和rstrip()

swapcase() 将字符串中大写转换为小写, 小写转换为大写

title()
返回"标题化"的字符串, 就是说所有单词都是以大写开始, 其余字母均为小写(见 istitle())

translate(table, deletechars="")
根据table给出的表(包含256各字符)转换string的字符, 要过滤掉的字符放到deletechars参数中

upper() 转换字符串中的小写字母为大写

zfill(width) 返回长度为width的字符串, 原字符串右对齐, 前面填充0

isdecimal() 检查字符串是否只包含十进制字符, 如果是返回true, 否则返回false

"""


# Python转义字符

#\ 在行尾 续行符 print("line1 \
# line2 \
# ")
#\\ 反斜杠符号 print("\\")
#\' 单引号 print("\'")
#\" 双引号 print('\"')
#\a 响铃 print("\a")
#\b 退格(Backspace) print("Hello \b World!")
#\000 空 print("\000")
#\n 换行 print("\n")
#\v 纵向制表符 print("Hello \v World!")
#\t 横向制表符 print("Hello \t World!")
#\r 回车,将\r后面的内容 print("Hello\rWorld")
# 移到字符串开头,并逐一
# 替换开头部分的字符,
# 直至将\r后面的内容
# 完全替换完成
#\f 换页 print("Hello \f World!")
#\yyy 八进制, y代表0-7的字符, print("\110\145\154\154\157\40\127\157\162\154\144\41")
# \012代表换行
#\xyy 十六进制数, 以\x开头,
# y代表的字符,例如:\x0a代表换行 print("\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21")




# 15、List(列表)
"""
Python有6个序列的内置类型, 但最常见的是列表和元组

List(列表)是Python中使用最频繁的数据类型。

列表可以完成大多数集合类的数据结构实现。

列表中元素的类型可以不相同, 它支持数字,
字符串甚至可以包含列表(所谓嵌套)。

列表是写在方括号 [] 里、用 , 分隔开的元素列表。
和字符串一样, 列表同样可以被索引和截取,
列表被截取后返回一个包含所需元素的新列表。

列表截取的语法格式: 变量[头下标 : 尾下标]

对于 myList[0::-1] 这个切片表达式:
0 指定了起始索引为 0,即从列表的第一个元素开始。
:: 表示步长为 -1,即逆向遍历列表。
[::-1] 表示从列表的最后一个元素开始,以逆向的方式遍历整个列表。

"""
# 索引以0为开始值, -1为从末尾的开始值
myList = ["abcd", 786, 2.23, "runoob", 70.2]
tinyList = [123, "runoob"]
print(myList) # ['abcd', 786, 2.23, 'runoob', 70.2]
print(myList[0]) # abcd
print(myList[1:3]) # [786, 2.23]
print(myList[2:]) # [2.23, 'runoob', 70.2]
print(tinyList * 2)# [123, 'runoob', 123, 'runoob']
print(myList + tinyList) #['abcd', 786, 2.23, 'runoob', 70.2, 123, 'runoob']

# 与Python字符串不一样的是, 列表中的元素是可以改变的
tinyList[0] = "我"
print(tinyList) # ['我', 'runoob']
myList[2:5]=[13, 14, 15]
#print(myList[5]) # 超出下标区间啥也不显示, 后面的也不执行了
print(myList) # ['abcd', 786, 13, 14, 15]
myList[2:5] = []
print(myList) # ['abcd', 786]
print(myList[::-1]) # [786, 'abcd']
print(myList[0::-1])# ['abcd']
print(myList[-1::-1])# [786, 'abcd']
myList.append("zhangsan") # 添加一个元素
print(myList) # ['abcd', 786, 'zhangsan']
del myList[2] # 删除一个元素
print(myList) # ['abcd', 786]
myList+=["zs", "ls"]# 支持拼接
print(myList) # ['abcd', 786, 'zs', 'ls']


# Python列表脚本操作符
"""
列表对+和*的操作符与字符串相似。+号用于组合列表, *号用于重复列表

Python表达式 结果 描述
len([1, 2, 3]) 3 长度
[1, 2, 3]+[4, 5, 6] [1, 2, 3, 4, 5, 6] 组合
["Hi!"]*4 ["Hi!","Hi!","Hi!","Hi!"] 重复
3 in [1, 2, 3] True 元素是否存在与列表中
for x in [1, 2, 3]:
print(x,end=" ") 1 2 3 迭代
"""


# 嵌套列表
list4 = ["a", "b", "c"]
list5 = [1, 2, 3]
list6 = [list4, list5]
print(list6) # [['a', 'b', 'c'], [1, 2, 3]]
print(list6[0]) # ['a', 'b', 'c']
print(list6[0][1]) # b

# 列表比较
list7 = [1, 2]
list8 = [2, 3]
list9 = [2, 3]
print(operator.eq(list7,list8)) # False
print(operator.eq(list8,list9)) # True

# Python列表截取可以接收第三个参数, 参数是截取的步长。
# 以下实例在索引1到索引4的位置并设置步长为2(间隔一个位置)来截取字符串
myLetters = ["r", "u", "n", "o", "o", "b"]
print(myLetters[1:4:2]) # ['u', 'o']

# 列表如果第三个数为负数表示逆向读取, 以下实例用于翻转字符串
def reverseWords(input):
# 通过空格把各个单词分隔为列表
inputWords = input.split(" ")
inputWords=inputWords[-1::-1]
return " ".join(inputWords)

inputStr = "I like Runoob"
inputStr = reverseWords(inputStr)
print(inputStr) # Runoob like I


# Python列表函数&方法
"""
Python包含以下函数:
len(list) 列表元素个数
max(list) 返回列表元素最大值
min(list) 返回列表元素最小值
list(seq) 将元组转换为列表

Python包含以下方法:
list.append(obj) 在列表末尾添加新的对象
list.count(obj) 统计某个元素在列表中出现的次数
list.extend(seq) 在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
list.index(obj) 从列表中找出某个值第一个匹配项的索引位置
list.insert(index, obj) 将对象插入列表
list.pop([index=-1]) 移除列表中的一个元素(默认最后一个元素), 并且返回该元素的值
list.remove(obj) 移除列表中某个值的第一个匹配项
list.reverse() 反转列表中的元素
list.sort(key=None, reverse=False) 对原列表进行排序
list.clear() 清空列表
list.copy() 复制列表
"""




# 16、Tuple(元组)
"""
元组(tuple)与列表类似, 不同之处在于元组的元素不能修改。
元组写在()里, 元素之间用 , 隔开。
元组中的元素类型也可以不相同。
元组也可以被索引和切片, 方法一样
注意构造包含0或1个元素的元组的特殊语法规则
元组也可以使用+操作符进行拼接
string、list和tuple都属于sequence(序列)
"""
myTuple = ("abcd", 786, 2.23, "runoob", 70.2)
tinyTuple = (123, "runoob")
print(myTuple) # ('abcd', 786, 2.23, 'runoob', 70.2)
print(myTuple[0]) # abcd
print(myTuple[1:3]) # (786, 2.23)
print(myTuple[2:]) # (2.23, 'runoob', 70.2)
print(tinyTuple*2) # (123, 'runoob', 123, 'runoob')
print(myTuple+tinyTuple) # ('abcd', 786, 2.23, 'runoob', 70.2, 123, 'runoob')
# tinyTuple[0]="123" # 修改元组元素的操作是非法的
tuple1 = "a", "b", "c", "d" # 这样也可以给元组赋值
print(tuple1, type(tuple1)) # ('a', 'b', 'c', 'd') <class 'tuple'>


# 虽然Tuple元素不可改变, 但它可以包含可变的对象, 比如list列表
tuple2 = ("a", "b", "c")
print(tuple2, hex(id(tuple2))) # ('a', 'b', 'c') 0x239d7728500
tuple2 = tuple([1, 2, 3])
print(tuple2, hex(id(tuple2))) # (1, 2, 3) 0x239d77309c0


# 构造包含0个或1个元素的元组比较特殊, 所以有一些额外的语法规则
tup1 = () # 空元组
tup2 = (20, ) # 一个元素, 需要在元素后添加逗号
tup3 = (30) # 否则将会识别为int类型
print(tup1, type(tup1)) # () <class 'tuple'>
print(tup2, type(tup2)) # (20,) <class 'tuple'>
print(tup3, type(tup3)) # 30 <class 'int'>

# 元组拼接
tup4 = ("a", "b", "c")
tup5 = (1, 2, 3)
tup6 = tup4 + tup5
print(tup6) # ('a', 'b', 'c', 1, 2, 3)

# 删除元组
del tup5
# print(tup5) 访问会出错

# 元组在输出时总是有括号的, 以便正确表达嵌套结构。
# 在输入时可能没有括号, 不过括号通常是必须的(如果元组是更大的表达式一部分)
tup7 = tup4, (1, 2, 3, 4)
print(tup7) # (('a', 'b', 'c'), (1, 2, 3, 4))



# 元组运算符
"""
与字符串一样, 元组之间可以使用+号和*号进行运算,
这就意味着它们可以组合和复制, 运算后会生成一个新的元组。

Python表达式 结果 描述
len((1, 2, 3)) 3 计算元素个数
(1, 2, 3)+(4, 5, 6) (1, 2, 3, 4, 5, 6) 连接
("Hi!", )*2 ("Hi!", "Hi!) 复制
3 in (1, 2, 3) True 元素是否存在
for x in (1, 2, 3):
print(x, end=" ") 1 2 3 迭代
"""


# 元组内置函数
"""
len(tuple) 计算元组元素个数
max(tuple) 返回元组中元素最大值
min(tuple) 返回元组中元素最小值
tuple(iterable) 将可迭代系列转换为元组
"""




# 17、Set(集合)
"""
集合(set)是由一个或数个形态各异的大小整体组成的(无序不重复),
构成集合的事务或对象称作元素或是成员。

基本功能是进行成员关系测试和删除重复元素。

可以使用大括号{}或者set()函数创建集合,
注意: 创建一个空集合必须用set()而不是{},
因为{}是用来创建一个空字典。
"""
parame = {"zs", "ls", 255, True, "ls"}
print(parame) # {True, 'ls', 'zs', 255}
parame2 = set("zsls")
print(parame2) # {'l', 'z', 's'}

# 成员测试
sites = {"Google", "Taobao", "Runoob", "Facebook", "Zhihu"}
print(sites)
if "Taobao" in sites:
print("找到了") # 找到了
else:
print("未找到")

# set可以进行集合运算
a = set("abracadabra")
b = set("alacazam")
print(a) # {'b', 'c', 'd', 'a', 'r'}
print(b) # {'c', 'm', 'z', 'a', 'l'}
print(a - b) # {'d', 'b', 'r'} 集合a中包含而b中不包含
print(a | b) # {'d', 'b', 'a', 'm', 'r', 'z', 'c', 'l'} 集合a、b中包含的所有元素
print(a & b) # {'a', 'c'} 集合a和b都包含的元素
print(a ^ b) # {'m', 'r', 'z', 'd', 'b', 'l'} 不同时包含于a和b的元素

# 添加元素
set1 = {"Google", "Runoob", "Taobao"}
set1.add("Taobao")
print(set1) # {'Runoob', 'Taobao', 'Google'} 如果元素已存在则不进行任何操作
# 还有一个方法也可添加元素, 参数可以是列表, 元组, 字典等
set1.update(["a", "b", "c"], ["d"])
print(set1) # {'a', 'b', 'Runoob', 'c', 'd', 'Google', 'Taobao'}

# 移除元素
set1.remove("d") # 不存在会发生错误
print(set1) # {'b', 'Taobao', 'c', 'a', 'Runoob', 'Google'}
set1.discard("b") # 不存在不会发生错误
print(set1) # {'c', 'a', 'Runoob', 'Google', 'Taobao'}
set1.pop() # 随机删除集合中的一个元素
print(set1) # {'c', 'a', 'Taobao', 'Runoob'}

# pop会对集合进行无序的排列, 然后将这个无需排列集合的左面第一个元素删除
set2 = set(("亚马逊", "谷歌", "微软"))
ret = set2.pop()
print(set2) # {'谷歌', '微软'}
print(ret) # 亚马逊

# 计算集合元素个数、清空集合
print(len(set2)) # 2
set2.clear()
print(set2) # set()

# 集合内置方法完整列表
"""
add() 为集合添加元素
clear() 移除集合中的所有元素
copy() 拷贝一个集合
difference() 返回多个集合的差集
difference_update() 移除集合中的元素, 该元素在指定的集合也存在
discard() 删除集合中指定的元素
intersection() 返回集合的交集
intersection_update() 返回集合的交集
isdisjoint() 判断两个集合是否包含相同的元素, 如果没有返回True, 否则False
issubset() 判断指定集合是否为该方法参数集合的子集
issuperset() 判断该方法的参数集合是否为指定集合的子集
pop() 随机移除元素
remove() 移除指定元素
symmetric_difference() 返回两个集合中不重复的元素集合
symmetric_difference_update() 移除当前集合中在另外一个指定集合相同的元素,
并将另外一个指定集合中不同的元素插入到当前集合中
union() 返回两个集合的并集
update() 给集合添加元素
"""
set2.difference()




# 18、Dictionary(字典)
"""
字典(dictionary)是Python中另一个非常有用的内置数据类型。
列表是有序的对象集合, 字典是无序的对象集合。
两者之间的区别在于: 字典当中的元素是通过键来存取的, 而不是通过偏移存取。
字典是一种映射类型, 字典用{}标识, 它是一个无序的
键(key):值(value) 的集合。
键(key)必须使用不可变类型。
在同一个字典中, 键(key)必须是唯一的。
"""
mydict = {} # 创建空字典
mydict["one"] = "我是菜鸟"
mydict[2] = "菜鸟应该多看书"
print(mydict) # {'one': '我是菜鸟', 2: '菜鸟应该多看书'}
print(mydict[2]) # 菜鸟应该多看书
print(mydict.keys()) # dict_keys(['one', 2])
print(mydict.values()) # dict_values(['我是菜鸟', '菜鸟应该多看书'])
print(list(mydict.keys())) # ['one', 2]
print(list(mydict.values())) # ['我是菜鸟', '菜鸟应该多看书']
mydict = {"one":1, "two":2}
print(mydict) # {'one': 1, 'two': 2}

# 构造函数dict()可以直接从键值对序列中构建字典如下
mydict2 = dict([("runoob",1),("Google",2),("TaoBao",3)])
print(mydict2) # {'runoob': 1, 'Google': 2, 'TaoBao': 3}

mydict3 = {x: x * 2 for x in (2, 4, 6)}
print(mydict3) # {2: 4, 4: 8, 6: 12}

mydict4 = dict(Runoob=1, Google=2, Taobao=3)
print(mydict4) # {'Runoob': 1, 'Google': 2, 'Taobao': 3}
# print(mydict4["jin"]) 如果用字典里没有的键访问数据, 会报错


# 在字典中遍历时, 关键字和对应的值可以使用items()方法同时解读出来
knights = {"gallahad":"the pure", "robin":"the brave"}
for k, v in knights.items():
print(k, v)
# gallahad the pure
# robin the brave

# 在序列中遍历时, 索引位置和对应值可以使用enumerate()函数同时得到:
for i, v in enumerate(["tic", "tac", "toe"]):
print(i, v)
# 0 tic
# 1 tac
# 2 toe


# 同时遍历两个或更多的序列, 可以使用zip()组合:
questions = ["name", "quest", "favorite color"]
answers = ["lancelot", "the holy grail", "blue"]
for q, a in zip(questions, answers):
print("What is your {0}? It is {1}".format(q, a))
# What is your name? It is lancelot
# What is your quest? It is the holy grail
# What is your favorite color? It is blue

# 删除字典元素
mydict5 = {"Name":"Runoob", "Age":"7", "Class":"First"}
print(mydict5) # {'Name': 'Runoob', 'Age': '7', 'Class': 'First'}
del mydict5["Name"] # 删除键 "Name"
print(mydict5) # {'Age': '7', 'Class': 'First'}
mydict5.clear() # 清空字典
print(mydict5) # {}
del mydict5 # 删除字典, 下面再访问此字典就报错了

# 字典键的特性
"""
字典值可以是任何的python对象, 既可以是标准的对象, 也可以是用户自定义的, 但键不行。
"""
# 不允许同一个键出现两次。如果同一个键被赋值两次, 后一个值会被记住
mydict6 = {"Name": "Runoob", "Age":7, "Name":"小菜鸟"}
print(mydict6) # {'Name': '小菜鸟', 'Age': 7}

# 键必须不可变, 所以可以用数字, 字符串或元组充当, 而用列表就不行
# mydict7 = {["Name"]:"Runoob", "Age":7} TypeError: unhashable type: 'list'
# print(mydict7)

# 字典内置函数&方法
"""
函数 描述
len(dict) 计算字典元素个数, 即键的总数
str(dict) 输出字典, 可以打印的字符串表示
type(variable) 函数返回输入的变量类型, 如变量是字典就返回字典类型
"""
mydict7 = {"Name":"Runoob", "Age":7, "Class":"First"}
print(len(mydict7)) # 3
print(type(str(mydict7)), type("123")) # <class 'str'> <class 'str'>

"""
Python字典包含了以下内置方法:
dict.clear() 删除字典内所有元素
dict.copy() 返回一个字典的浅复制
dict.fromkey(seq) 创建一个新字典, 以序列seq中元素做字典的值,val为字典所有键对应的初始值
dict.get(key, default=None) 返回指定键的值, 如果键不在字典中返回default设置的默认值
key in dict 如果键再字典dict里则返回True, 否则返回False
dict.items() 以列表返回一个视图对象
dict.keys() 返回一个视图对象
dict.setdefault(key, default=None) 和get()类似,但如果键不存在字典中, 将会添加键并将值设为default
dict.update(dict2) 把字典dict2的键/值对更新到dict里
dict.values() 返回一个视图对象
pop(key[,default]) 删除字典key(键)所对应的值, 返回被删除的值
popitem() 返回并删除字典中的最后一对键值对
"""




# 19、Python数据类型转换
"""
数据类型转换, 你只需要将数据类型作为函数名即可。
以下几个内置的函数可以执行数据类型之间的转换。
这些函数返回一个新的对象, 表示转换的值。

Python数据类型转换可以分为两种:
隐式转换——自动完成
显示转换——需要使用类型函数来转换
"""
""" []中是可选的
int(x[,base]) 将x转换为一个整数
float(x) 将x转换到一个浮点数
complex(real[,imag]) 创建一个复数
str(x) 将对象x转换为字符串
repr(x) 将对象x转换为表达式字符串
eval(str) 用来计算在字符串中的有效Python表达式, 并返回一个对象
tuple(x) 将序列s转换为一个数组
list(s) 将序列s转换为一个列表
set(s) 转换为可变集合
dict(d) 创建一个字典。d必须是一个(key,value)元素序列。
frozenset(s) 转换为不可变集合
chr(x) 将一个整数转换为一个字符
ord(x) 将一个字符转换为它的整数值
hex(x) 将一个整数转换为一个十六进制字符串
oct(x) 将一个整数转换为一个八进制字符串
"""
# 下面实例中, 对两种不同类型的数据进行运算, 较低的数据类型(整数)就会转换为较高数据类型(浮点型), 以免数据丢失
num_int = 123
num_flo = 1.23
num_new = num_int + num_flo
print("datatype of num_int", type(num_int)) # <class 'int'>
print("datatype of num_flo", type(num_flo)) # <class 'float'>
print(num_new, "datatype of num_flo", type(num_new)) # 124.23 <class 'float'>

num_str = "123"
#num_new = num_int + num_str # 整型和字符串型直接运算结果会报错,可以使用显示转换
num_new = num_int + int(num_str)
print(num_new) # 246




# 20、Python推导式
"""
Python推导式是一种独特的数据处理方式, 可以从一个数据序列构建另一个新的数据序列的结构体。
Python支持各种数据结构的推导式:
列表(list)推导式
字典(dict)推导式
集合(set)推导式
元组(tuple)推导式
"""
# 列表推导式
"""
[表达式 for 变量 in 列表]

[表达式 for 变量 in 列表 if 条件]
[out_exp_res for out_exp in input_list if condition]

out_exp_res: 列表生成元素表达式, 可以是有返回值的函数。
for out_exp in input_list: 迭代input_list将out_exp传入到out_exp_res表达式中。
if condition: 条件语句, 可以过滤列表中不符合条件的值
"""
# 过滤掉长度小于或等于3的字符串列表, 并将剩下的转换成大写字母
names = ["Bob", "Tom", "Alice", "Jerry", "Wendy", "Smith"]
new_names = [name.upper() for name in names if len(name) > 3]
print(new_names) # ['ALICE', 'JERRY', 'WENDY', 'SMITH']

# 计算30以内可以被3整除的整数
nums = [i for i in range(30) if i % 3 == 0]
print(nums) # [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]

# 小花样
list2d = [2, 4, 6]
list2dd = [[2*x, 3*x] for x in list2d]
print(list2dd)

# 关于循环的其他技巧
list3d = [2, 4, 6]
list4d = [4, 3, -9]
list5d = [x*y for x in list3d for y in list4d]
print(list5d) # [8, 6, -18, 16, 12, -36, 24, 18, -54]
list6d = [list3d[i]*list4d[i] for i in range(len(list3d))]
print(list6d) # [8, 12, -54]

# 列表推导式可以使用复杂表达式或嵌套函数
list7d = [str(round(355/113, i)) for i in range(1, 6)]
print(list7d) # ['3.1', '3.14', '3.142', '3.1416', '3.14159']

# 嵌套列表解析
matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
]
matrix2 = [[row[i] for row in matrix] for i in range(4)]
print(matrix2) # [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

transposed = []
for i in range(4):
transposed.append([row[i] for row in matrix])
print(transposed) # [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
transposed = []
for i in range(4):
transposed_row = []
for row in matrix:
transposed_row.append(row[i])
transposed.append(transposed_row)
print(transposed) # [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]



# 字典推导式
"""
{ key_expr: value_expr for value in collection }

{ key_expr: value_expr for value in collection if condition }
"""
# 使用字符串及其长度创建字典
listDemo = ["Google", "Runoob", "Taobao"]
dicts = { key : len(key) for key in listDemo }
print(dicts) # {'Google': 6, 'Runoob': 6, 'Taobao': 6}

# 提供三个数字, 以三个数字为键, 三个数字的平方为值来创建字典
dicts2 = {num : num**2 for num in [4, 7, 2]}
print(dicts2) # {4: 16, 7: 49, 2: 4}


# 集合推导式
"""
{expression for item in Sequence}

{expression for item in Sequence if condition}
"""
# 计算数字1,2,3的平方根 (set中是乱序的)
numset = {x**0.5 for x in [1, 2, 3]}
print(numset) # {1.0, 1.7320508075688772, 1.4142135623730951}

# 判断不是abc的字母并输出
charset = {char for char in "abreadfagaewc" if char not in "abc"}
print(charset) # {'g', 'f', 'r', 'e', 'w', 'd'}


# 元组推导式(生成器表达式)
"""
元组推导式可以利用range区间、元组、列表、字典和集合等数据类型, 快速生成一个满足指定需求的元组。

(expression for item in Sequence)

(expression for item in Sequence if condition)

元组推导式和列表推导式的用法也完全相同, 只是元组推导式是用()圆括号将各个部分括起来,
而列表推导式用的是中括号[], 另外元组推导式返回的结果是一个生成器对象。

生成器和列表推导式都是用于简化代码和创建可迭代对象的工具,但它们在实现方式和特点上存在一些区别。

共同点:
都可以用于快速生成元素序列。
都支持筛选、变换等操作。

区别:
生成器是一种惰性求值(lazy evaluation)的机制,可以逐个生成结果并在需要时计算,而列表推导式会立即生成一个完整的列表。
生成器只在需要时才会生成下一个元素,因此可以节省内存空间,而列表推导式会一次性生成所有元素,占用更多内存。
生成器的结果是通过 yield 关键字逐个产生的,而列表推导式的结果是一个完整的列表。
生成器可以处理无限序列,而列表推导式则不适用于无限序列。

"""
# 生成一个包含数字 1~9 的元组
numtuble = (x for x in range(0, 9)) # 返回的是生成器对象
print(numtuble) # <generator object <genexpr> at 0x000002474F278580>
print(tuple(numtuble)) # 使用tuple()函数, 可直接将生成器对象转为元组
# (0, 1, 2, 3, 4, 5, 6, 7, 8)

listt = ["Python", "test1", "test2"] # ['PYTHON', 'test1', 'test2']
print([word if word.startswith("t") else word.upper() for word in listt])





# 21、Python解释器
"""
我们可以将Python3安装在 /usr/local/python3目录中。
安装完成后将路径 /usr/local/python3/bin添加到Linux环境变量中,
这样您就可以在shell中输入下面的命令来启动Python3
$ PATH=$PATH:/usr/local/python3/bin/python3 #设置环境变量
$ python3 --version
Python 3.4.0

在windows系统中, 假设Python安装在 C:\Python3下
set path=%path%;C:\python3

Python解释器不止一种,有CPython、IPython、Jython、PyPy等。
CPython就是用C语言开发的, 是官方标准实现, 拥有良好的生态, 所以应用也就最为广泛了。
而IPython是在CPython的基础上在交互方式方面得到增强的解释器 (http://ipython.org/)

Jython是专为Java平台设计的Python解释器 (http://www.jython.org),它把Python代码
编译为Java字节码执行。

PyPy是Python语言 (2.7.13和3.5.3)的一种快速、兼容的替代实现 (http://pypy.org/), 以速度快著称。
"""

"""
在Linux系统中, 你可以在脚本顶部添加以下命令让Python脚本可以像Shell脚本一样可以直接执行
#! /usr/bin/env python3

然后修改脚本权限, 使其有执行权限, 命令如下:
$ chmod +x hello.py

执行以下命令
./hello.py

输出结果为
Hello, Python!
"""




# 22、Python3条件控制
"""
Python中使用elif代替了else if, 所以if语句的关键字为: if—elif—else(可以嵌套进行)
注意:
每个条件后面要使用冒号 : ,表示接下来是满足条件后要执行的语句块
使用缩进来划分语句块, 相同缩进数的语句在一起组成了一个语句块
在Python中没有switch—case语句
"""
var6 = 100
if var6:
print("表达式条件为True")

var6=0
if var6:
print("表达式条件为True")
print(var6)
print("GoodBye")

age = input("请输入年龄: ")
age = int(input("请输入年龄: "))
if age<=0:
print("age<0")
elif age==1:
print("age==1")
elif age==2:
print("age==2")
else:
print(age)




# 23、Python3循环语句
"""
while 判断条件:
...

Python中没有do...while循环

# while循环使用else语句
如果while后面的条件语句为false时, 则执行else语句块
while 判断条件:
...
else :
...

"""
count = 0
while count<5:
print(count, "小于5")
count+=1
else:
print(count, "大于等于5")

"""
for 语句
Python for循环可以遍历任何可迭代对象, 如一个列表或者一个字符串。
在穷尽列表(for)或条件变为false(while)将导致循环终止时执行else子句,
但循环被break终止时不执行

for <variable> in <sequence>:
<statements>
else:
<statements>
"""
lang = ["C", "C++", "Perl", "Python"]
for var in lang:
print(var)

mysites = ["Baidu", "Google", "Runoob", "Taobao"]
for site in mysites:
if site == "Runoob":
print("菜鸟教程")
break
print("循环数据"+site)
else:
print("没有循环数据!")
print("完成循环!")
"""
循环数据Baidu
循环数据Google
菜鸟教程
完成循环!
"""

# range()函数
for i in range(5, 9):
print(i)

# 也可以使range以指定数字开始并指定不同点增量(甚至可以是负数, 有时这也叫做"步长")
for i in range(0, 10, 3):
print(i)

# 可以结合range()和len()函数以遍历一个序列的索引
forlist = ["谷歌", "百度", "菜鸟", "淘宝"]
for i in range(len(forlist)):
print(i, forlist[i])

# 借助range()函数来创建一个列表
list8 = list(range(5))
print(list8) # [0, 1, 2, 3, 4]

"""
break语句可以跳出for和while的循环体。
如果你从for或while循环中终止, 任何对应的循环else块将不执行

continue语句被用来告诉Python跳过当前循环中的剩余语句,
然后继续进行下一轮
"""
for letter in "Runoob":
if letter == "b":
break
print(letter)

var7 = 10
while var7 > 0:
print("当前遍历值为: ", var7)
var7 -= 1
if var7 == 5:
break

print("Bye!!!")

# 查找质数
for i in range(2,10):
for j in range(2, i):
if i % j == 0:
print(i, "等于", j, "*", i//j)
break
else:
print(i, "是质数")




# 24、pass语句
"""
Python pass是空语句, 是为了保持程序结果的完整性
pass不做任何事情, 一般用作占位语句, 如下实例
"""

# while True:
# pass # 等待键盘中断 (Ctrl + C)

for let in "Runoob":
if let == "o":
pass # 如果没有内容, 可以先写pass, 但是如果不写pass, 就会语法报错
print("执行pass块")
print("当前字母: ", let)

print("Good Bye!")




# 25、Python3迭代器和生成器
"""
迭代是Python最强大的功能之一, 是访问集合元素的一种方式
迭代器是一个可以记住遍历位置的对象
迭代器对象从集合的第一个元素开始访问, 直到所有的元素被访问完结束。
迭代器只能往前不会后退
迭代器有两个基本的方法: iter()和next()
字符串, 列表或元组对象都可用于创建迭代器
"""
list10 = [1, 2, 3, 4, 5]
ite = iter(list10)
#print(next(ite)) # 1
#print(next(ite)) # 2

# 迭代器对象可以使用常规的for语句进行遍历
for x in ite:
print(x, end=" ") # 1 2 3 4 5
print()

# 也可以使用next()函数来迭代
list11 = [1, 2, 3, 4, 5]
ite = iter(list11)
while True:
try:
print(next(ite))
except StopIteration:
pass
break

# 创建一个迭代器
"""
把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__()与__next__()
Python的构造函数为__init__(), 它会在对象初始化时执行。

__iter__()方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__()
方法并通过StopIteration异常标识迭代完成。
__next__()方法会返回下一个迭代器对象。
"""
# 创建一个返回数字的迭代器
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 1
return x

myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter)) # 1
print(next(myiter)) # 2
print(next(myiter)) # 3
print(next(myiter)) # 4


# StopIteration异常
"""
StopIteration异常用于标识迭代的异常, 防止出现无限循环的情况。
在__next__()方法中我们可以设置在完成直到循环次数后触发StopIteration来结束迭代
"""
class MyNumber2:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration
myClass = MyNumber2()
myiter = iter(myClass)
for x in myiter:
print(x)


# 生成器
"""
在Python中, 使用了yield的函数被称为生成器(generator)。

跟普通函数不同的是, 生成器是一个返回迭代器的函数, 只能用于迭代操作,
更简单点理解生成器就是一个迭代器。

在调用生成器运行的过程中, 每次遇到yield时函数会暂停并保存当前所有的
运行信息, 返回yield的值, 并在下一次执行next()方法时从当前位置继续运行。

调用一个生成器函数, 返回的是一个迭代器对象。
"""
# 以下实例使用yield实现斐波那契数列
import sys
def fibonacci(n): # 生成器函数—斐波那契
a, b, counter = 0, 1, 0
while True:
if counter>n:
return
yield a
a, b = b, a + b
counter += 1

f = fibonacci(10) # f是一个迭代器, 由生成器返回生成

while True:
try:
print(next(f), end=" ")
except StopIteration:
break
print()




# 26、Python3函数
"""
函数是组织好的, 可重复使用的, 用来实现单一的, 或相关联功能的代码段。
函数能提高应用的模块性, 和代码的重复利用率。
你知道Python提供了许多内建函数, 比如print()。你也可以自己创建函数,
这被叫做用户自定义函数。

函数定义规则:
函数代码块以def关键词开头, 后接函数标识符名称和圆括号()。
任何传入参数和自变量必须放在圆括号之间, 圆括号之间可以用于定义参数。
函数的第一行语句可以选择性地使用文档字符串——用于存放函数说明。
函数内容以冒号:起始, 并且缩进。
return [表达式]结束函数, 选择性地返回一个值给调用方, 不带表达式的return相当于返回None。

def 函数名 (参数列表) :
函数体
"""

# 比较两个数, 并返回较大的数
def max(a, b):
if a > b:
return a
else:
return b

print(max(10, 20))


# 参数传递
"""
在Python中, 类型属于对象, 对象有不同类型的区分, 变量是没有类型的:
a = [1, 2, 3]
a = "Runoob"
以上代码中, [1, 2, 3]是list类型, "Runoob"是string类型, 而变量a是没有类型,
它仅仅是一个对象的引用(一个指针), 可以是指向list类型对象, 也可以是指向string类型对象。
"""

# 可更改(mutable)与不可更改(immutable)对象
"""
在Python中, strings, tuples,和numbers是不可更改的对象, 而list, dict等则是可修改对象。

不可变类型: 变量赋值 a=5 后再赋值 a=10, 这里实际是新生成一个int值对象10, 再让a指向它,
而5被丢弃, 不是改变a的值, 相当于新生成了a。
可变类型: 变量赋值 la=[1, 2, 3, 4]后再赋值 la[2]=5则是将 list la的第三个元素值更改,
本身la没有动, 只是其内部的一部分值被修改了。

Python函数的参数传递:
不可变类型: 类似c++的值传递, 如整数、字符串、元组。如 fun(a),传递的只是a的值, 没有影响a
对象本身。如果在fun(a)内部修改a的值, 则是生成一个a的对象。

可变类型: 类似C++的引用传递, 如列表, 字典。如fun(la), 则是将la真正的传过去, 修改后fun()
外部的la也会受影响。

Python中一切都是对象, 严格意义我们不能说值传递还是引用传递, 我们应该说传不可变对象和传可变对象。
"""
# 通过id()函数来查看内存地址变化
def change(a):
print(hex(id(a))) # 指向的是同一个对象 0x7ffc596b1710
a = 10
print(hex(id(a))) # 一个新对象 0x7ffc596b1830

a = 1
print(hex(id(a))) # 0x7ffc596b1710
change(a)

# 传可变对象实例
def changeme (mylist):
mylist.append([1, 2, 3, 4])
print("函数内取值: ", mylist)
return

myList = [10, 20, 30]
changeme(myList)
print("函数外取值: ", myList)
# 函数内取值: [10, 20, 30, [1, 2, 3, 4]]
# 函数外取值: [10, 20, 30, [1, 2, 3, 4]]

# 参数
"""
以下是调用函数时可以使用的正式参数类型:
必须参数
关键字参数
默认参数
不定长参数
"""
# 必须参数 必须以正确的顺序传入函数, 调用时的数量必须和声明时的一样。
def printme(str):
print(str)
return
printme("Hello") # 调用时候必须传入一个参数, 不然报错

# 关键字参数和函数调用关系紧密, 函数调用使用关键字参数来确定传入的参数值
# 使用关键字参数允许函数调用时参数的顺序与声明时不一致, 因为Python解释器
# 能够用参数名匹配参数值
printme(str= "ByeBye")

# 默认参数, 如果没有传递参数, 则会使用默认参数。以下实例中如果没有传入age, 则使用默认
def printfo(name, age = 25):
print("名字: ", name)
print("年龄: ", age)
return
printfo(age=30, name="zhangsan")
printfo("lisi")

# 不定长参数, 可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数
# 加了 * 的参数会以元组(tuple)的形式导入, 存放所有未命名的变量参数
"""
def functionname([formal_args,] *var_args_tuple):
function_suite
return [expression]
"""
def functionname(arg1, *vartuple):
print(arg1)
print(vartuple)
return

functionname(70, 80, 90) #70
#(80, 90)


# 如果在函数调用时没有指定参数, 它就是一个空元组,
# 我们也可以不向函数传递未命名的变量
def printminfo(arg, *vartuple):
print(arg)
for i in vartuple:
print(i)
return

printminfo(10) # 10
printminfo(70, 60, 50, 40)

# 还有一种就是参数带两个**
"""
def functionname([formal_args,] **var_args_dict):
function_suite
return [expression]
"""
def printinfo(arg1, **vardict):
print(arg1)
print(vardict)
return

printinfo(1, a=2, b=3)
# 1
# {'a': 2, 'b': 3}

# 声明函数时, 参数中的星号*可以单独出现
# 如果单独出现*, 则*后的参数必须用关键字传入
def f(a, b, *, c):
return a+b+c

f(10, 20, c=30)
# f(10, 20, 30) 报错




# 匿名函数
"""
Python使用lambda来创建匿名函数
所谓匿名, 意思就是不再使用def语句这样标准的形式定义一个函数

lambda只是一个表达式, 函数体比def简单很多。
lambda的主体是一个表达式, 而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
lambda函数拥有自己的命名空间, 且不能访问自己参数列表之外或全局命名空间里的参数。

虽然lambda函数看起来只能写一行, 却不等同于C或C++的内联函数, 后者的目的是调用小函数
时不占用栈内存从而增加运行效率。

语法:
lambda [arg1 [,arg2,....argn]]:expression

"""

# 设置参数a加上10
xx = lambda a : a + 10
print(xx(10)) # 20

summ = lambda arg1, arg2 : arg1 + arg2
print(summ(10, 20)) # 30

# 我们可以将匿名函数封装在一个函数内, 这样可以使用同样的代码
# 来创建多个匿名函数。
def myfunc(n):
return lambda a : a * n

f1 = myfunc(2)
f2 = myfunc(5)
print(f1(11)) # 22
print(f2(11)) # 55

# Lambda 表达式也可以用于条件表达式,使代码更简洁
is_even = lambda x: True if x % 2 == 0 else False
print(is_even(4)) # 输出:True
print(is_even(7)) # 输出:False

# Lambda 表达式可以作为其他函数的参数进行传递,例如在排序或映射操作中使用
numbers = [5, 2, 8, 1, 6]
sorted_numbers = sorted(numbers, key=lambda x: x % 3)
print(sorted_numbers) # 输出:[6, 2, 5, 8, 1]

# Lambda 表达式还可以嵌套使用,以构建更复杂的函数
calculate = lambda op: (lambda x, y: x + y if op == 'add' else x * y)
add_func = calculate('add')
multiply_func = calculate('multiply')
print(add_func(2, 3)) # 输出:5
print(multiply_func(2, 3)) # 输出:6


# return [表达式]用于退出函数选择性的向调用方返回表达式,
# 不带参数值的return语句返回None。
def sum(arg1, arg2):
total = arg1 + arg2
print(hex(id(total))) # 0x7ffc573218d0
return total

total = sum(10, 5)
print(hex(id(total))) # 0x7ffc573218d0

# 强制位置参数
"""
Python3.8新增了一个函数形参语法 / 用来指明函数形参必须使用指定位置参数,
不能使用关键字参数的形式。

在以下的例子中, 形参 a 和 b 必须使用指定位置参数, c或d可以是位置形参或
关键字形参, 而e和f要求为关键字形参
"""
def fff(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)

fff(10, 20, 30, 40, e=50, f=60)
# fff(10, b=20, c=30, d=40, e=50, f=60) b不能用关键字参数形式
# fff(10, 20, 30, 40, 50, f=60) e必须使用关键字参数的形式




# 27、Python3数据结构
"""
Python中列表是可变的, 这是它区别于字符串和元组最重要的特点。
一句话概括即: 列表可以修改, 而字符串和元组不能。


方法 描述
list.append(x) 把一个元素添加到列表的结尾, 相当于 a[len(a):] = [x]
list.extend(L) 通过添加指定列表的所有元素来扩充列表, 相当于a[len(a):] = L
list.insert(i, x) 在指定位置插入一个元素, 第一个参数是准备插入到其前面的那个元素的索引,
例如 a.insert(0, x)会插入到整个列表之前, 而a.insert(len(a), x)相当于a.append(x)
list.remove(x) 删除列表中值为x的第一个元素。如果没有这样的元素, 就会返回一个错误。
list.pop([i]) 从列表的指定位置移除元素, 并将其返回。如果没有指定索引, a.pop()返回最后一个元素。
元素随机从列表中被移除。(方法中i两边的方括号表示这个参数是可选的, 而不是要求你输入
一对方括号, 你会经常在Python库参考手册中遇到这样的标记。)
list.clear() 移除列表中的所有项, 等于del a[:]
list.index(x) 返回列表中第一个值为x的元素的索引。如果没有匹配的元素就会返回一个错误。
list.count(x) 返回x在列表中出现的次数。
list.sort() 对列表中的元素进行排序
list.reverse() 倒排列表中的元素
list.copy() 返回列表的浅复制, 等于a[:]。
"""
list12 = [66.25, 333, 345, 1, 125, 8.5]
print(list12.count(333), list12.count(345), list12.count("x")) #1 1 0
list12.insert(3, "nihao")
print(list12) # [66.25, 333, 345, 'nihao', 1, 125, 8.5]
list12.append("apend")
print(list12)
#... 类似insert, remove或sort等修改列表的方法没有返回值


# 将列表当做堆栈使用/将列表当队列使用
"""
列表方法使得列表可以很方便的作为一个堆栈来使用, 堆栈作为特定的数据结构,
最先进入的元素最后一个被释放(后进先出)。用append()方法可以把一个元素添
加到堆栈顶。用不指定索引的pop()方法可以把一个元素从堆栈顶释放出来。

也可以把列表当队列用, 只是在队列里第一个加入的元素, 第一个取出来。但是拿
列表用作这样操作的效率不高。在列表的最后添加或者弹出元素速度快, 然而在列
表里插入或者从头部弹出速度却不快 (因为所有其他的元素都得一个一个地移动)
"""
from collections import deque
myQueue = deque(["Eric", "John", "Michael"])
print(myQueue) # deque(['Eric', 'John', 'Michael'])
myQueue.append("Terry")
myQueue.append("Graham")
print(myQueue) # deque(['Eric', 'John', 'Michael', 'Terry', 'Graham'])
myQueue.popleft()
print(myQueue) # deque(['John', 'Michael', 'Terry', 'Graham'])




# 28、Python3模块
"""
模块是一个包含所有你定义的函数和变量的文件, 其后缀名是 .py。
模块可以被别的程序引入, 以使用该模块中的函数等功能。
这也是使用python标准库的方法
"""
# import sys引入python标准库中的 sys.py 模块, 这是引入某一模块的方法。
# sys.argv 是一个包含命令行参数的列表
# sys.path 包含了一个Python解释器自动查找所需模块的路径的列表
import sys
for i in sys.argv:
print(i) # E:\CLion2022.2.3\Project\primertest\Test.py
print(sys.path)

# import语句
"""
想使用Python源文件, 只需在另一个源文件里执行import语句, 语法如下:
import module1[, module2][, ...moduleN]]
当解释器遇到import语句, 如果模块在当前的搜索路径就会被导入。
搜索路径是一个解释器会先进行搜索的所有目录的列表。如果想要导入模块support,
需要把命令放在脚本的顶端

support.py 文件
#!/usr/bin/python3
#Filename: support.py
def print_func(par):
print("Hello:", par)
return

test.py引入support模块
#!/usr/bin/python3
#Filename: test.py
#导入模块
import support
#现在可以调用模块里包含的函数了
support.print_func("Runoob")
"""

"""
一个模块只会被导入一次, 不管你执行了多少次import。
这样可以防止导入模块被一遍又一遍地执行。

当我们使用import语句的时候, Python解释器是怎样找到对应的文件的呢?
这就涉及到Python的搜索路径, 搜索路径是由一系列目录名组成的, Python
解释器就依次从这些目录中去寻找所引入的模块。

这看起来很像环境变量, 事实上也可以通过定义环境变量的方式来确定搜索路径。
搜索路径是在Python编译或安装的时候确定的, 安装新的库应该也会修改。
搜索路径被存储在sys模块中的path变量。

被导入的模块的名称将被放入当前操作的模块的符号表中。
"""
import sys
print(sys.path)

# 如果你经常使用一个函数, 你可以把它赋给一个本地的名称
"""
import 模块名
localMethod = 模块名.函数名
localMethod(实参) #调用
"""

# from...import语句
"""
Python的from语句让你从模块中导入一个指定的部分到当前命名空间中
from modname import name1[, name2][, ...nameN]


例如, 要导入模块fibo的fib函数, 使用如下语句
from fibo import fib, fib2

fib(500)

这个声明不会把整个fibo模块导入到当前的命名空间中,
所以fibo模块不会被放入到当前的字符表中。因此fibo
这个名称在当前模块中是没有定义的。
它只会将fibo里的fib函数引入进来。
"""

# from...import * 语句
"""
把一个模块的所有内容都导入到当前的命名空间也是可行的,
只需使用如下声明。
from modname import *
这提供了一个简单的方法来导入一个模块中的所有项目。
然而这种声明不该被过多使用。

这种方式其实就是把模块中所有(函数、变量)名称都导入到当前模块的字符表。
但是那些由单一下划线_开头的名字不在此列。
"""



# __name__属性
"""
一个模块被被另一个程序第一次引入时, 其主程序将运行。
如果我们想在模块被引入时, 模块中的某一程序块不执行,
我们可以用__name__属性来使该程序块仅在该模块自身运行时执行。

每个模块都有一个__name__属性, 当其值是"__main__"时, 表明
该模块自身在运行, 否则是被引入。
"""
#if __name__ == "__main__":
# print("程序自身在运行")
#else:
# print("我来自另一模块")




# dir()函数
"""
内置的函数dir()可以找到模块内定义的所有名称。
以一个字符串列表的形式返回
"""
def myMethod():
myname="hello"
list12 = [1, 2, 3]
# 要引入模块后再dir(模块)才有效果
import Test2
print(dir(Test2))
# 如果没有给定参数, 那么dir()会罗列出当前定义的所有名称
print(dir())


# 标准模块
"""
Python本身带着一些标准的模块库, 在Python库参考文档中将会介绍到。
有些模块直接被构建在解析器里, 这些虽然不是一些语言内置的功能,
但是他却能很高效的使用, 甚至是系统级调用也没问题。
这些组件会根据不同点操作系统进行不同形式的配置, 比如winreg这个模块
就只会提供给windows系统。
应该注意到这有一个特别的模块sys, 它内置在每一个Python解析器中。
变量sys.ps1和sys.ps2定义了主提示符和副提示符所对应的字符串

>>> import sys
>>> sys.ps1
'>>>'
>>> sys.ps2
'...'
>>> sys.ps1 = '$ '
$ print("Hello world!")
Hello world!
$
"""




# 29、包
"""
包是一种管理Python模块命名空间的形式, 采用"点模块名称"。
比如说你想设计一套统一处理声音文件和数据的模块 (或者称之为 "包")

sound/ 顶层包
__init__.py 初始化 sound 包

formats/ 文件格式转换子包
__init__.py
wavread.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...

effects/ 声音效果子包
__init__.py
echo.py
surround.py
reverse.py
...

filters/
__init__.py filters子包
equalizer.py
vocoder.py
karaoke.py

在导入一个包的时候, Python会根据sys.path中的目录来寻找这个包中包含的子目录。
目录只有包含一个叫做 __init__.py 的文件才会被认为是一个包, 主要是为了避免
一些烂名字(比如说string)不小心影响搜索路径中的有效模块。

最简单的情况, 放一个空的__init__.py就可以了。当然这个文件也可以包含一些初始化
代码或者为(将在后面介绍的) __all__ 变量赋值。
用户可以每次之导入一个包里面的特定模块, 比如:
import sound.effects.echo

这将会导入子模块 sound.effects.echo。但它必须使用全名去访问
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
还有一种导入子模块的方法是
from sound.effects import echo
这同样会导入子模块 echo, 并且它不需要那些冗长的前缀, 所以可以这样使用
echo.echofilter(input, output, delay=0.7, atten=4)
还有一种变化就是直接导入一个函数或者变量
from sound.effects.echo import echofilter
同样的, 这种方法会导入子模块echo, 并且可以直接使用它的echofilter()函数
echofilter(input, output, delay=0.7, atten=4)

注意当使用 from package import item 这种形式的时候, 对应的item既可以是包
里面的子模块(子包), 或者里面定义的其他名称, 比如函数, 类或者变量。

如果使用形如import item.subitem.subsubitem 这种导入形式, 除了最后一项,
都必须是包, 而最后一项则可以是模块或者是包, 但是不可以是类, 函数或者变量名字。
"""

# 从一个包中导入*
"""
如果我们使用from sound.effects import *会发生什么呢?
Python会进入文件系统, 找到这个包里面所有的子模块, 然后一个一个的把它们都导入进来。
但这个方法在Windows平台上工作的就不是非常好, 因为Windows是个不区分大小写的系统。
在windows系统上, 我们无法确定一个叫做ECHO.py的文件导入为模块是echo还是Echo,或ECHO。

为解决这个问题, 我们需要提供一个精确包的索引。
导入语句准许如下规则, 如果包定义文件 __init__.py存在一个叫做 __all__的列表变量,
那么在使用from package import *的时候就把这个列表中的所有名字作为包内容导入。
作为包的作者, 可别忘了在更新包之后保证__all__也更新了啊。
以下实例在sounds/effects/__init__.py中包含了如下代码

__all__=["echo", "surround", "reverse"]

这表示当你使用from sound.effects.import * 这种用法时, 你只会导入包里面这三个模块。
如果 __all__真的没有定义, 那么使用from sound.effects import * 这种语法的时候,
就不会导入包sound.effects里的任何子模块。他只是把包sound.effects和它里面定义的所有
内容导入进来(可能运行__init__.py里定义的初始化代码)。
这会把__init__.py里面定义的所有名字导入进来。并且他不会破坏掉我们在这句话之前导入的
所有明确指定的模块。看下这部分代码
import sound.effects.echo
import sound.effects.surround
from sound.effects import *
这个例子中, 在执行from...import前, 包sound.effects 中的echo和surround模块都被导入
到当前的命名空间中了。(当然如果定义了__all__就更没问题了)

记住, 使用from Package import specific_submodule这种方法永远不会有错。事实上, 这
也是推荐的方法。除非是你要导入的子模块有可能和其他包的子模块重名。

如果在结构中包是一个子包(比如这个例子中对于包sound来说), 而你又想导入兄弟包(同级别的包)
你就得使用导入绝对的路径来导入。比如模块sound.filters.vocoder要使用包sound.effects
中的模块echo, 你就要写成from sound.effects import echo。

from . import echo
from .. import formats
from .. filters import equalizer
无论是隐式还是显式的相对导入都是从当前模块开始的。主模块的名字永远是"__main__", 一个Python
应用程序的主模块, 应当总是使用绝对路径引用。
包还提供一个额外的属性__path__。这是一个目录列表, 里面每一个包含的目录都有为这个包服务的
__init__.py, 你得在其他__init__.py被执行前定义哦。可以修改这个变量, 用来影响包含在包里
面的模块和子包。这个功能不常用, 一般用来扩展包里面的模块。
"""




# 30、Python3输入和输出
"""
Python两种输出值的方式: 表达式语句和print()函数

第三种方式是使用文件对象的write()方法, 标准输出文件可以用sys.stdout引用。
如果你希望输出的形式更加多样, 可以使用str.format()函数来格式化输出值。
如果你希望将输出的值转为字符串, 可以使用repr()或者、str()函数来实现。
str(): 函数返回以恶用户易读的表达形式。
repr(): 产生一个解释器易读的表达形式
"""
value = "my name is zs"
value1 = str(True)
print(value1, type(value1)) # True <class 'str'>
value1 = repr(value)
print(value1, type(value1)) # 'my name is zs' <class 'str'>

# repr()函数可以转义字符串中的特殊字符
value1 = "hello, runoob\n"
print(value1) # 输出会带换行效果
print(repr(value1)) # 'hello, runoob\n'

value1 = (32.5, 4000, ("Google", "Runoob"))
print(str(value1))
print(repr(value1))



# 两种方式输出平方与立方表
for x in range(1, 11):
print(repr(x).rjust(2), repr(x*x).rjust(3), end=" ")
print(repr(x*x*x).rjust(4))
for x in range(1, 11):
print("{0:2d} {1:3d} {2:4d}".format(x, x*x, x*x*x))
"""
第一个例子中, 每列间的空格由print()添加。
这个例子展示了字符串对象的rjust()方法, 它可以将字符串靠右,
并在左边填充空格。
还有类似的方法, 如ljust()和center()。这些方法并不会写任何东西,
它们仅仅返回新的字符串。
"""

# 另一个方法zfill(), 它会在数字的左边填充0
print("wee".zfill(5)) # 00wee
print("-3.14".zfill(7)) # -003.14

# str.format()的基本使用如下
#括号及其里面的字符(称作格式化字段)将会被format()中的参数替换
print("{}网址: {}!". # 菜鸟教程网址: www.runoob.com!
format("菜鸟教程", "www.runoob.com"))

#在括号中的数字用于指向传入对象在format()中的位置
print("{0} 和 {1}".
format("Google", "Runoob")) # Google 和 Runoob
print("{1} 和 {0}".
format("Google", "Runoob")) # Runoob 和 Google

#如果在format()中使用了关键字参数, 那么它们的值会指向使用该名字的参数。
print("{name}网址: {site}".
format(name="菜鸟教程", site="www.runoob.com"))

#位置及关键字参数可以任意的结合
print("站点列表{0}, {1}, 和 {other}".
format("Google", "Runoob", other="Taobao"))
#站点列表Google, Runoob, 和 Taobao

# !a(使用ascii()), !s(使用str()) 和 !r(使用repr())
# 可以用于在格式化某个值之前对其进行转化
print("常量PI的值近似为: {!r}".format(math.pi))

#可选项:和格式标识符可以跟着字段名。这就允许对值进行更好的格式化。
print("常量PI的值近似为: {0:.3f}".format(math.pi)) # 3.142

#在 : 后传入一个整数, 可以保证该域至少有这么多的宽度。用于美化表格时很有用。
table = {"Google": 1, "Runoob": 2, "Taobao": 3}
for name, number in table.items():
print("{0:10} ==> {1:10d}".format(name, number))

#如果你有一个很长的格式化字符串, 而你不想将它们分开, 那么在格式化
#时通过变量名而非位置会是很好的事情。
#最简单的就是传入一个字典, 然后使用方括号[]来访问键值
table = {"Google": 1, "Runoob": 2, "Taobao": 3}
print("Runoob: {0[Runoob]:d}; Google: {0[Google]:d}; "
"Taobao: {0[Taobao]:d}".format(table))
# Runoob: 2; Google: 1; Taobao: 3

# 也可以通过在table变量前使用**来实现相同的功能
print('Runoob: {Runoob:d}; Google: {Google:d}; Taobao: {Taobao:d}'.
format(**table))


# 旧式字符串格式化
# %操作符也可以实现字符串格式化。它将左边的参数作为类似sprintf()
# 的格式化字符串, 而将右边的代入, 然后返回格式化后的字符串。
# 10为整体长度,5为小数点后位数
print("%10.5f" % math.pi) # 3.14159




# 读取键盘输入
"""
Python提供了input()内置函数从标准输入读取一行文本,
默认的标准输入是键盘。
"""
#strr = input("请输入: ")
print("你输入的内容是: ", strr)




# 31、读和写文件
"""
open()将会返回一个file对象, 基本语法格式如下

open(filename, mode)
filename: 包含了你要访问的文件名称的字符串值
mode: 决定了打开文件的模式。 只读、写入、追加等等。
所有可取值见如下表。这个参数是非强制的, 默认文件访问模式为只读(r)

# 完整语法格式
open(file, mode='r', buffering=-1, encoding=None,
errors=None, newline=None, closefd=True, opener=None)

参数说明:
file: 必需,文件路径(相对或者绝对路径)。
mode: 可选,文件打开模式
buffering: 设置缓冲
encoding: 一般使用utf8
errors: 报错级别
newline: 区分换行符
closefd: 传入的file参数类型
opener: 设置自定义开启器,开启器的返回值必须是一个打开的文件描述符。

mode 参数有:
t
文本模式 (默认)。

x
写模式,新建一个文件,如果该文件已存在则会报错。

b
二进制模式。

+
打开一个文件进行更新(可读可写)。

U
通用换行模式(Python 3 不支持)。

r
以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。

rb
以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。
这是默认模式。一般用于非文本文件如图片等。

r+
打开一个文件用于读写。文件指针将会放在文件的开头。

rb+
以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
一般用于非文本文件如图片等。

w
打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,
即原有内容会被删除。如果该文件不存在,创建新文件。

wb
以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,
并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
一般用于非文本文件如图片等。

w+
打开一个文件用于读写。如果该文件已存在则打开文件, 并从开头开始编辑,
即原有内容会被删除。如果该文件不存在, 创建新文件。

wb+
以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,
并从开头开始编辑, 即原有内容会被删除。如果该文件不存在, 创建新文件。
一般用于非文本文件如图片等。

a
打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。
也就是说, 新的内容将会被写入到已有内容之后。如果该文件不存在, 创建新文件进行写入。

ab
以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。
也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。

a+
打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。
文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。

ab+
以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。
如果该文件不存在,创建新文件用于读写。

"""
# 打开文件, 开始写入, 关闭文件
f = open("./tmp.txt", "w", encoding="utf-8")
#print(f.write("123456789"))
#f.close()

"""
# f.read()
为了读取一个文件的内容, 调用f.read(size), 这将读取一定数目的数据, 然后作为字符串
或者字节对象返回。
size是一个可选的数字类型的参数。当size被忽略了或者为负, 那么该文件的所有内容都将被
读取并且返回。

# f.readline()
f.readline() 会从文件中读取单独的一行。换行符为 '\n'。f.readline()
如果返回一个空字符串, 说明已经已经读取到最后一行。

# f.readlines()
将返回该文件中包含的所有行。
如果设置可选参数 sizehint, 则读取指定长度的字节, 并且将这些字节按行分割。
# ['Python 是一个非常好的语言。\n', '是的,的确非常好!!\n']

# 另一种方式是迭代一个文件对象然后读取每行
# 打开一个文件
f = open("/tmp/foo.txt", "r")

for line in f:
print(line, end='')

# 关闭打开的文件
f.close()


# f.write(string)
将 string 写入到文件中, 然后返回写入的字符数。


# 如果要写入一些不是字符串的东西, 那么将需要先进行转换
# 打开一个文件
f = open("/tmp/foo1.txt", "w")

value = ('www.runoob.com', 14)
s = str(value)
f.write(s)
关闭打开的文件
f.close()

# f.tell()
返回文件对象当前所处的位置,
它是从文件开头开始算起的字节数。

# f.seek()
如果要改变文件指针当前的位置,
可以使用 f.seek(offset, from_what) 函数。
from_what 的值, 如果是 0 表示开头, 如果是 1 表示当前位置, 2 表示文件的结尾,例如:
seek(x,0) : 从起始位置即文件首行首字符开始移动 x 个字符
seek(x,1) : 表示从当前位置往后移动x个字符
seek(-x,2):表示从文件的结尾往前移动x个字符

文件对象还有其他方法, 如 isatty() 和 trucate(), 但这些通常比较少用。
"""
"""
file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数:

file.close()
关闭文件。关闭后文件不能再进行读写操作。

file.flush()
刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件,
而不是被动的等待输出缓冲区写入。

file.fileno()
返回一个整型的文件描述符(file descriptor FD 整型),
可以用在如os模块的read方法等一些底层操作上。

file.isatty()
如果文件连接到一个终端设备返回 True,否则返回 False。

file.next()
Python 3 中的 File 对象不支持 next() 方法。
返回文件下一行。

file.read([size])
从文件读取指定的字节数,如果未给定或为负则读取所有。

file.readline([size])
读取整行,包括 "\n" 字符。

file.readlines([sizeint])
读取所有行并返回列表,若给定sizeint>0,返回总和大约为sizeint字节的行,
实际读取值可能比 sizeint 较大, 因为需要填充缓冲区。

file.seek(offset[, whence])
移动文件读取指针到指定位置

file.tell()
返回文件当前位置。

file.truncate([size])
从文件的首行首字符开始截断,截断文件为 size 个字符,无 size 表示从当前位置截断;
截断之后后面的所有字符被删除,其中 windows 系统下的换行代表2个字符大小。

file.write(str)
将字符串写入文件,返回的是写入的字符长度。

file.writelines(sequence)
向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符。

"""


# 当处理一个文件对象时, 使用 with 关键字是非常好的方式。
# 在结束后, 它会帮你正确的关闭文件。
# 而且写起来也比 try - finally 语句块要简短:
"""
with open('/tmp/foo.txt', 'r') as ff:
read_data = ff.read()
"""





# 32、pickle模块
"""
python的pickle模块实现了基本的数据序列和反序列化。
通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储。
通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象。

基本接口:
pickle.dump(obj, file, [,protocol])

有了 pickle 这个对象, 就能对 file 以读取的形式打开:
x = pickle.load(file)
"""
import pickle

#使用pickle模块将数据对象保存到文件
data = {"a": [1, 2, 3, 4+6j],
"b": ("string", u"Unicode string"),
"c": None
}
sefref_list = [1, 2, 3]
sefref_list.append(sefref_list)
print(sefref_list)

output = open("./data.pkl", "wb")
pickle.dump(data, output)
pickle.dump(sefref_list, output, -1)
output.close()

#!/usr/bin/python3
import pprint, pickle

#使用pickle模块从文件中重构python对象
pkl_file = open('./data.pkl', 'rb')

data1 = pickle.load(pkl_file)
pprint.pprint(data1)

data2 = pickle.load(pkl_file)
pprint.pprint(data2)

pkl_file.close()




# 33、Python3 OS文件/目录方法
"""
os.access(path, mode)
检验权限模式

os.chdir(path)
改变当前工作目录

os.chflags(path, flags)
设置路径的标记为数字标记。

os.chmod(path, mode)
更改权限

os.chown(path, uid, gid)
更改文件所有者

os.chroot(path)
改变当前进程的根目录

os.close(fd)
关闭文件描述符 fd

os.closerange(fd_low, fd_high)
关闭所有文件描述符,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略

os.dup(fd)
复制文件描述符 fd

os.dup2(fd, fd2)
将一个文件描述符 fd 复制到另一个 fd2

os.fchdir(fd)
通过文件描述符改变当前工作目录

os.fchmod(fd, mode)
改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限。

os.fchown(fd, uid, gid)
修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,
该文件由文件描述符fd指定。

os.fdatasync(fd)
强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息。

os.fdopen(fd[, mode[, bufsize]])
通过文件描述符 fd 创建一个文件对象,并返回这个文件对象

os.fpathconf(fd, name)
返回一个打开的文件的系统配置信息。name为检索的系统配置的值,
它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1, Unix 95, Unix 98, 和其它)。

os.fstat(fd)
返回文件描述符fd的状态,像stat()。

os.fstatvfs(fd)
返回包含文件描述符fd的文件的文件系统的信息,Python 3.3 相等于 statvfs()。

os.fsync(fd)
强制将文件描述符为fd的文件写入硬盘。

os.ftruncate(fd, length)
裁剪文件描述符fd对应的文件, 所以它最大不能超过文件大小。

os.getcwd()
返回当前工作目录

os.getcwdb()
返回一个当前工作目录的Unicode对象

os.isatty(fd)
如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False。

os.lchflags(path, flags)
设置路径的标记为数字标记,类似 chflags(),但是没有软链接

os.lchmod(path, mode)
修改连接文件权限

os.lchown(path, uid, gid)
更改文件所有者,类似 chown,但是不追踪链接。

os.link(src, dst)
创建硬链接,名为参数 dst,指向参数 src

os.listdir(path)
返回path指定的文件夹包含的文件或文件夹的名字的列表。

os.lseek(fd, pos, how)
设置文件描述符 fd当前位置为pos, how方式修改: SEEK_SET 或者 0 设置从文件开始的计算的pos;
SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始. 在unix,Windows中有效

os.lstat(path)
像stat(),但是没有软链接

os.major(device)
从原始的设备号中提取设备major号码 (使用stat中的st_dev或者st_rdev field)。

os.makedev(major, minor)
以major和minor设备号组成一个原始设备号

os.makedirs(path[, mode])
递归文件夹创建函数。像mkdir(),
但创建的所有intermediate-level文件夹需要包含子文件夹。

os.minor(device)
从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field )。

os.mkdir(path[, mode])
以数字mode的mode创建一个名为path的文件夹.默认的 mode 是 0777 (八进制)。

os.mkfifo(path[, mode])
创建命名管道,mode 为数字,默认为 0666 (八进制)

os.mknod(filename[, mode=0600, device])
创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe)。

os.open(file, flags[, mode])
打开一个文件,并且设置需要的打开选项,mode参数是可选的

os.openpty()
打开一个新的伪终端对。返回 pty 和 tty的文件描述符。

os.pathconf(path, name)
返回相关文件的系统配置信息。

os.pipe()
创建一个管道. 返回一对文件描述符(r, w) 分别为读和写

os.popen(command[, mode[, bufsize]])
从一个 command 打开一个管道

os.read(fd, n)
从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,
文件描述符 fd对应文件已达到结尾, 返回一个空字符串。

os.readlink(path)
返回软链接所指向的文件

os.remove(path)
删除路径为path的文件。如果path 是一个文件夹,将抛出OSError;
查看下面的rmdir()删除一个 directory。

os.removedirs(path)
递归删除目录。

os.rename(src, dst)
重命名文件或目录,从 src 到 dst

os.renames(old, new)
递归地对目录进行更名,也可以对文件进行更名。

os.rmdir(path)
删除path指定的空目录,如果目录非空,则抛出一个OSError异常。

os.stat(path)
获取path指定的路径的信息,功能等同于C API中的stat()系统调用。

os.stat_float_times([newvalue])
决定stat_result是否以float对象显示时间戳

os.statvfs(path)
获取指定路径的文件系统统计信息

os.symlink(src, dst)
创建一个软链接

os.tcgetpgrp(fd)
返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组

os.tcsetpgrp(fd, pg)
设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg。

os.tempnam([dir[, prefix]])
Python3 中已删除。返回唯一的路径名用于创建临时文件

os.tmpfile()
Python3 中已删除。返回一个打开的模式为(w+b)的文件对象 .
这文件对象没有文件夹入口,没有文件描述符,将会自动删除。

os.tmpnam()
Python3 中已删除。为创建一个临时文件返回一个唯一的路径

os.ttyname(fd)
返回一个字符串,它表示与文件描述符fd 关联的终端设备。
如果fd 没有与终端设备关联,则引发一个异常。

os.unlink(path)
删除文件路径

os.utime(path, times)
返回指定的path文件的访问和修改的时间。

os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
输出在文件夹中的文件名通过在树中游走,向上或者向下。

os.write(fd, str)
写入字符串到文件描述符 fd中. 返回实际写入的字符串长度

os.path 模块
获取文件的属性信息。

os.pardir()
获取当前目录的父目录,以字符串形式显示目录名。

os.replace()
重命名文件或目录。
"""




# 34、Python3错误和异常
"""
Python 有两种错误很容易辨认:语法错误和异常。

Python assert(断言)用于判断一个表达式,
在表达式条件为 false 的时候触发异常。

异常处理: try/except
try:
执行代码
except:
发生异常时执行的代码


一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。最多只有一个分支会被执行。
处理程序将只针对对应的 try 子句中的异常进行处理,而不是其他的 try 的处理程序中的异常。
一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组,例如:

except (RuntimeError, TypeError, NameError):
pass

"""

# 最后一个except子句可以忽略异常的名称,它将被当作通配符使用。
# 你可以使用这种方法打印一个错误信息,然后再次把异常抛出。
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise


# try/except...else语句
"""
try/except 语句还有一个可选的 else 子句,如果使用这个子句,
那么必须放在所有的 except 子句之后。
else 子句将在 try 子句没有发生任何异常的时候执行。

try:
执行代码
execpt:
发生异常时执行代码
else:
没有异常时执行代码
"""



# try-finally语句
"""
try-finally 语句无论是否发生异常都将执行最后的代码。
try:
执行代码
execpt:
发生异常时执行代码
else:
没有异常时执行的代码
finally:
不管有没有异常都会执行的代码
"""
try:
#runoob()
i = 10
except AssertionError as error:
print(error)
else:
try:
with open('file.log') as file:
read_data = file.read()
except FileNotFoundError as fnf_error:
print(fnf_error)
finally:
print('这句话,无论异常是否发生都会执行。')




# 抛出异常
"""
Python 使用 raise 语句抛出一个指定的异常。
raise [Exception [, args [, traceback]]]

x = 10
if x > 5:
raise Exception('x 不能大于 5。x 的值为: {}'.format(x))

raise 唯一的一个参数指定了要被抛出的异常。
它必须是一个异常的实例或者是异常的类(也就是 Exception 的子类)。
如果你只想知道这是否抛出了一个异常,并不想去处理它,
那么一个简单的 raise 语句就可以再次把它抛出。

try:
raise NameError('HiThere')
except NameError:
print('An exception flew by!')
raise

"""



# 用户自定义异常
"""
你可以通过创建一个新的异常类来拥有自己的异常。
异常类继承自 Exception 类,可以直接继承,或者间接继承。
"""
# 在这个例子中, 类Exception默认的__init__()被覆盖
class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)

try:
e = MyError(5)
raise e
except MyError as e:
print('My exception occurred, value:', e.value)

# 当创建一个模块有可能抛出多种不同的异常时, 一种通常的做法是为这个包
# 建立一个基础异常类, 然后基于这个基础类为不同的错误情况创建不同的子类
# 大多数异常的名字都以"Error"结尾, 就跟标准的异常命名一样。
class Error(Exception):
"""Base class for exceptions in this module."""
pass

class InputError(Error):
"""Exception raised for errors in the input.

Attributes:
expression -- input expression in which the error occurred
message -- explanation of the error
"""

def __init__(self, expression, message):
self.expression = expression
self.message = message

class TransitionError(Error):
"""Raised when an operation attempts a state transition that's not
allowed.

Attributes:
previous -- state at beginning of transition
next -- attempted new state
message -- explanation of why the specific transition is not allowed
"""

def __init__(self, previous, next, message):
self.previous = previous
self.next = next
self.message = message




# 定义清理行为
# try语句还有另外一个可选的子句,
# 它定义了无论在任何情况下都会执行的清理行为。
# 下面例子不管try子句里面有没有发生异常, finally子句都执行
try:
#raise KeyboardInterrupt
pass
finally:
print('Goodbye, world!')

# 如果一个异常在try子句里(或者在except和else子句里)被抛出,
# 而又没有任何的except把它截住, 那么这个异常会在finally子句
# 执行后被抛出。
def divide(x, y):
try:
result = x / y
except ZeroDivisionError:
print("division by zero!")
else:
print("result is", result)
finally:
print("executing finally clause")

divide(2, 1)
#divide("2", '1')




# 预定义的清理行为
# 一些对象定义了标准的清理行为, 无论系统是否成功使用了它,
# 一旦不需要它了, 那么这个标准的清理行为就会执行。
for line in open("./myfile.txt"):
print(line, end="")
# 以上这段代码的问题是, 当执行完毕后, 文件会保持打开状态, 并没有被关闭。
# 关键词with语句就可以保证诸如文件之类的对象在使用完之后一定会正确的执行他的清理方法。
with open("./myfile.txt") as f:
for line in f:
print(line, end="")
# 以上这段代码执行完毕后, 就算在处理过程中出问题了, 文件f总是会关闭。




# 35、Python3面向对象
"""
类(Class): 用来描述具有相同的属性和方法的对象的集合。
它定义了该集合中每个对象所共有的属性和方法, 对象是类的实例。

方法: 类中定义的函数

类变量: 类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。
类变量通常不作为实例变量使用。

数据成员: 类变量或者实例变量用于处理类及其实例对象的相关的数据。

方法重写: 如果从父类继承的方法不能满足子类的需求, 可以对其进行改写, 这个过程
叫方法的覆盖(override), 也称为方法的重写。

局部变量: 在类的声明中, 属性是用变量来表示的, 这种变量就称为实例变量,
实例变量就是一个用self修饰的变量。

继承: 即一个派生类(derived class)继承基类(base class)的字段和方法。
继承也允许把一个派生类的对象作为一个基类对象对待。is-a的关系

实例化: 创建一个类的实例, 类的具体对象。

对象: 通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

"""

"""
在Python中,可以使用两种方式来定义类的属性,一种是在类中直接定义,另一种是在__init__函数中定义。这两种方式的区别在于属性的作用域和生命周期。

1、类中直接定义属性

通过在类中直接定义属性,可以创建所有实例都具有的公共属性。这些属性的值在类被创建时就已经确定,且在整个类的生命周期内都存在。

以下是一个例子:


class MyClass:
name = "MyClass" # 在类中定义属性

obj1 = MyClass()
obj2 = MyClass()

print(obj1.name) # 输出:"MyClass"
print(obj2.name) # 输出:"MyClass"

MyClass.name = "NewClass"
print(obj1.name) # 输出:"NewClass"
print(obj2.name) # 输出:"NewClass"

从上面的代码可以看出,当在类中直接定义属性时,所有实例都可以访问这些属性,且属性的值在类级别上进行管理,对所有实例都生效。

2、在__init__函数中定义属性

在__init__函数中定义属性,创建的属性是实例属性,每个实例都拥有自己的一份属性副本。这些属性的值是在每个实例初始化时被创建的,并且只在实例的生命周期内存在。

以下是一个例子:


class MyClass:
def __init__(self, name):
self.name = name # 在__init__函数中定义属性

obj1 = MyClass("Object1")
obj2 = MyClass("Object2")

print(obj1.name) # 输出:"Object1"
print(obj2.name) # 输出:"Object2"

obj1.name = "NewObject1"
print(obj1.name) # 输出:"NewObject1"
print(obj2.name) # 输出:"Object2"

从上面的代码可以看出,当在__init__函数中定义属性时,每个实例都有自己的一份属性副本,这些属性的值可以针对每个实例单独设置和更改。

因此,当我们需要在创建实例时给属性进行赋值,并希望这些属性只与该实例相关时,应该在__init__函数中定义属性;而当我们需要创建所有实例都具有的公共属性时,应该在类中直接定义属性。
"""
# Python的类继承机制允许多个基类, 派生类可以覆盖基类中的任何方法,
# 方法中可以调用基类中的同名方法。对象可以包含任意数量和类型的数据。
# 类实例化后, 可以使用其属性, 实际上, 创建一个类后, 可以通过类名访问其属性。
class MyClass:
"""一个简单的类实例"""
i = 12345
def f(self):
return 'hello world'

# 实例化类
x = MyClass()

# 访问类的属性和方法
print("MyClass 类的属性 i 为:", MyClass.i)
print("MyClass 类的方法 f 输出为:", x.f())


# 类有一个名为__init__()的特殊方法(构造方法),
# 该方法在类实例化时自动调用, 比如上述 x = MyClass()时
def __init__(self):
self.data = []

# 当然, __init__方法可以有参数, 参数通过__init__()
# 传递到类的实例化操作上。
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i) # 输出结果:3.0 -4.5

# self代表类的实例,而非类
"""
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,
按照惯例它的名字是self。
self不是python关键字, 我们把他换成runoob也是可以正常执行的
"""
class Test:
def prt(self):
print(self)
print(self.__class__)

t = Test()
t.prt()
"""
<__main__.Test instance at 0x100771878>
__main__.Test
"""

# 类方法
"""
在类的内部, 使用def关键字来定义一个方法, 与一般函数定义不同,
类方法必须包含参数self, 且为第一个参数, self代表的是类的实例。
"""
#类定义
class people:
#定义构造方法
def __init__(self,n,a,w):
#定义基本属性
self.name = n
self.age = a
#定义私有属性,私有属性在类外部无法直接进行访问
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))

# 实例化类
p = people('runoob',10,30)
p.speak()

# 继承
"""
子类会继承父类的属性和方法。基类必须与派生类定义在一个作用域内。
除了类, 还可以用表达式, 基类定义在另一个模块中时这一点非常有用。
class DerivedClassName(modname.BaseClassName):
"""
#类定义
class people:
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))

#单继承示例
class student(people):
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))

s = student('ken',10,60,3)
s.speak()


# 多继承
"""
Python同样有限的支持多继承形式。多几次的类定义形如下
class DerivedClassName(Base1, Base2, Base3):

需要注意圆括号中父类的顺序,若是父类中有相同的方法名,
而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,
从左到右查找父类中是否包含方法。
"""
#类定义
class people:
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))

#单继承示例
class student(people):
def __init__(self, n, a, w, g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))

#另一个类,多重继承之前的准备
class speaker:
def __init__(self,n,t):
self.name = n
self.topic = t
def speak(self):
print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))

#多重继承
class sample(speaker,student):
def __init__(self,n,a,w,g,t):
student.__init__(self,n,a,w,g)
speaker.__init__(self,n,t)

test = sample("Tim",25,80,4,"Python")
test.speak() #方法名同,默认调用的是在括号中参数位置排前父类的方法

# 方法重写
class Parent: # 定义父类
def myMethod(self):
print ('调用父类方法')

class Child(Parent): # 定义子类
def myMethod(self):
print ('调用子类方法')

c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法


# Python子类继承父类构造函数说明
"""
如果在子类中需要父类的构造方法就需要显式地调用父类的构造方法,
或者不重写父类的构造方法。

子类不重写 __init__,实例化子类时,
会自动调用父类定义的 __init__。
"""
class Father(object):
def __init__(self, name):
self.name=name
print ( "name: %s" %( self.name) )
def getName(self):
return 'Father ' + self.name

class Son(Father):
def getName(self):
return 'Son '+self.name

if __name__=='__main__':
son=Son('runoob')
print ( son.getName() )

# 如果重写了__init__ 时,
# 实例化子类,就不会调用父类已经定义的 __init__
class Father(object):
def __init__(self, name):
self.name=name
print ( "name: %s" %( self.name) )
def getName(self):
return 'Father ' + self.name

class Son(Father):
def __init__(self, name):
print ( "hi" )
self.name = name
def getName(self):
return 'Son '+self.name

if __name__=='__main__':
son=Son('runoob')
print(son.getName())

# 如果重写了__init__ 时,
# 要继承父类的构造方法,可以使用 super 关键字
"""
super() 函数是用于调用父类(超类)的一个方法。

super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,
但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。

MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。

super(子类,self).__init__(参数1,参数2,....)

还有一种经典写法:
父类名称.__init__(self,参数1,参数2,...)

Python3.x 和 Python2.x 的一个区别是:
Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx :


"""
class Father(object):
def __init__(self, name):
self.name=name
print ( "name: %s" %( self.name))
def getName(self):
return 'Father ' + self.name

class Son(Father):
def __init__(self, name):
super(Son, self).__init__(name)
print ("hi")
self.name = name
def getName(self):
return 'Son '+self.name

if __name__=='__main__':
son=Son('runoob')
print ( son.getName() )


# 类属性与方法
"""
类的私有属性:
__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。
在类内部的方法中使用时 self.__private_attrs。

类的方法:
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self,
且为第一个参数,self 代表的是类的实例。
self 的名字并不是规定死的,也可以使用 this,但是最好还是按照约定使用 self。

类的私有方法:
__private_method:两个下划线开头,声明该方法为私有方法,
只能在类的内部调用 ,不能在类的外部调用。self.__private_methods。
"""
class JustCounter:
def __init__(self):
self.__secretCount = 0 # 私有变量
self.publicCount = 0 # 公开变量

def count(self):
self.__secretCount += 1
self.publicCount += 1
print (self.__secretCount)

counter = JustCounter()
counter.count()
counter.count()
print (counter.publicCount)
print (counter.__secretCount) # 报错,实例不能访问私有变量


class Site:
def __init__(self, name, url):
self.name = name # public
self.__url = url # private

def who(self):
print('name : ', self.name)
print('url : ', self.__url)

def __foo(self): # 私有方法
print('这是私有方法')

def foo(self): # 公共方法
print('这是公共方法')
self.__foo()

x = Site('菜鸟教程', 'www.runoob.com')
x.who() # 正常输出
x.foo() # 正常输出
x.__foo() # 报错


# 类的专有方法
"""
__init__ : 构造函数,在生成对象时调用
__del__ : 析构函数,释放对象时使用
__repr__ : 打印,转换
__setitem__ : 按照索引赋值
__getitem__: 按照索引获取值
__len__: 获得长度
__cmp__: 比较运算
__call__: 函数调用
__add__: 加运算
__sub__: 减运算
__mul__: 乘运算
__truediv__: 除运算
__mod__: 求余运算
__pow__: 乘方
"""

# 运算符重载
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b

def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)

def __add__(self,other):
return Vector(self.a + other.a, self.b + other.b)

v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)





# 36、Python3命名空间和作用域
"""
命名空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的。

命名空间提供了在项目中避免名字冲突的一种方法。各个命名空间是独立的,没有任何关系的,
所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响。

我们举一个计算机系统中的例子,一个文件夹(目录)中可以包含多个文件夹,
每个文件夹中不能有相同的文件名,但不同文件夹中的文件可以重名。

一般有三种命名空间:
内置名称(built-in names), Python 语言内置的名称,
比如函数名 abs、char 和异常名称 BaseException、Exception 等等。

全局名称(global names),模块中定义的名称,记录了模块的变量,
包括函数、类、其它导入的模块、模块级的变量和常量。

局部名称(local names),函数中定义的名称,记录了函数的变量,
包括函数的参数和局部定义的变量。(类中定义的也是)

命名空间查找顺序:
假设我们要使用变量 runoob,则 Python 的查找顺序为:
局部的命名空间去 -> 全局命名空间 -> 内置命名空间。

如果找不到变量 runoob,它将放弃查找并引发一个 NameError 异常

命名空间的生命周期:
命名空间的生命周期取决于对象的作用域,如果对象执行完成,则该命名空间的生命周期就结束。
因此,我们无法从外部命名空间访问内部命名空间的对象。
"""
# var1 是全局名称
var1 = 5
def some_func():
# var2 是局部名称
var2 = 6
def some_inner_func():
# var3 是内嵌的局部名称
var3 = 7


# 作用域
"""
作用域就是一个 Python 程序可以直接访问命名空间的正文区域。

在一个 python 程序中,直接访问一个变量,会从内到外依次访问所有的作用域直到找到,
否则会报未定义的错误。

Python 中,程序的变量并不是在哪个位置都可以访问的,
访问权限决定于这个变量是在哪里赋值的。

变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。
Python 的作用域一共有4种,分别是:

有四种作用域:
L(Local):最内层,包含局部变量,比如一个函数/方法内部。
E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。
比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,
那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
G(Global):当前脚本的最外层,比如当前模块的全局变量。
B(Built-in): 包含了内建的变量/关键字等,最后被搜索。
规则顺序: L –> E –> G –> B。
在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。
"""
g_count = 0 # 全局作用域
def outer():
o_count = 1 # 闭包函数外的函数中
def inner():
i_count = 2 # 局部作用域

# 内置作用域
"""
内置作用域是通过一个名为 builtin 的标准模块来实现的,但是这个变量名自身并没有放入内置作用域内,
所以必须导入这个文件才能够使用它。在Python3.0中,可以使用以下的代码来查看到底预定义了哪些变量:
>>> import builtins
>>> dir(builtins)
"""

# 不是一般理解的作用域
"""
Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,
其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,
也就是说这些语句内定义的变量,外部也可以访问,如下代码:

>>> if True:
... msg = 'I am from Runoob'
...
>>> msg
'I am from Runoob'
>>>

实例中 msg 变量定义在 if 语句块中,但外部还是可以访问的。
如果将 msg 定义在函数中,则它就是局部变量,外部不能访问:
"""


# 全局变量和局部变量
"""
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。

局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。
调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。如下实例:
"""
total = 0 # 这是一个全局变量
# 可写函数说明
def sum( arg1, arg2 ):
#返回2个参数的和."
total = arg1 + arg2 # total在这里是局部变量.
print ("函数内是局部变量 : ", total)
return total

#调用sum函数
sum( 10, 20 )
print ("函数外是全局变量 : ", total)


# global和nonlocal关键字
"""
当内部作用域想修改外部作用域的变量时,就要用到 global 和 nonlocal 关键字了。
"""
num = 1
def fun1():
global num # 需要使用 global 关键字声明
print(num)
num = 123
print(num)
fun1()
print(num)
"""
如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量
则需要 nonlocal 关键字了
"""
def outer():
num = 10
def inner():
nonlocal num # nonlocal关键字声明
num = 100
print(num)
inner()
print(num)
outer()

"""
另外有一种特殊情况
"""
a = 10
def test():
a = a + 1
print(a)
test() # 会报错
# 错误信息为局部作用域引用错误,
# 因为 test 函数中的 a 使用的是局部,未定义,无法修改。

# 修改一下即可
a = 10
def test():
global a
a = a + 1
print(a)
test()

# 也可通过函数参数传递
a = 10
def test(a):
a = a + 1
print(a)
test(a)