소스 검색

add:增加脚本文件和学习的base;

gongyuan 9 달 전
부모
커밋
ac1293a766
100개의 변경된 파일2586개의 추가작업 그리고 0개의 파일을 삭제
  1. 30 0
      base/0basic/do_for.py
  2. 27 0
      base/0basic/do_if.py
  3. 5 0
      base/0basic/do_input.py
  4. 18 0
      base/0basic/do_print.py
  5. 18 0
      base/0basic/do_while.py
  6. 4 0
      base/0basic/hello.py
  7. 12 0
      base/0basic/the_dict.py
  8. 32 0
      base/0basic/the_list.py
  9. 8 0
      base/0basic/the_set.py
  10. 13 0
      base/0basic/the_string.py
  11. 13 0
      base/0basic/the_tuple.py
  12. 8 0
      base/10commonlib/check_bmp.py
  13. 14 0
      base/10commonlib/do_base64.py
  14. 20 0
      base/10commonlib/use_chainmap.py
  15. 28 0
      base/10commonlib/use_collections.py
  16. 40 0
      base/10commonlib/use_datetime.py
  17. 13 0
      base/10commonlib/use_hashlib.py
  18. 36 0
      base/10commonlib/use_htmlparser.py
  19. 18 0
      base/10commonlib/use_itertools.py
  20. 28 0
      base/10commonlib/use_sax.py
  21. 58 0
      base/10commonlib/use_urllib.py
  22. 26 0
      base/11packages/pil/README
  23. BIN
      base/11packages/pil/test.jpg
  24. 10 0
      base/11packages/pil/use_pil_blur.py
  25. 44 0
      base/11packages/pil/use_pil_draw.py
  26. 15 0
      base/11packages/pil/use_pil_resize.py
  27. 27 0
      base/12gui/hello_gui.py
  28. 26 0
      base/12gui/turtle/rect.py
  29. 16 0
      base/12gui/turtle/stars.py
  30. 59 0
      base/12gui/turtle/tree.py
  31. 35 0
      base/13socket/do_tcp.py
  32. 14 0
      base/13socket/udp_client.py
  33. 18 0
      base/13socket/udp_server.py
  34. 86 0
      base/14mail/fetch_mail.py
  35. 28 0
      base/14mail/send_mail.py
  36. 33 0
      base/15db/do_mysql.py
  37. 44 0
      base/15db/do_sqlalchemy.py
  38. 35 0
      base/15db/do_sqlite.py
  39. 29 0
      base/16web/do_flask.py
  40. 11 0
      base/16web/do_wsgi.py
  41. 7 0
      base/16web/hello.py
  42. 25 0
      base/16web/mvc/app.py
  43. 16 0
      base/16web/mvc/templates/form.html
  44. 8 0
      base/16web/mvc/templates/home.html
  45. 8 0
      base/16web/mvc/templates/signin-ok.html
  46. 33 0
      base/17async/aio_web.py
  47. 16 0
      base/17async/async_hello.py
  48. 15 0
      base/17async/async_hello2.py
  49. 25 0
      base/17async/async_wget.py
  50. 15 0
      base/17async/async_wget2.py
  51. 24 0
      base/17async/coroutine.py
  52. 13 0
      base/18micropython/hellorobot/.vscode/extensions.json
  53. 14 0
      base/18micropython/hellorobot/.vscode/launch.json
  54. 6 0
      base/18micropython/hellorobot/.vscode/settings.json
  55. 14 0
      base/18micropython/hellorobot/main.py
  56. 13 0
      base/18micropython/rccar/.vscode/extensions.json
  57. 14 0
      base/18micropython/rccar/.vscode/launch.json
  58. 6 0
      base/18micropython/rccar/.vscode/settings.json
  59. 47 0
      base/18micropython/rccar/devices.py
  60. 100 0
      base/18micropython/rccar/main.py
  61. 13 0
      base/18micropython/smallcar/.vscode/extensions.json
  62. 14 0
      base/18micropython/smallcar/.vscode/launch.json
  63. 7 0
      base/18micropython/smallcar/.vscode/settings.json
  64. 51 0
      base/18micropython/smallcar/main.py
  65. 13 0
      base/18micropython/tank/.vscode/extensions.json
  66. 14 0
      base/18micropython/tank/.vscode/launch.json
  67. 6 0
      base/18micropython/tank/.vscode/settings.json
  68. BIN
      base/18micropython/tank/cannon.wav
  69. 47 0
      base/18micropython/tank/devices.py
  70. 61 0
      base/18micropython/tank/joystick.py
  71. 103 0
      base/18micropython/tank/main.py
  72. 9 0
      base/1function/call_func.py
  73. 34 0
      base/1function/def_func.py
  74. 32 0
      base/1function/kw_args.py
  75. 24 0
      base/1function/recur.py
  76. 15 0
      base/1function/var_args.py
  77. 31 0
      base/2advance/do_generator.py
  78. 64 0
      base/2advance/do_iter.py
  79. 12 0
      base/2advance/do_listcompr.py
  80. 16 0
      base/2advance/do_slice.py
  81. 29 0
      base/2advance/do_yield.py
  82. 33 0
      base/3functional/decorator.py
  83. 14 0
      base/3functional/do_filter.py
  84. 7 0
      base/3functional/do_map.py
  85. 9 0
      base/3functional/do_partial.py
  86. 61 0
      base/3functional/do_reduce.py
  87. 15 0
      base/3functional/do_sorted.py
  88. 29 0
      base/3functional/prime_numbers.py
  89. 46 0
      base/3functional/return_func.py
  90. 36 0
      base/4module/hello.py
  91. 67 0
      base/5oop_basic/animals.py
  92. 25 0
      base/5oop_basic/attrs.py
  93. 30 0
      base/5oop_basic/get_instance.py
  94. 14 0
      base/5oop_basic/get_type.py
  95. 35 0
      base/5oop_basic/protected_student.py
  96. 29 0
      base/5oop_basic/student.py
  97. 13 0
      base/6oop_advance/create_class_on_the_fly.py
  98. 77 0
      base/6oop_advance/orm.py
  99. 12 0
      base/6oop_advance/special_call.py
  100. 21 0
      base/6oop_advance/special_getattr.py

+ 30 - 0
base/0basic/do_for.py

@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# 打印list:
+names = ['Michael', 'Bob', 'Tracy']
+for name in names:
+    print(name)
+
+# 打印数字 0 - 9
+for x in range(10):
+    print(x)
+
+
+for x in range(0,11,2):
+    print("数字为%d"%x);
+
+name = "打发斯蒂芬";
+for str in name:
+    print("每个数字=%s"%str);
+
+lists = ["小明","小红","消防"];
+for item in lists:
+    print("当前名字=%s"%item);
+
+for i in range(len(lists)):
+    name = lists[i];
+    print("当前下标为=%d,名字为=%s"%(i,name))
+
+print("---")
+

+ 27 - 0
base/0basic/do_if.py

@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# 注意:
+# input()返回的是字符串
+# 必须通过int()将字符串转换为整数
+# 才能用于数值比较:
+age = int(input('Input your age: '))
+
+if age >= 18:
+    print('adult')
+elif age >= 6:
+    print('teenager')
+else:
+    print('kid')
+
+age = int(input("输入名字"))
+if age >= 18:
+    print("输入正确")
+    if age > 100:
+        print("成人")
+    elif age > 1000:
+        print("23423")
+else:
+    print("123")
+
+

+ 5 - 0
base/0basic/do_input.py

@@ -0,0 +1,5 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+name = input()
+print('Hello,', name)

+ 18 - 0
base/0basic/do_print.py

@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+print('The quick brown fox', 'jumps over', 'the lazy dog')
+print(300)
+print(100 + 200)
+print('100 + 200 =', 100 + 200)
+
+import random
+
+x = random.randint(0,20);
+print("\n当前随机数为=%s"%x);
+if x > 5:
+    print("当前是%d,大于5"%x)
+elif x > 10:
+    print("大于10");
+else:
+    print("什么都没有");

+ 18 - 0
base/0basic/do_while.py

@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# 计算1+2+3+...+100:
+sum = 0
+n = 1
+while n <= 100:
+    sum = sum + n
+    n = n + 1
+print(sum)
+
+# 计算1x2x3x...x100:
+acc = 1
+n = 1
+while n <= 100:
+    acc = acc * n
+    n = n + 1
+print(acc)

+ 4 - 0
base/0basic/hello.py

@@ -0,0 +1,4 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+print('Hello, world')

+ 12 - 0
base/0basic/the_dict.py

@@ -0,0 +1,12 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+d = {
+    'Michael': 95,
+    'Bob': 75,
+    'Tracy': 85
+}
+print('d[\'Michael\'] =', d['Michael'])
+print('d[\'Bob\'] =', d['Bob'])
+print('d[\'Tracy\'] =', d['Tracy'])
+print('d.get(\'Thomas\', -1) =', d.get('Thomas', -1))

+ 32 - 0
base/0basic/the_list.py

@@ -0,0 +1,32 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+classmates = ['Michael', 'Bob', 'Tracy']
+print('classmates =', classmates)
+print('len(classmates) =', len(classmates))
+print('classmates[0] =', classmates[0])
+print('classmates[1] =', classmates[1])
+print('classmates[2] =', classmates[2])
+print('classmates[-1] =', classmates[-1])
+classmates.pop()
+print('classmates =', classmates)
+
+contentLists = [1, "2", "3", [["6"], ["7"]]]
+for item in contentLists:
+    print("当前item=%s" % item)
+
+contentLists.append("天剑内容")
+
+for index in range(len(contentLists)):
+    content = contentLists[index];
+    if isinstance(content, list):
+        print("当前为数组")
+        for temp in content:
+            print(temp)
+    print("下标=%d,内容=%s" % (index, content))
+
+findName = input("请输入")
+if findName in contentLists:
+    print("已找到");
+else:
+    print("没有");

+ 8 - 0
base/0basic/the_set.py

@@ -0,0 +1,8 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+s1 = set([1, 1, 2, 2, 3, 3])
+print(s1)
+s2 = set([2, 3, 4])
+print(s1 & s2)
+print(s1 | s2)

+ 13 - 0
base/0basic/the_string.py

@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+s = 'Python-中文'
+print(s)
+b = s.encode('utf-8')
+print(b)
+print(b.decode('utf-8'))
+
+content = 'i\'am good'
+content = "i'am good" #//
+temp = content[0,3]; #截取
+temp = temp + "你好";#r""" 直接显示全部内容

+ 13 - 0
base/0basic/the_tuple.py

@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+classmates = ('Michael', 'Bob', 'Tracy')
+print('classmates =', classmates)
+print('len(classmates) =', len(classmates))
+print('classmates[0] =', classmates[0])
+print('classmates[1] =', classmates[1])
+print('classmates[2] =', classmates[2])
+print('classmates[-1] =', classmates[-1])
+
+# cannot modify tuple:
+classmates[0] = 'Adam'

+ 8 - 0
base/10commonlib/check_bmp.py

@@ -0,0 +1,8 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import struct
+
+bmp_header = b'\x42\x4d\x38\x8c\x0a\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00\x80\x02\x00\x00\x68\x01\x00\x00\x01\x00\x18\x00'
+
+print(struct.unpack('<ccIIIIIIHH', bmp_header))

+ 14 - 0
base/10commonlib/do_base64.py

@@ -0,0 +1,14 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import base64
+
+s = base64.b64encode('在Python中使用BASE 64编码'.encode('utf-8'))
+print(s)
+d = base64.b64decode(s).decode('utf-8')
+print(d)
+
+s = base64.urlsafe_b64encode('在Python中使用BASE 64编码'.encode('utf-8'))
+print(s)
+d = base64.urlsafe_b64decode(s).decode('utf-8')
+print(d)

+ 20 - 0
base/10commonlib/use_chainmap.py

@@ -0,0 +1,20 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from collections import ChainMap
+import os, argparse
+
+defaults = {
+    'color': 'red',
+    'user': 'guest'
+}
+
+parser = argparse.ArgumentParser()
+parser.add_argument('-u', '--user')
+parser.add_argument('-c', '--color')
+namespace = parser.parse_args()
+command_line_args = { k: v for k, v in vars(namespace).items() if v }
+
+combined = ChainMap(command_line_args, os.environ, defaults)
+print('color=%s' % combined['color'])
+print('user=%s' % combined['user'])

+ 28 - 0
base/10commonlib/use_collections.py

@@ -0,0 +1,28 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from collections import namedtuple
+
+Point = namedtuple('Point', ['x', 'y'])
+p = Point(1, 2)
+print('Point:', p.x, p.y)
+
+from collections import deque
+
+q = deque(['a', 'b', 'c'])
+q.append('x')
+q.appendleft('y')
+print(q)
+
+from collections import defaultdict
+
+dd = defaultdict(lambda: 'N/A')
+dd['key1'] = 'abc'
+print('dd[\'key1\'] =', dd['key1'])
+print('dd[\'key2\'] =', dd['key2'])
+
+from collections import Counter
+c = Counter()
+for ch in 'programming':
+    c[ch] = c[ch] + 1
+print(c)

+ 40 - 0
base/10commonlib/use_datetime.py

@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from datetime import datetime, timedelta, timezone
+
+# 获取当前datetime:
+now = datetime.now()
+print('now =', now)
+print('type(now) =', type(now))
+
+# 用指定日期时间创建datetime:
+dt = datetime(2015, 4, 19, 12, 20)
+print('dt =', dt)
+
+# 把datetime转换为timestamp:
+print('datetime -> timestamp:', dt.timestamp())
+
+# 把timestamp转换为datetime:
+t = dt.timestamp()
+print('timestamp -> datetime:', datetime.fromtimestamp(t))
+print('timestamp -> datetime as UTC+0:', datetime.utcfromtimestamp(t))
+
+# 从str读取datetime:
+cday = datetime.strptime('2015-6-1 18:19:59', '%Y-%m-%d %H:%M:%S')
+print('strptime:', cday)
+
+# 把datetime格式化输出:
+print('strftime:', cday.strftime('%a, %b %d %H:%M'))
+
+# 对日期进行加减:
+print('current datetime =', cday)
+print('current + 10 hours =', cday + timedelta(hours=10))
+print('current - 1 day =', cday - timedelta(days=1))
+print('current + 2.5 days =', cday + timedelta(days=2, hours=12))
+
+# 把时间从UTC+0时区转换为UTC+8:
+utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc)
+utc8_dt = utc_dt.astimezone(timezone(timedelta(hours=8)))
+print('UTC+0:00 now =', utc_dt)
+print('UTC+8:00 now =', utc8_dt)

+ 13 - 0
base/10commonlib/use_hashlib.py

@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import hashlib
+
+md5 = hashlib.md5()
+md5.update('how to use md5 in python hashlib?'.encode('utf-8'))
+print(md5.hexdigest())
+
+sha1 = hashlib.sha1()
+sha1.update('how to use sha1 in '.encode('utf-8'))
+sha1.update('python hashlib?'.encode('utf-8'))
+print(sha1.hexdigest())

+ 36 - 0
base/10commonlib/use_htmlparser.py

@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from html.parser import HTMLParser
+from html.entities import name2codepoint
+
+class MyHTMLParser(HTMLParser):
+
+    def handle_starttag(self, tag, attrs):
+        print('<%s>' % tag)
+
+    def handle_endtag(self, tag):
+        print('</%s>' % tag)
+
+    def handle_startendtag(self, tag, attrs):
+        print('<%s/>' % tag)
+
+    def handle_data(self, data):
+        print(data)
+
+    def handle_comment(self, data):
+        print('<!--', data, '-->')
+
+    def handle_entityref(self, name):
+        print('&%s;' % name)
+
+    def handle_charref(self, name):
+        print('&#%s;' % name)
+
+parser = MyHTMLParser()
+parser.feed('''<html>
+<head></head>
+<body>
+<!-- test html parser -->
+    <p>Some <a href=\"#\">html</a> HTML&nbsp;tutorial...<br>END</p>
+</body></html>''')

+ 18 - 0
base/10commonlib/use_itertools.py

@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import itertools
+
+natuals = itertools.count(1)
+for n in natuals:
+    print(n)
+    if n >= 100:
+        break
+
+cs = itertools.cycle('ABC')
+t = 10
+for c in cs:
+    print(c)
+    t = t - 1
+    if t == 0:
+        break

+ 28 - 0
base/10commonlib/use_sax.py

@@ -0,0 +1,28 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from xml.parsers.expat import ParserCreate
+
+class DefaultSaxHandler(object):
+    def start_element(self, name, attrs):
+        print('sax:start_element: %s, attrs: %s' % (name, str(attrs)))
+
+    def end_element(self, name):
+        print('sax:end_element: %s' % name)
+
+    def char_data(self, text):
+        print('sax:char_data: %s' % text)
+
+xml = r'''<?xml version="1.0"?>
+<ol>
+    <li><a href="/python">Python</a></li>
+    <li><a href="/ruby">Ruby</a></li>
+</ol>
+'''
+
+handler = DefaultSaxHandler()
+parser = ParserCreate()
+parser.StartElementHandler = handler.start_element
+parser.EndElementHandler = handler.end_element
+parser.CharacterDataHandler = handler.char_data
+parser.Parse(xml)

+ 58 - 0
base/10commonlib/use_urllib.py

@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from urllib import request, parse
+
+# get:
+
+with request.urlopen('https://api.douban.com/v2/book/2129650') as f:
+    data = f.read()
+    print('Status:', f.status, f.reason)
+    for k, v in f.getheaders():
+        print('%s: %s' % (k, v))
+    print('Data:', data.decode('utf-8'))
+
+# advanced get:
+
+req = request.Request('http://www.douban.com/')
+req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')
+with request.urlopen(req) as f:
+    print('Status:', f.status, f.reason)
+    for k, v in f.getheaders():
+        print('%s: %s' % (k, v))
+    print('Data:', f.read().decode('utf-8'))
+
+# post:
+
+print('Login to weibo.cn...')
+email = input('Email: ')
+passwd = input('Password: ')
+login_data = parse.urlencode([
+    ('username', email),
+    ('password', passwd),
+    ('entry', 'mweibo'),
+    ('client_id', ''),
+    ('savestate', '1'),
+    ('ec', ''),
+    ('pagerefer', 'https://passport.weibo.cn/signin/welcome?entry=mweibo&r=http%3A%2F%2Fm.weibo.cn%2F%3Fjumpfrom%3Dweibocom&jumpfrom=weibocom')
+])
+
+req = request.Request('https://passport.weibo.cn/sso/login')
+req.add_header('Origin', 'https://passport.weibo.cn')
+req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')
+req.add_header('Referer', 'https://passport.weibo.cn/signin/login?entry=mweibo&res=wel&wm=3349&r=http%3A%2F%2Fm.weibo.cn%2F%3Fjumpfrom%3Dweibocom')
+
+with request.urlopen(req, data=login_data.encode('utf-8')) as f:
+    print('Status:', f.status, f.reason)
+    for k, v in f.getheaders():
+        print('%s: %s' % (k, v))
+    print('Data:', f.read().decode('utf-8'))
+
+# with proxy and proxy auth:
+
+proxy_handler = urllib.request.ProxyHandler({'http': 'http://www.example.com:3128/'})
+proxy_auth_handler = urllib.request.ProxyBasicAuthHandler()
+proxy_auth_handler.add_password('realm', 'host', 'username', 'password')
+opener = urllib.request.build_opener(proxy_handler, proxy_auth_handler)
+with opener.open('http://www.example.com/login.html') as f:
+    pass

+ 26 - 0
base/11packages/pil/README

@@ -0,0 +1,26 @@
+Install PIL
+===========
+
+### Windows
+
+Open web page: https://pypi.python.org/pypi/Pillow/2.8.1
+
+Find link of "Pillow-2.8.1.win-amd64-py3.4.exe" and download it:
+
+https://pypi.python.org/packages/3.4/P/Pillow/Pillow-2.8.1.win-amd64-py3.4.exe
+
+### Mac OS X
+
+Step 1: Install dependencies by brew:
+
+$ brew install libtiff libjpeg webp little-cms2
+
+Step 2: Install Pillow by pip:
+
+$ sudo pip3 install Pillow
+
+### Linux
+
+For Debian/Ubuntu:
+
+$ sudo apt-get install python3-pil

BIN
base/11packages/pil/test.jpg


+ 10 - 0
base/11packages/pil/use_pil_blur.py

@@ -0,0 +1,10 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from PIL import Image, ImageFilter
+
+# 打开一个jpg图像文件,注意是当前路径:
+im = Image.open('test.jpg')
+# 应用模糊滤镜:
+im2 = im.filter(ImageFilter.BLUR)
+im2.save('blur.jpg', 'jpeg')

+ 44 - 0
base/11packages/pil/use_pil_draw.py

@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from PIL import Image, ImageDraw, ImageFont, ImageFilter
+
+import random
+
+# 随机字母:
+
+
+def rndChar():
+    return chr(random.randint(65, 90))
+
+# 随机颜色1:
+
+
+def rndColor():
+    return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))
+
+# 随机颜色2:
+
+
+def rndColor2():
+    return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))
+
+
+# 240 x 60:
+width = 60 * 4
+height = 60
+image = Image.new('RGB', (width, height), (255, 255, 255))
+# 创建Font对象:
+font = ImageFont.truetype('Arial.ttf', 36)
+# 创建Draw对象:
+draw = ImageDraw.Draw(image)
+# 填充每个像素:
+for x in range(width):
+    for y in range(height):
+        draw.point((x, y), fill=rndColor())
+# 输出文字:
+for t in range(4):
+    draw.text((60 * t + 10, 10), rndChar(), font=font, fill=rndColor2())
+# 模糊:
+image = image.filter(ImageFilter.BLUR)
+image.save('code.jpg', 'jpeg')

+ 15 - 0
base/11packages/pil/use_pil_resize.py

@@ -0,0 +1,15 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from PIL import Image
+
+# 打开一个jpg图像文件,注意是当前路径:
+im = Image.open('test.jpg')
+# 获得图像尺寸:
+w, h = im.size
+print('Original image size: %sx%s' % (w, h))
+# 缩放到50%:
+im.thumbnail((w//2, h//2))
+print('Resize image to: %sx%s' % (w//2, h//2))
+# 把缩放后的图像用jpeg格式保存:
+im.save('thumbnail.jpg', 'jpeg')

+ 27 - 0
base/12gui/hello_gui.py

@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from tkinter import *
+import tkinter.messagebox as messagebox
+
+class Application(Frame):
+    def __init__(self, master=None):
+        Frame.__init__(self, master)
+        self.pack()
+        self.createWidgets()
+
+    def createWidgets(self):
+        self.nameInput = Entry(self)
+        self.nameInput.pack()
+        self.alertButton = Button(self, text='Hello', command=self.hello)
+        self.alertButton.pack()
+
+    def hello(self):
+        name = self.nameInput.get() or 'world'
+        messagebox.showinfo('Message', 'Hello, %s' % name)
+
+app = Application()
+# 设置窗口标题:
+app.master.title('Hello World')
+# 主消息循环:
+app.mainloop()

+ 26 - 0
base/12gui/turtle/rect.py

@@ -0,0 +1,26 @@
+# 导入turtle包的所有内容:
+from turtle import *
+
+# 设置笔刷宽度:
+width(4)
+
+# 前进:
+forward(200)
+# 右转90度:
+right(90)
+
+# 笔刷颜色:
+pencolor('red')
+forward(100)
+right(90)
+
+pencolor('green')
+forward(200)
+right(90)
+
+pencolor('blue')
+forward(100)
+right(90)
+
+# 调用done()使得窗口等待被关闭,否则将立刻关闭窗口:
+done()

+ 16 - 0
base/12gui/turtle/stars.py

@@ -0,0 +1,16 @@
+from turtle import *
+
+def drawStar(x, y):
+    pu()
+    goto(x, y)
+    pd()
+    # set heading: 0
+    seth(0)
+    for i in range(5):
+        fd(40)
+        rt(144)
+
+for x in range(0, 250, 50):
+    drawStar(x, 0)
+
+done()

+ 59 - 0
base/12gui/turtle/tree.py

@@ -0,0 +1,59 @@
+from turtle import *
+
+colormode(255)
+
+lt(90)
+
+lv = 14
+l = 120
+s = 45
+
+width(lv)
+
+r = 0
+g = 0
+b = 0
+pencolor(r, g, b)
+
+penup()
+bk(l)
+pendown()
+fd(l)
+
+def draw_tree(l, level):
+    global r, g, b
+    # save the current pen width
+    w = width()
+
+    # narrow the pen width
+    width(w * 3.0 / 4.0)
+    # set color:
+    r = r + 1
+    g = g + 2
+    b = b + 3
+    pencolor(r % 200, g % 200, b % 200)
+
+    l = 3.0 / 4.0 * l
+
+    lt(s)
+    fd(l)
+
+    if level < lv:
+        draw_tree(l, level + 1)
+    bk(l)
+    rt(2 * s)
+    fd(l)
+
+    if level < lv:
+        draw_tree(l, level + 1)
+    bk(l)
+    lt(s)
+
+    # restore the previous pen width
+    width(w)
+
+speed("fastest")
+
+draw_tree(l, 4)
+
+done()

+ 35 - 0
base/13socket/do_tcp.py

@@ -0,0 +1,35 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import socket
+
+# 创建一个socket:
+s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+# 建立连接:
+s.connect(('www.sina.com.cn', 80))
+
+# 发送数据:
+s.send(b'GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n')
+
+# 接收数据:
+buffer = []
+while True:
+    # 每次最多接收1k字节:
+    d = s.recv(1024)
+    if d:
+        buffer.append(d)
+    else:
+        break
+
+data = b''.join(buffer)
+
+# 关闭连接:
+s.close()
+
+header, html = data.split(b'\r\n\r\n', 1)
+print(header.decode('utf-8'))
+
+# 把接收的数据写入文件:
+with open('sina.html', 'wb') as f:
+    f.write(html)

+ 14 - 0
base/13socket/udp_client.py

@@ -0,0 +1,14 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import socket
+
+s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+
+for data in [b'Michael', b'Tracy', b'Sarah']:
+    # 发送数据:
+    s.sendto(data, ('127.0.0.1', 9999))
+    # 接收数据:
+    print(s.recv(1024).decode('utf-8'))
+
+s.close()

+ 18 - 0
base/13socket/udp_server.py

@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import socket
+
+s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+
+# 绑定端口:
+s.bind(('127.0.0.1', 9999))
+
+print('Bind UDP on 9999...')
+
+while True:
+    # 接收数据:
+    data, addr = s.recvfrom(1024)
+    print('Received from %s:%s.' % addr)
+    reply = 'Hello, %s!' % data.decode('utf-8')
+    s.sendto(reply.encode('utf-8'), addr)

+ 86 - 0
base/14mail/fetch_mail.py

@@ -0,0 +1,86 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from email.parser import Parser
+from email.header import decode_header
+from email.utils import parseaddr
+
+import poplib
+
+# 输入邮件地址, 口令和POP3服务器地址:
+email = input('Email: ')
+password = input('Password: ')
+pop3_server = input('POP3 server: ')
+
+def guess_charset(msg):
+    charset = msg.get_charset()
+    if charset is None:
+        content_type = msg.get('Content-Type', '').lower()
+        pos = content_type.find('charset=')
+        if pos >= 0:
+            charset = content_type[pos + 8:].strip()
+    return charset
+
+def decode_str(s):
+    value, charset = decode_header(s)[0]
+    if charset:
+        value = value.decode(charset)
+    return value
+
+def print_info(msg, indent=0):
+    if indent == 0:
+        for header in ['From', 'To', 'Subject']:
+            value = msg.get(header, '')
+            if value:
+                if header=='Subject':
+                    value = decode_str(value)
+                else:
+                    hdr, addr = parseaddr(value)
+                    name = decode_str(hdr)
+                    value = u'%s <%s>' % (name, addr)
+            print('%s%s: %s' % ('  ' * indent, header, value))
+    if (msg.is_multipart()):
+        parts = msg.get_payload()
+        for n, part in enumerate(parts):
+            print('%spart %s' % ('  ' * indent, n))
+            print('%s--------------------' % ('  ' * indent))
+            print_info(part, indent + 1)
+    else:
+        content_type = msg.get_content_type()
+        if content_type=='text/plain' or content_type=='text/html':
+            content = msg.get_payload(decode=True)
+            charset = guess_charset(msg)
+            if charset:
+                content = content.decode(charset)
+            print('%sText: %s' % ('  ' * indent, content + '...'))
+        else:
+            print('%sAttachment: %s' % ('  ' * indent, content_type))
+
+# 连接到POP3服务器:
+server = poplib.POP3(pop3_server)
+# 可以打开或关闭调试信息:
+server.set_debuglevel(1)
+# 可选:打印POP3服务器的欢迎文字:
+print(server.getwelcome().decode('utf-8'))
+# 身份认证:
+server.user(email)
+server.pass_(password)
+# stat()返回邮件数量和占用空间:
+print('Messages: %s. Size: %s' % server.stat())
+# list()返回所有邮件的编号:
+resp, mails, octets = server.list()
+# 可以查看返回的列表类似[b'1 82923', b'2 2184', ...]
+print(mails)
+# 获取最新一封邮件, 注意索引号从1开始:
+index = len(mails)
+resp, lines, octets = server.retr(index)
+# lines存储了邮件的原始文本的每一行,
+# 可以获得整个邮件的原始文本:
+msg_content = b'\r\n'.join(lines).decode('utf-8')
+# 稍后解析出邮件:
+msg = Parser().parsestr(msg_content)
+print_info(msg)
+# 可以根据邮件索引号直接从服务器删除邮件:
+# server.dele(index)
+# 关闭连接:
+server.quit()

+ 28 - 0
base/14mail/send_mail.py

@@ -0,0 +1,28 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from email import encoders
+from email.header import Header
+from email.mime.text import MIMEText
+from email.utils import parseaddr, formataddr
+import smtplib
+
+def _format_addr(s):
+    name, addr = parseaddr(s)
+    return formataddr((Header(name, 'utf-8').encode(), addr))
+
+from_addr = input('From: ')
+password = input('Password: ')
+to_addr = input('To: ')
+smtp_server = input('SMTP server: ')
+
+msg = MIMEText('hello, send by Python...', 'plain', 'utf-8')
+msg['From'] = _format_addr('Python爱好者 <%s>' % from_addr)
+msg['To'] = _format_addr('管理员 <%s>' % to_addr)
+msg['Subject'] = Header('来自SMTP的问候……', 'utf-8').encode()
+
+server = smtplib.SMTP(smtp_server, 25)
+server.set_debuglevel(1)
+server.login(from_addr, password)
+server.sendmail(from_addr, [to_addr], msg.as_string())
+server.quit()

+ 33 - 0
base/15db/do_mysql.py

@@ -0,0 +1,33 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+########## prepare ##########
+
+# install mysql-connector-python:
+# pip3 install mysql-connector-python --allow-external mysql-connector-python
+
+import mysql.connector
+
+# change root password to yours:
+conn = mysql.connector.connect(
+    user='root', password='password', database='test')
+
+cursor = conn.cursor()
+# 创建user表:
+cursor.execute(
+    'create table user (id varchar(20) primary key, name varchar(20))')
+# 插入一行记录,注意MySQL的占位符是%s:
+cursor.execute('insert into user (id, name) values (%s, %s)', ('1', 'Michael'))
+print('rowcount =', cursor.rowcount)
+# 提交事务:
+conn.commit()
+cursor.close()
+
+# 运行查询:
+cursor = conn.cursor()
+cursor.execute('select * from user where id = %s', ('1',))
+values = cursor.fetchall()
+print(values)
+# 关闭Cursor和Connection:
+cursor.close()
+conn.close()

+ 44 - 0
base/15db/do_sqlalchemy.py

@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from sqlalchemy import Column, String, create_engine
+from sqlalchemy.orm import sessionmaker
+from sqlalchemy.ext.declarative import declarative_base
+
+# 创建对象的基类:
+Base = declarative_base()
+
+# 定义User对象:
+class User(Base):
+    # 表的名字:
+    __tablename__ = 'user'
+
+    # 表的结构:
+    id = Column(String(20), primary_key=True)
+    name = Column(String(20))
+
+# 初始化数据库连接:
+engine = create_engine('mysql+mysqlconnector://root:password@localhost:3306/test')
+# 创建DBSession类型:
+DBSession = sessionmaker(bind=engine)
+
+# 创建session对象:
+session = DBSession()
+# 创建新User对象:
+new_user = User(id='5', name='Bob')
+# 添加到session:
+session.add(new_user)
+# 提交即保存到数据库:
+session.commit()
+# 关闭session:
+session.close()
+
+# 创建Session:
+session = DBSession()
+# 创建Query查询,filter是where条件,最后调用one()返回唯一行,如果调用all()则返回所有行:
+user = session.query(User).filter(User.id=='5').one()
+# 打印类型和对象的name属性:
+print('type:', type(user))
+print('name:', user.name)
+# 关闭Session:
+session.close()

+ 35 - 0
base/15db/do_sqlite.py

@@ -0,0 +1,35 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import sqlite3
+
+# 连接到SQLite数据库
+# 数据库文件是test.db
+# 如果文件不存在,会自动在当前目录创建:
+conn = sqlite3.connect('test.db')
+# 创建一个Cursor:
+cursor = conn.cursor()
+# 执行一条SQL语句,创建user表:
+cursor.execute(
+    'create table user (id varchar(20) primary key, name varchar(20))')
+# 继续执行一条SQL语句,插入一条记录:
+cursor.execute('insert into user (id, name) values (\'1\', \'Michael\')')
+# 通过rowcount获得插入的行数:
+print('rowcount =', cursor.rowcount)
+# 关闭Cursor:
+cursor.close()
+# 提交事务:
+conn.commit()
+# 关闭Connection:
+conn.close()
+
+# 查询记录:
+conn = sqlite3.connect('test.db')
+cursor = conn.cursor()
+# 执行查询语句:
+cursor.execute('select * from user where id=?', '1')
+# 获得查询结果集:
+values = cursor.fetchall()
+print(values)
+cursor.close()
+conn.close()

+ 29 - 0
base/16web/do_flask.py

@@ -0,0 +1,29 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from flask import Flask
+from flask import request
+
+app = Flask(__name__)
+
+@app.route('/', methods=['GET', 'POST'])
+def home():
+    return '<h1>Home</h1>'
+
+@app.route('/signin', methods=['GET'])
+def signin_form():
+    return '''<form action="/signin" method="post">
+              <p><input name="username"></p>
+              <p><input name="password" type="password"></p>
+              <p><button type="submit">Sign In</button></p>
+              </form>'''
+
+@app.route('/signin', methods=['POST'])
+def signin():
+    # 需要从request对象读取表单内容:
+    if request.form['username']=='admin' and request.form['password']=='password':
+        return '<h3>Hello, admin!</h3>'
+    return '<h3>Bad username or password.</h3>'
+
+if __name__ == '__main__':
+    app.run()

+ 11 - 0
base/16web/do_wsgi.py

@@ -0,0 +1,11 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from wsgiref.simple_server import make_server
+
+from hello import application
+
+httpd = make_server('', 8000, application)
+print('Serving HTTP on port 8000...')
+
+httpd.serve_forever()

+ 7 - 0
base/16web/hello.py

@@ -0,0 +1,7 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+def application(environ, start_response):
+    start_response('200 OK', [('Content-Type', 'text/html')])
+    body = '<h1>Hello, %s!</h1>' % (environ['PATH_INFO'][1:] or 'web')
+    return [body.encode('utf-8')]

+ 25 - 0
base/16web/mvc/app.py

@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from flask import Flask, request, render_template
+
+app = Flask(__name__)
+
+@app.route('/', methods=['GET', 'POST'])
+def home():
+    return render_template('home.html')
+
+@app.route('/signin', methods=['GET'])
+def signin_form():
+    return render_template('form.html')
+
+@app.route('/signin', methods=['POST'])
+def signin():
+    username = request.form['username']
+    password = request.form['password']
+    if username=='admin' and password=='password':
+        return render_template('signin-ok.html', username=username)
+    return render_template('form.html', message='Bad username or password', username=username)
+
+if __name__ == '__main__':
+    app.run()

+ 16 - 0
base/16web/mvc/templates/form.html

@@ -0,0 +1,16 @@
+<html>
+<head>
+  <title>Please Sign In</title>
+</head>
+<body>
+  {% if message %}
+  <p style="color:red">{{ message }}</p>
+  {% endif %}
+  <form action="/signin" method="post">
+    <legend>Please sign in:</legend>
+    <p><input name="username" placeholder="Username" value="{{ username }}"></p>
+    <p><input name="password" placeholder="Password" type="password"></p>
+    <p><button type="submit">Sign In</button></p>
+  </form>
+</body>
+</html>

+ 8 - 0
base/16web/mvc/templates/home.html

@@ -0,0 +1,8 @@
+<html>
+<head>
+  <title>Home</title>
+</head>
+<body>
+  <h1 style="font-style:italic">Home</h1>
+</body>
+</html>

+ 8 - 0
base/16web/mvc/templates/signin-ok.html

@@ -0,0 +1,8 @@
+<html>
+<head>
+  <title>Welcome, {{ username }}</title>
+</head>
+<body>
+  <p>Welcome, {{ username }}!</p>
+</body>
+</html>

+ 33 - 0
base/17async/aio_web.py

@@ -0,0 +1,33 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+__author__ = 'Michael Liao'
+
+'''
+async web application.
+'''
+
+import asyncio
+
+from aiohttp import web
+
+async def index(request):
+    await asyncio.sleep(0.5)
+    return web.Response(body=b'<h1>Index</h1>')
+
+async def hello(request):
+    await asyncio.sleep(0.5)
+    text = '<h1>hello, %s!</h1>' % request.match_info['name']
+    return web.Response(body=text.encode('utf-8'))
+
+async def init(loop):
+    app = web.Application(loop=loop)
+    app.router.add_route('GET', '/', index)
+    app.router.add_route('GET', '/hello/{name}', hello)
+    srv = await loop.create_server(app.make_handler(), '127.0.0.1', 8000)
+    print('Server started at http://127.0.0.1:8000...')
+    return srv
+
+loop = asyncio.get_event_loop()
+loop.run_until_complete(init(loop))
+loop.run_forever()

+ 16 - 0
base/17async/async_hello.py

@@ -0,0 +1,16 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import threading
+import asyncio
+
+@asyncio.coroutine
+def hello():
+    print('Hello world! (%s)' % threading.currentThread())
+    yield from asyncio.sleep(1)
+    print('Hello again! (%s)' % threading.currentThread())
+
+loop = asyncio.get_event_loop()
+tasks = [hello(), hello()]
+loop.run_until_complete(asyncio.wait(tasks))
+loop.close()

+ 15 - 0
base/17async/async_hello2.py

@@ -0,0 +1,15 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import threading
+import asyncio
+
+async def hello():
+    print('Hello world! (%s)' % threading.currentThread())
+    await asyncio.sleep(1)
+    print('Hello again! (%s)' % threading.currentThread())
+
+loop = asyncio.get_event_loop()
+tasks = [hello(), hello()]
+loop.run_until_complete(asyncio.wait(tasks))
+loop.close()

+ 25 - 0
base/17async/async_wget.py

@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import asyncio
+
+@asyncio.coroutine
+def wget(host):
+    print('wget %s...' % host)
+    connect = asyncio.open_connection(host, 80)
+    reader, writer = yield from connect
+    header = 'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' % host
+    writer.write(header.encode('utf-8'))
+    yield from writer.drain()
+    while True:
+        line = yield from reader.readline()
+        if line == b'\r\n':
+            break
+        print('%s header > %s' % (host, line.decode('utf-8').rstrip()))
+    # Ignore the body, close the socket
+    writer.close()
+
+loop = asyncio.get_event_loop()
+tasks = [wget(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']]
+loop.run_until_complete(asyncio.wait(tasks))
+loop.close()

+ 15 - 0
base/17async/async_wget2.py

@@ -0,0 +1,15 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import threading
+import asyncio
+
+async def hello():
+    print('Hello world! (%s)' % threading.currentThread())
+    await asyncio.sleep(1)
+    print('Hello again! (%s)' % threading.currentThread())
+
+loop = asyncio.get_event_loop()
+tasks = [hello(), hello()]
+loop.run_until_complete(asyncio.wait(tasks))
+loop.close()

+ 24 - 0
base/17async/coroutine.py

@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+def consumer():
+    r = ''
+    while True:
+        n = yield r
+        if not n:
+            return
+        print('[CONSUMER] Consuming %s...' % n)
+        r = '200 OK'
+
+def produce(c):
+    c.send(None)
+    n = 0
+    while n < 5:
+        n = n + 1
+        print('[PRODUCER] Producing %s...' % n)
+        r = c.send(n)
+        print('[PRODUCER] Consumer return: %s' % r)
+    c.close()
+
+c = consumer()
+produce(c)

+ 13 - 0
base/18micropython/hellorobot/.vscode/extensions.json

@@ -0,0 +1,13 @@
+{
+	// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
+	// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
+
+	// List of extensions which should be recommended for users of this workspace.
+	"recommendations": [
+		"lego-education.ev3-micropython"
+	],
+	// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
+	"unwantedRecommendations": [
+		"ms-python.python"
+	]
+}

+ 14 - 0
base/18micropython/hellorobot/.vscode/launch.json

@@ -0,0 +1,14 @@
+{
+	// Use IntelliSense to learn about possible attributes.
+	// Hover to view descriptions of existing attributes.
+	// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+	"version": "0.2.0",
+	"configurations": [
+		{
+			"name": "Download and Run",
+			"type": "ev3devBrowser",
+			"request": "launch",
+			"program": "/home/robot/${workspaceRootFolderName}/main.py"
+		}
+	]
+}

+ 6 - 0
base/18micropython/hellorobot/.vscode/settings.json

@@ -0,0 +1,6 @@
+// Place your settings in this file to overwrite default and user settings.
+{
+	"files.eol": "\n",
+	"debug.openDebug": "neverOpen",
+	"python.linting.enabled": false
+}

+ 14 - 0
base/18micropython/hellorobot/main.py

@@ -0,0 +1,14 @@
+#!/usr/bin/env pybricks-micropython
+
+from pybricks import ev3brick as brick
+from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, InfraredSensor, UltrasonicSensor, GyroSensor)
+from pybricks.parameters import (Port, Stop, Direction, Button, Color, SoundFile, ImageFile, Align)
+from pybricks.tools import print, wait, StopWatch
+from pybricks.robotics import DriveBase
+
+# Write your program here
+brick.sound.beep()
+# 输出到控制台:
+print('Hello, robot!')
+# 输出到EV3屏幕:
+brick.display.text('Hello, robot!')

+ 13 - 0
base/18micropython/rccar/.vscode/extensions.json

@@ -0,0 +1,13 @@
+{
+	// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
+	// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
+
+	// List of extensions which should be recommended for users of this workspace.
+	"recommendations": [
+		"lego-education.ev3-micropython"
+	],
+	// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
+	"unwantedRecommendations": [
+		"ms-python.python"
+	]
+}

+ 14 - 0
base/18micropython/rccar/.vscode/launch.json

@@ -0,0 +1,14 @@
+{
+	// Use IntelliSense to learn about possible attributes.
+	// Hover to view descriptions of existing attributes.
+	// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+	"version": "0.2.0",
+	"configurations": [
+		{
+			"name": "Download and Run",
+			"type": "ev3devBrowser",
+			"request": "launch",
+			"program": "/home/robot/${workspaceRootFolderName}/main.py"
+		}
+	]
+}

+ 6 - 0
base/18micropython/rccar/.vscode/settings.json

@@ -0,0 +1,6 @@
+// Place your settings in this file to overwrite default and user settings.
+{
+	"files.eol": "\n",
+	"debug.openDebug": "neverOpen",
+	"python.linting.enabled": false
+}

+ 47 - 0
base/18micropython/rccar/devices.py

@@ -0,0 +1,47 @@
+# list input devices
+
+class InputDevice():
+    def __init__(self):
+        self.name = ''
+        self.handler = ''
+
+    def __str__(self):
+        return '<Input Device: name=%s, handler=%s>' % (self.name, self.handler)
+
+    def setName(self, name):
+        if len(name) >= 2 and name.startswith('"') and name.endswith('"'):
+            name = name[1:len(name)-1]
+        self.name = name
+
+    def setHandler(self, handlers):
+        for handler in handlers.split(' '):
+            if handler.startswith('event'):
+                self.handler = handler
+
+def listDevices():
+    devices = []
+    with open('/proc/bus/input/devices', 'r') as f:
+        device = None
+        while True:
+            s = f.readline()
+            if s == '':
+                break
+            s = s.strip()
+            if s == '':
+                devices.append(device)
+                device = None
+            else:
+                if device is None:
+                    device = InputDevice()
+                if s.startswith('N: Name='):
+                    device.setName(s[8:])
+                elif s.startswith('H: Handlers='):
+                    device.setHandler(s[12:])
+    return devices
+
+def detectJoystick(joystickNames):
+    for device in listDevices():
+        for joystickName in joystickNames:
+            if joystickName in device.name:
+                return '/dev/input/%s' % device.handler
+    return None

+ 100 - 0
base/18micropython/rccar/main.py

@@ -0,0 +1,100 @@
+#!/usr/bin/env pybricks-micropython
+
+import struct, threading
+
+from pybricks import ev3brick as brick
+from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, InfraredSensor, UltrasonicSensor, GyroSensor)
+from pybricks.parameters import (Port, Stop, Direction, Button, Color, SoundFile, ImageFile, Align)
+from pybricks.tools import print, wait, StopWatch
+from pybricks.robotics import DriveBase
+from devices import detectJoystick
+
+class Robot():
+    def __init__(self):
+        self.motor = Motor(Port.B)
+        self.ultrasonic = UltrasonicSensor(Port.S4)
+        self.active = True
+        self.speed = 0
+        self.colors = [None, Color.GREEN, Color.YELLOW, Color.RED]
+
+    def setSpeed(self, acc):
+        if acc < 0:
+            self.speed = max(-3, self.speed - 1)
+        elif acc > 0:
+            self.speed = min(3, self.speed + 1)
+        else:
+            self.speed = 0
+        if self.speed != 0:
+            self.motor.run(self.speed * 90)
+        else:
+            self.motor.stop()
+        brick.light(self.colors[abs(self.speed)])
+
+    def inactive(self):
+        self.active = False
+        self.setSpeed(0)
+        brick.sound.beep()
+
+def autoStopLoop(robot):
+    while robot.active:
+        if robot.speed > 0 and robot.ultrasonic.distance() < 200:
+            robot.setSpeed(0)
+        wait(100)
+
+def joystickLoop(robot, eventFile):
+    FORMAT = 'llHHI'
+    EVENT_SIZE = struct.calcsize(FORMAT)
+    with open(eventFile, 'rb') as infile:
+        while True:
+            event = infile.read(EVENT_SIZE)
+            _, _, t, c, v = struct.unpack(FORMAT, event)
+            # button A, B:
+            if t == 1 and v == 1:
+                if c == 305:
+                    # press A:
+                    robot.setSpeed(1)
+                elif c == 304:
+                    # press B:
+                    robot.setSpeed(-1)
+                elif c == 307:
+                    # press X:
+                    return robot.inactive()
+            elif t == 3:
+                if c == 1:
+                    # Left stick & vertical:
+                    speed = 0
+                    if v < 32768:
+                        # up:
+                        speed = 1
+                    elif v > 32768:
+                        # down:
+                        speed = -1
+                    robot.setSpeed(speed)
+
+def buttonLoop(robot):
+    while True:
+        if not any(brick.buttons()):
+            wait(10)
+        else:
+            if Button.LEFT in brick.buttons():
+                robot.setSpeed(-1)
+            elif Button.RIGHT in brick.buttons():
+                robot.setSpeed(1)
+            elif Button.CENTER in brick.buttons():
+                robot.setSpeed(0)
+            elif Button.UP in brick.buttons():
+                return robot.inactive()
+            wait(500)
+
+def main():
+    brick.sound.beep()
+    joystickEvent = detectJoystick(['Controller'])
+    robot = Robot()
+    t = threading.Thread(target=autoStopLoop, args=(robot,))
+    t.start()
+    if joystickEvent:
+        joystickLoop(robot, joystickEvent)
+    else:
+        buttonLoop(robot)
+
+main()

+ 13 - 0
base/18micropython/smallcar/.vscode/extensions.json

@@ -0,0 +1,13 @@
+{
+	// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
+	// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
+
+	// List of extensions which should be recommended for users of this workspace.
+	"recommendations": [
+		"lego-education.ev3-micropython"
+	],
+	// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
+	"unwantedRecommendations": [
+		"ms-python.python"
+	]
+}

+ 14 - 0
base/18micropython/smallcar/.vscode/launch.json

@@ -0,0 +1,14 @@
+{
+	// Use IntelliSense to learn about possible attributes.
+	// Hover to view descriptions of existing attributes.
+	// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+	"version": "0.2.0",
+	"configurations": [
+		{
+			"name": "Download and Run",
+			"type": "ev3devBrowser",
+			"request": "launch",
+			"program": "/home/robot/${workspaceRootFolderName}/main.py"
+		}
+	]
+}

+ 7 - 0
base/18micropython/smallcar/.vscode/settings.json

@@ -0,0 +1,7 @@
+// Place your settings in this file to overwrite default and user settings.
+{
+	"files.eol": "\n",
+	"debug.openDebug": "neverOpen",
+	"python.linting.enabled": false,
+	"python.formatting.provider": "autopep8"
+}

+ 51 - 0
base/18micropython/smallcar/main.py

@@ -0,0 +1,51 @@
+#!/usr/bin/env pybricks-micropython
+
+from pybricks import ev3brick as brick
+from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, InfraredSensor, UltrasonicSensor, GyroSensor)
+from pybricks.parameters import (Port, Stop, Direction, Button, Color, SoundFile, ImageFile, Align)
+from pybricks.tools import print, wait, StopWatch
+from pybricks.robotics import DriveBase
+
+# Write your program here
+
+motor = Motor(Port.B)
+ultrasonic = UltrasonicSensor(Port.S4)
+
+brick.sound.beep()
+brick.light(None)
+
+speed = 0
+colors = [None, Color.GREEN, Color.YELLOW, Color.RED]
+
+def setSpeed(acc):
+    global speed
+    if acc < 0:
+        speed = max(0, speed - 1)
+    elif acc > 0:
+        speed = min(3, speed + 1)
+    else:
+        speed = 0
+    if speed > 0:
+        motor.run(speed * 90)
+    else:
+        motor.stop()
+    brick.light(colors[speed])
+
+while True:
+    if not any(brick.buttons()):
+        wait(10)
+    else:
+        if Button.LEFT in brick.buttons():
+            setSpeed(-1)
+        elif Button.RIGHT in brick.buttons():
+            setSpeed(1)
+        elif Button.CENTER in brick.buttons():
+            setSpeed(0)
+        elif Button.UP in brick.buttons():
+            setSpeed(0)
+            break
+        wait(500)
+    if ultrasonic.distance() < 200:
+        setSpeed(0)
+
+brick.sound.beep()

+ 13 - 0
base/18micropython/tank/.vscode/extensions.json

@@ -0,0 +1,13 @@
+{
+	// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
+	// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
+
+	// List of extensions which should be recommended for users of this workspace.
+	"recommendations": [
+		"lego-education.ev3-micropython"
+	],
+	// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
+	"unwantedRecommendations": [
+		"ms-python.python"
+	]
+}

+ 14 - 0
base/18micropython/tank/.vscode/launch.json

@@ -0,0 +1,14 @@
+{
+	// Use IntelliSense to learn about possible attributes.
+	// Hover to view descriptions of existing attributes.
+	// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+	"version": "0.2.0",
+	"configurations": [
+		{
+			"name": "Download and Run",
+			"type": "ev3devBrowser",
+			"request": "launch",
+			"program": "/home/robot/${workspaceRootFolderName}/main.py"
+		}
+	]
+}

+ 6 - 0
base/18micropython/tank/.vscode/settings.json

@@ -0,0 +1,6 @@
+// Place your settings in this file to overwrite default and user settings.
+{
+	"files.eol": "\n",
+	"debug.openDebug": "neverOpen",
+	"python.linting.enabled": false
+}

BIN
base/18micropython/tank/cannon.wav


+ 47 - 0
base/18micropython/tank/devices.py

@@ -0,0 +1,47 @@
+# list input devices
+
+class InputDevice():
+    def __init__(self):
+        self.name = ''
+        self.handler = ''
+
+    def __str__(self):
+        return '<Input Device: name=%s, handler=%s>' % (self.name, self.handler)
+
+    def setName(self, name):
+        if len(name) >= 2 and name.startswith('"') and name.endswith('"'):
+            name = name[1:len(name)-1]
+        self.name = name
+
+    def setHandler(self, handlers):
+        for handler in handlers.split(' '):
+            if handler.startswith('event'):
+                self.handler = handler
+
+def listDevices():
+    devices = []
+    with open('/proc/bus/input/devices', 'r') as f:
+        device = None
+        while True:
+            s = f.readline()
+            if s == '':
+                break
+            s = s.strip()
+            if s == '':
+                devices.append(device)
+                device = None
+            else:
+                if device is None:
+                    device = InputDevice()
+                if s.startswith('N: Name='):
+                    device.setName(s[8:])
+                elif s.startswith('H: Handlers='):
+                    device.setHandler(s[12:])
+    return devices
+
+def detectJoystick(joystickNames):
+    for device in listDevices():
+        for joystickName in joystickNames:
+            if joystickName in device.name:
+                return '/dev/input/%s' % device.handler
+    return None

+ 61 - 0
base/18micropython/tank/joystick.py

@@ -0,0 +1,61 @@
+# joystick control:
+
+import struct
+
+# define button code:
+
+BUTTON_A = 305
+BUTTON_B = 304
+BUTTON_X = 307
+BUTTON_Y = 306
+BUTTON_PLUS = 313
+BUTTON_MINUS = 312
+BUTTON_START = 317
+BUTTON_HOME = 316 
+
+class JoyStick():
+    def __init__(self, eventFile):
+        self.eventFile = eventFile
+        self.buttonHandler = None
+        self.joyLeftHandler = None
+        self.joyRightHandler = None
+
+    def setButtonHandler(self, buttonHandler):
+        self.buttonHandler = buttonHandler
+
+    def setJoyLeftHandler(self, joyLeftHandler):
+        self.joyLeftHandler = joyLeftHandler
+
+    def setJoyRightHandler(self, joyRightHandler):
+        self.joyRightHandler = joyRightHandler
+
+    def startLoop(self):
+        FORMAT = 'llHHI'
+        EVENT_SIZE = struct.calcsize(FORMAT)
+        with open(self.eventFile, 'rb') as infile:
+            lx, ly, rx, ry = 0, 0, 0, 0
+            while True:
+                event = infile.read(EVENT_SIZE)
+                _, _, t, c, v = struct.unpack(FORMAT, event)
+                if t == 1 and v == 1:
+                    # button pressed:
+                    if self.buttonHandler:
+                        if not self.buttonHandler(c):
+                            return
+                if t == 3:
+                    if c == 0 and self.joyLeftHandler:
+                        # left stick & horizontal:
+                        lx = v - 32768
+                        self.joyLeftHandler(lx, ly)
+                    elif c == 1 and self.joyLeftHandler:
+                        # left stick & vertical:
+                        ly = v - 32768
+                        self.joyLeftHandler(lx, ly)
+                    elif c == 3 and self.joyRightHandler:
+                        # right stick & horizontal:
+                        rx = v - 32768
+                        self.joyRightHandler(rx, ry)
+                    elif c == 4 and self.joyRightHandler:
+                        # right stick & vertical:
+                        ry = v - 32768
+                        self.joyRightHandler(rx, ry)

+ 103 - 0
base/18micropython/tank/main.py

@@ -0,0 +1,103 @@
+#!/usr/bin/env pybricks-micropython
+
+import struct, threading
+
+from pybricks import ev3brick as brick
+from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, InfraredSensor, UltrasonicSensor, GyroSensor)
+from pybricks.parameters import (Port, Stop, Direction, Button, Color, SoundFile, ImageFile, Align)
+from pybricks.tools import print, wait, StopWatch
+from pybricks.robotics import DriveBase
+
+from devices import detectJoystick
+from joystick import JoyStick, BUTTON_A, BUTTON_X
+
+SPEED = 100
+STEERING = 90
+
+STATUS_STOPPED = 0
+STATUS_FORWARD = 1
+STATUS_BACKWARD = 2
+STATUS_STEERING = 3
+
+COLORS = (None, Color.GREEN, Color.RED, Color.YELLOW)
+
+class Driver():
+    def __init__(self, leftMotor, rightMotor, diameter, axle):
+        self.driver = DriveBase(leftMotor, rightMotor, diameter, axle)
+        self.x = 0
+        self.y = 0
+        self.speed = 0
+        self.steering = 0
+
+    def drive(self, speed, steering):
+        self.speed = speed
+        self.steering = steering
+        if self.speed == 0:
+            self.driver.stop()
+        else:
+            self.driver.drive(self.speed, self.steering)
+
+class Robot():
+    def __init__(self, leftMotor, rightMotor, topMotor, diameter, axle, maxSpeed=300, maxSteering=180, port=Port.S4):
+        self.driver = Driver(leftMotor, rightMotor, diameter, axle)
+        self.cannon = topMotor
+        self.ultrasonic = UltrasonicSensor(port)
+        self.speedStep = 32767 // maxSpeed
+        self.steeringStep = 32767 // maxSteering
+        self.active = True
+
+    def drive(self, x, y):
+        # map y (-32768 ~ +32767) to speed (+maxSpeed ~ -maxSpeed):
+        speed = -y // self.speedStep
+        # map x (-32768 ~ +32767) to steering (-maxSteering ~ +maxSteering):
+        steering = x // self.steeringStep
+        self.driver.drive(speed, steering)
+
+    def target(self, x):
+        self.cannon.run(-x // 327)
+
+    def fire(self):
+        brick.sound.file('cannon.wav')
+
+    def inactive(self):
+        self.active = False
+        self.drive(0, 0)
+        brick.sound.beep()
+
+def autoStopLoop(robot):
+    while robot.active:
+        if robot.ultrasonic.distance() < 200:
+            robot.drive(0, 0)
+        wait(100)
+
+def main():
+    brick.sound.beep()
+    joystickEvent = detectJoystick(['Controller'])
+    if joystickEvent:
+        robot = Robot(Motor(Port.D), Motor(Port.A), Motor(Port.B), 55, 200)
+        t = threading.Thread(target=autoStopLoop, args=(robot,))
+        t.start()
+
+        def onButtonPressed(code):
+            if code == BUTTON_X:
+                robot.inactive()
+                return False
+            if code == BUTTON_A:
+                robot.fire()
+            return True
+
+        def onLeftJoyChanged(x, y):
+            robot.drive(x, y)
+
+        def onRightJoyChanged(x, y):
+            robot.target(x)
+
+        joystick = JoyStick(joystickEvent)
+        joystick.setButtonHandler(onButtonPressed)
+        joystick.setJoyLeftHandler(onLeftJoyChanged)
+        joystick.setJoyRightHandler(onRightJoyChanged)
+        joystick.startLoop()
+    else:
+        brick.sound.beep()
+
+main()

+ 9 - 0
base/1function/call_func.py

@@ -0,0 +1,9 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+x = abs(100)
+y = abs(-20)
+print(x, y)
+print('max(1, 2, 3) =', max(1, 2, 3))
+print('min(1, 2, 3) =', min(1, 2, 3))
+print('sum([1, 2, 3]) =', sum([1, 2, 3]))

+ 34 - 0
base/1function/def_func.py

@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import math
+
+def my_abs(x):
+    if not isinstance(x, (int, float)):
+        raise TypeError('bad operand type')
+    if x >= 0:
+        return x
+    else:
+        return -x
+
+def move(x, y, step, angle=0):
+    nx = x + step * math.cos(angle)
+    ny = y - step * math.sin(angle)
+    return nx, ny
+
+n = my_abs(-20)
+print(n)
+
+x, y = move(100, 100, 60, math.pi / 6)
+print(x, y)
+
+# TypeError: bad operand type:
+# my_abs('123')
+
+def addSum(x,y):
+    sum = x + y ;
+    return sum;
+
+# 多个返回值就过个返回和接收
+count = addSum(1,2);
+print(count);

+ 32 - 0
base/1function/kw_args.py

@@ -0,0 +1,32 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+def print_scores(**kw):
+    print('      Name  Score')
+    print('------------------')
+    for name, score in kw.items():
+        print('%10s  %d' % (name, score))
+    print()
+
+print_scores(Adam=99, Lisa=88, Bart=77)
+
+data = {
+    'Adam Lee': 99,
+    'Lisa S': 88,
+    'F.Bart': 77
+}
+
+print_scores(**data)
+
+def print_info(name, *, gender, city='Beijing', age):
+    print('Personal Info')
+    print('---------------')
+    print('   Name: %s' % name)
+    print(' Gender: %s' % gender)
+    print('   City: %s' % city)
+    print('    Age: %s' % age)
+    print()
+
+print_info('Bob', gender='male', age=20)
+print_info('Lisa', gender='female', city='Shanghai', age=18)
+print_info("1","1",1,"d",12);

+ 24 - 0
base/1function/recur.py

@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# 利用递归函数计算阶乘
+# N! = 1 * 2 * 3 * ... * N
+def fact(n):
+    if n == 1:
+        return 1
+    return n * fact(n-1)
+
+print('fact(1) =', fact(1))
+print('fact(5) =', fact(5))
+print('fact(10) =', fact(10))
+
+# 利用递归函数移动汉诺塔:
+def move(n, a, b, c):
+    if n == 1:
+        print('move', a, '-->', c)
+    else:
+        move(n-1, a, c, b)
+        move(1, a, b, c)
+        move(n-1, b, a, c)
+
+move(4, 'A', 'B', 'C')

+ 15 - 0
base/1function/var_args.py

@@ -0,0 +1,15 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+def hello(greeting, *args):
+    if (len(args)==0):
+        print('%s!' % greeting)
+    else:
+        print('%s, %s!' % (greeting, ', '.join(args)))
+
+hello('Hi') # => greeting='Hi', args=()
+hello('Hi', 'Sarah') # => greeting='Hi', args=('Sarah')
+hello('Hello', 'Michael', 'Bob', 'Adam') # => greeting='Hello', args=('Michael', 'Bob', 'Adam')
+
+names = ('Bart', 'Lisa')
+hello('Hello', *names) # => greeting='Hello', args=('Bart', 'Lisa')

+ 31 - 0
base/2advance/do_generator.py

@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+s = (x * x for x in range(5))
+print(s)
+for x in s:
+    print(x)
+
+def fib(max):
+    n, a, b = 0, 0, 1
+    while n < max:
+        yield b
+        a, b = b, a + b
+        n = n + 1
+    return 'done'
+
+f = fib(10)
+print('fib(10):', f)
+for x in f:
+    print(x)
+
+# call generator manually:
+g = fib(5)
+while 1:
+    try:
+        x = next(g)
+        print('g:', x)
+    except StopIteration as e:
+        print('Generator return value:', e.value)
+        break
+

+ 64 - 0
base/2advance/do_iter.py

@@ -0,0 +1,64 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from collections.abc import Iterable, Iterator
+
+def g():
+    yield 1
+    yield 2
+    yield 3
+
+print('Iterable? [1, 2, 3]:', isinstance([1, 2, 3], Iterable))
+print('Iterable? \'abc\':', isinstance('abc', Iterable))
+print('Iterable? 123:', isinstance(123, Iterable))
+print('Iterable? g():', isinstance(g(), Iterable))
+
+print('Iterator? [1, 2, 3]:', isinstance([1, 2, 3], Iterator))
+print('Iterator? iter([1, 2, 3]):', isinstance(iter([1, 2, 3]), Iterator))
+print('Iterator? \'abc\':', isinstance('abc', Iterator))
+print('Iterator? 123:', isinstance(123, Iterator))
+print('Iterator? g():', isinstance(g(), Iterator))
+
+# iter list:
+print('for x in [1, 2, 3, 4, 5]:')
+for x in [1, 2, 3, 4, 5]:
+    print(x)
+
+print('for x in iter([1, 2, 3, 4, 5]):')
+for x in iter([1, 2, 3, 4, 5]):
+    print(x)
+
+print('next():')
+it = iter([1, 2, 3, 4, 5])
+print(next(it))
+print(next(it))
+print(next(it))
+print(next(it))
+print(next(it))
+
+d = {'a': 1, 'b': 2, 'c': 3}
+
+# iter each key:
+print('iter key:', d)
+for k in d.keys():
+    print('key:', k)
+
+# iter each value:
+print('iter value:', d)
+for v in d.values():
+    print('value:', v)
+
+# iter both key and value:
+print('iter item:', d)
+for k, v in d.items():
+    print('item:', k, v)
+
+# iter list with index:
+print('iter enumerate([\'A\', \'B\', \'C\']')
+for i, value in enumerate(['A', 'B', 'C']):
+    print(i, value)
+
+# iter complex list:
+print('iter [(1, 1), (2, 4), (3, 9)]:')
+for x, y in [(1, 1), (2, 4), (3, 9)]:
+    print(x, y)

+ 12 - 0
base/2advance/do_listcompr.py

@@ -0,0 +1,12 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+print([x * x for x in range(1, 11)])
+print([x * x for x in range(1, 11) if x % 2 == 0])
+print([m + n for m in 'ABC' for n in 'XYZ'])
+
+d = {'x': 'A', 'y': 'B', 'z': 'C' }
+print([k + '=' + v for k, v in d.items()])
+
+L = ['Hello', 'World', 'IBM', 'Apple']
+print([s.lower() for s in L])

+ 16 - 0
base/2advance/do_slice.py

@@ -0,0 +1,16 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
+
+print('L[0:3] =', L[0:3])
+print('L[:3] =', L[:3])
+print('L[1:3] =', L[1:3])
+print('L[-2:] =', L[-2:])
+
+R = list(range(100))
+print('R[:10] =', R[:10])
+print('R[-10:] =', R[-10:])
+print('R[10:20] =', R[10:20])
+print('R[:10:2] =', R[:10:2])
+print('R[::5] =', R[::5])

+ 29 - 0
base/2advance/do_yield.py

@@ -0,0 +1,29 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+def each_ascii(s):
+    for ch in s:
+        yield ord(ch)
+    return '%s chars' % len(s)
+
+def yield_from(s):
+    r = yield from each_ascii(s)
+    print(r)
+
+def main():
+    for x in each_ascii('abc'):
+        print(x) # => 'a', 'b', 'c'
+    it = each_ascii('xyz')
+    try:
+        while True:
+            print(next(it)) # => 'x', 'y', 'z'
+    except StopIteration as s:
+        print(s.value) # => '3 chars'
+
+    # using yield from in main() will change main() from function to generator:
+    # r = yield from each_ascii('hello')
+
+    for ch in yield_from('hello'):
+        pass
+
+main()

+ 33 - 0
base/3functional/decorator.py

@@ -0,0 +1,33 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import functools
+
+def log(func):
+    @functools.wraps(func)
+    def wrapper(*args, **kw):
+        print('call %s():' % func.__name__)
+        return func(*args, **kw)
+    return wrapper
+
+@log
+def now():
+    print('2015-3-25')
+
+now()
+
+def logger(text):
+    def decorator(func):
+        @functools.wraps(func)
+        def wrapper(*args, **kw):
+            print('%s %s():' % (text, func.__name__))
+            return func(*args, **kw)
+        return wrapper
+    return decorator
+
+@logger('DEBUG')
+def today():
+    print('2015-3-25')
+
+today()
+print(today.__name__)

+ 14 - 0
base/3functional/do_filter.py

@@ -0,0 +1,14 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+def is_odd(n):
+    return n % 2 == 1
+
+L = range(100)
+
+print(list(filter(is_odd, L)))
+
+def not_empty(s):
+    return s and s.strip()
+
+print(list(filter(not_empty, ['A', '', 'B', None, 'C', '  '])))

+ 7 - 0
base/3functional/do_map.py

@@ -0,0 +1,7 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+def f(x):
+    return x * x
+
+print(list(map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])))

+ 9 - 0
base/3functional/do_partial.py

@@ -0,0 +1,9 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import functools
+
+int2 = functools.partial(int, base=2)
+
+print('1000000 =', int2('1000000'))
+print('1010101 =', int2('1010101'))

+ 61 - 0
base/3functional/do_reduce.py

@@ -0,0 +1,61 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from functools import reduce
+
+CHAR_TO_INT = {
+    '0': 0,
+    '1': 1,
+    '2': 2,
+    '3': 3,
+    '4': 4,
+    '5': 5,
+    '6': 6,
+    '7': 7,
+    '8': 8,
+    '9': 9
+}
+
+def str2int(s):
+    ints = map(lambda ch: CHAR_TO_INT[ch], s)
+    return reduce(lambda x, y: x * 10 + y, ints)
+
+print(str2int('0'))
+print(str2int('12300'))
+print(str2int('0012345'))
+
+CHAR_TO_FLOAT = {
+    '0': 0,
+    '1': 1,
+    '2': 2,
+    '3': 3,
+    '4': 4,
+    '5': 5,
+    '6': 6,
+    '7': 7,
+    '8': 8,
+    '9': 9,
+    '.': -1
+}
+
+def str2float(s):
+    nums = map(lambda ch: CHAR_TO_FLOAT[ch], s)
+    point = 0
+    def to_float(f, n):
+        nonlocal point
+        if n == -1:
+            point = 1
+            return f
+        if point == 0:
+            return f * 10 + n
+        else:
+            point = point * 10
+            return f + n / point
+    return reduce(to_float, nums, 0.0)
+
+print(str2float('0'))
+print(str2float('123.456'))
+print(str2float('123.45600'))
+print(str2float('0.1234'))
+print(str2float('.1234'))
+print(str2float('120.0034'))

+ 15 - 0
base/3functional/do_sorted.py

@@ -0,0 +1,15 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from operator import itemgetter
+
+L = ['bob', 'about', 'Zoo', 'Credit']
+
+print(sorted(L))
+print(sorted(L, key=str.lower))
+
+students = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
+
+print(sorted(students, key=itemgetter(0)))
+print(sorted(students, key=lambda t: t[1]))
+print(sorted(students, key=itemgetter(1), reverse=True))

+ 29 - 0
base/3functional/prime_numbers.py

@@ -0,0 +1,29 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+def main():
+    for n in primes():
+        if n < 1000:
+            print(n)
+        else:
+            break
+
+def _odd_iter():
+    n = 1
+    while True:
+        n = n + 2
+        yield n
+
+def _not_divisible(n):
+    return lambda x: x % n > 0
+
+def primes():
+    yield 2
+    it = _odd_iter()
+    while True:
+        n = next(it)
+        yield n
+        it = filter(_not_divisible(n), it)
+
+if __name__ == '__main__':
+    main()

+ 46 - 0
base/3functional/return_func.py

@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+def lazy_sum(*args):
+    def sum():
+        ax = 0
+        for n in args:
+            ax = ax + n
+        return ax
+    return sum
+
+f = lazy_sum(1, 2, 4, 5, 7, 8, 9)
+print(f)
+print(f())
+
+# why f1(), f2(), f3() returns 9, 9, 9 rather than 1, 4, 9?
+def count():
+    fs = []
+    for i in range(1, 4):
+        def f():
+             return i * i
+        fs.append(f)
+    return fs
+
+f1, f2, f3 = count()
+
+print(f1())
+print(f2())
+print(f3())
+
+# fix:
+def count():
+    fs = []
+    def f(n):
+        def j():
+            return n * n
+        return j
+    for i in range(1, 4):
+        fs.append(f(i))
+    return fs
+
+f1, f2, f3 = count()
+
+print(f1())
+print(f2())
+print(f3())

+ 36 - 0
base/4module/hello.py

@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+' a test module '
+
+__author__ = 'Michael Liao'
+
+import sys
+
+from bs4 import BeautifulSoup  # 网页解析html文档
+import re  # 正则表达式
+import urllib.request
+import urllib.error  # 指定url获取网页数据
+import sqlite3  # 数据存储
+
+
+def test():
+    args = sys.argv
+    if len(args) == 1:
+        print('Hello, world!')
+    elif len(args) == 2:
+        print('Hello, %s!' % args[1])
+    else:
+        print('Too many arguments!')
+
+    path = "http://wwww.baidu.com"
+    askUrl(path)
+
+
+def askUrl(path):
+    response = urllib.request.urlopen(path)
+    print(response.read().decode("utf-8"))
+
+
+if __name__ == '__main__':
+    test()

+ 67 - 0
base/5oop_basic/animals.py

@@ -0,0 +1,67 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+class Animal(object):
+    def run(self):
+        print('Animal is running...')
+
+
+class Dog(Animal):
+    def run(self):
+        print('Dog is running...')
+
+
+class Cat(Animal):
+    def run(self):
+        print('Cat is running...')
+
+
+def run_twice(animal):
+    animal.run()
+    animal.run()
+
+
+a = Animal()
+d = Dog()
+c = Cat()
+
+print('a is Animal?', isinstance(a, Animal))
+print('a is Dog?', isinstance(a, Dog))
+print('a is Cat?', isinstance(a, Cat))
+
+print('d is Animal?', isinstance(d, Animal))
+print('d is Dog?', isinstance(d, Dog))
+print('d is Cat?', isinstance(d, Cat))
+
+run_twice(c)
+
+
+class Human(object):
+    age = 0
+
+    def __init__(self):
+        age = 1
+        self.name = "人类"
+        print('人活着')
+
+    def eat(self):
+        print('人吃饭饭')
+
+
+class Man(Human):
+    def eat(self):
+        print('男人吃饭饭')
+
+    def zhuanqian(self):
+        print('男人赚钱')
+
+
+def manDo(human):
+    human.eat()
+
+
+man = Man()
+man.eat()
+man.zhuanqian()
+
+manDo(man)

+ 25 - 0
base/5oop_basic/attrs.py

@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+class MyObject(object):
+
+    def __init__(self):
+        self.x = 9
+
+    def power(self):
+        return self.x * self.x
+
+obj = MyObject()
+
+print('hasattr(obj, \'x\') =', hasattr(obj, 'x')) # 有属性'x'吗?
+print('hasattr(obj, \'y\') =', hasattr(obj, 'y')) # 有属性'y'吗?
+setattr(obj, 'y', 19) # 设置一个属性'y'
+print('hasattr(obj, \'y\') =', hasattr(obj, 'y')) # 有属性'y'吗?
+print('getattr(obj, \'y\') =', getattr(obj, 'y')) # 获取属性'y'
+print('obj.y =', obj.y) # 获取属性'y'
+
+print('getattr(obj, \'z\') =',getattr(obj, 'z', 404)) # 获取属性'z',如果不存在,返回默认值404
+
+f = getattr(obj, 'power') # 获取属性'power'
+print(f)
+print(f())

+ 30 - 0
base/5oop_basic/get_instance.py

@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+class Animal(object):
+    pass
+
+class Dog(Animal):
+    pass
+
+class Husky(Dog):
+    pass
+
+a = Animal()
+d = Dog()
+h = Husky()
+
+print('check a = Animal()...')
+print('isinstance(a, Animal) =', isinstance(a, Animal))
+print('isinstance(a, Dog) =', isinstance(a, Dog))
+print('isinstance(a, Husky) =', isinstance(a, Husky))
+
+print('check d = Dog()...')
+print('isinstance(d, Animal) =', isinstance(d, Animal))
+print('isinstance(d, Dog) =', isinstance(d, Dog))
+print('isinstance(d, Husky) =', isinstance(d, Husky))
+
+print('check h = Husky()...')
+print('isinstance(h, Animal) =', isinstance(h, Animal))
+print('isinstance(h, Dog) =', isinstance(h, Dog))
+print('isinstance(h, Husky) =', isinstance(h, Husky))

+ 14 - 0
base/5oop_basic/get_type.py

@@ -0,0 +1,14 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# type()
+
+print('type(123) =', type(123))
+print('type(\'123\') =', type('123'))
+print('type(None) =', type(None))
+print('type(abs) =', type(abs))
+
+import types
+
+print('type(\'abc\')==str?', type('abc')==str)
+

+ 35 - 0
base/5oop_basic/protected_student.py

@@ -0,0 +1,35 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+class Student(object):
+
+    def __init__(self, name, score):
+        self.__name = name
+        self.__score = score
+
+    def get_name(self):
+        return self.__name
+
+    def get_score(self):
+        return self.__score
+
+    def set_score(self, score):
+        if 0 <= score <= 100:
+            self.__score = score
+        else:
+            raise ValueError('bad score')
+
+    def get_grade(self):
+        if self.__score >= 90:
+            return 'A'
+        elif self.__score >= 60:
+            return 'B'
+        else:
+            return 'C'
+
+bart = Student('Bart Simpson', 59)
+print('bart.get_name() =', bart.get_name())
+bart.set_score(60)
+print('bart.get_score() =', bart.get_score())
+
+print('DO NOT use bart._Student__name:', bart._Student__name)

+ 29 - 0
base/5oop_basic/student.py

@@ -0,0 +1,29 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+class Student(object):
+
+    def __init__(self, name, score):
+        self.name = name
+        self.score = score
+
+    def print_score(self):
+        print('%s: %s' % (self.name, self.score))
+
+    def get_grade(self):
+        if self.score >= 90:
+            return 'A'
+        elif self.score >= 60:
+            return 'B'
+        else:
+            return 'C'
+
+bart = Student('Bart Simpson', 59)
+lisa = Student('Lisa Simpson', 87)
+
+print('bart.name =', bart.name)
+print('bart.score =', bart.score)
+bart.print_score()
+
+print('grade of Bart:', bart.get_grade())
+print('grade of Lisa:', lisa.get_grade())

+ 13 - 0
base/6oop_advance/create_class_on_the_fly.py

@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+def fn(self, name='world'): # 先定义函数
+    print('Hello, %s.' % name)
+
+Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class
+
+h = Hello()
+print('call h.hello():')
+h.hello()
+print('type(Hello) =', type(Hello))
+print('type(h) =', type(h))

+ 77 - 0
base/6oop_advance/orm.py

@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+' Simple ORM using metaclass '
+
+class Field(object):
+
+    def __init__(self, name, column_type):
+        self.name = name
+        self.column_type = column_type
+
+    def __str__(self):
+        return '<%s:%s>' % (self.__class__.__name__, self.name)
+
+class StringField(Field):
+
+    def __init__(self, name):
+        super(StringField, self).__init__(name, 'varchar(100)')
+
+class IntegerField(Field):
+
+    def __init__(self, name):
+        super(IntegerField, self).__init__(name, 'bigint')
+
+class ModelMetaclass(type):
+
+    def __new__(cls, name, bases, attrs):
+        if name=='Model':
+            return type.__new__(cls, name, bases, attrs)
+        print('Found model: %s' % name)
+        mappings = dict()
+        for k, v in attrs.items():
+            if isinstance(v, Field):
+                print('Found mapping: %s ==> %s' % (k, v))
+                mappings[k] = v
+        for k in mappings.keys():
+            attrs.pop(k)
+        attrs['__mappings__'] = mappings # 保存属性和列的映射关系
+        attrs['__table__'] = name # 假设表名和类名一致
+        return type.__new__(cls, name, bases, attrs)
+
+class Model(dict, metaclass=ModelMetaclass):
+
+    def __init__(self, **kw):
+        super(Model, self).__init__(**kw)
+
+    def __getattr__(self, key):
+        try:
+            return self[key]
+        except KeyError:
+            raise AttributeError(r"'Model' object has no attribute '%s'" % key)
+
+    def __setattr__(self, key, value):
+        self[key] = value
+
+    def save(self):
+        fields = []
+        params = []
+        args = []
+        for k, v in self.__mappings__.items():
+            fields.append(v.name)
+            params.append('?')
+            args.append(getattr(self, k, None))
+        sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
+        print('SQL: %s' % sql)
+        print('ARGS: %s' % str(args))
+
+# testing code:
+
+class User(Model):
+    id = IntegerField('id')
+    name = StringField('username')
+    email = StringField('email')
+    password = StringField('password')
+
+u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
+u.save()

+ 12 - 0
base/6oop_advance/special_call.py

@@ -0,0 +1,12 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+class Student(object):
+    def __init__(self, name):
+        self.name = name
+
+    def __call__(self):
+        print('My name is %s.' % self.name)
+
+s = Student('Michael')
+s()

+ 21 - 0
base/6oop_advance/special_getattr.py

@@ -0,0 +1,21 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+class Student(object):
+
+    def __init__(self):
+        self.name = 'Michael'
+
+    def __getattr__(self, attr):
+        if attr=='score':
+            return 99
+        if attr=='age':
+            return lambda: 25
+        raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)
+
+s = Student()
+print(s.name)
+print(s.score)
+print(s.age())
+# AttributeError: 'Student' object has no attribute 'grade'
+print(s.grade)

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.