diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..c735cbc
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,7 @@
+# top-most EditorConfig file
+root = true
+
+# all files
+[*]
+indent_style = space
+indent_size = 4
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..26d3f99
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+# vscode files
+.vscode/
+
+# python bytecode
+**/__pycache__/
+
+# test email infos
+Email/pop3.txt
+Email/smtp.txt
+
+# sqlite3 database files
+SQL/*.db
\ No newline at end of file
diff --git a/AsynchronousIO/AiohttpServer.py b/AsynchronousIO/AiohttpServer.py
new file mode 100644
index 0000000..7a77c78
--- /dev/null
+++ b/AsynchronousIO/AiohttpServer.py
@@ -0,0 +1,28 @@
+'''
+async web application.
+'''
+
+import asyncio
+
+from aiohttp import web
+
+async def index(request):
+ await asyncio.sleep(0.5)
+ return web.Response(body=b'
Index ', content_type='text/html')
+
+async def hello(request):
+ await asyncio.sleep(0.5)
+ text = 'hello, %s! ' % request.match_info['name']
+ return web.Response(body=text.encode('utf-8'), content_type='text/html')
+
+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()
\ No newline at end of file
diff --git a/AsynchronousIO/AsyncIoHello.py b/AsynchronousIO/AsyncIoHello.py
new file mode 100644
index 0000000..f634e41
--- /dev/null
+++ b/AsynchronousIO/AsyncIoHello.py
@@ -0,0 +1,14 @@
+import asyncio
+import threading
+
+@asyncio.coroutine
+def hello(n):
+ print(f'hello,world! from {threading.currentThread()}, n = {n}')
+ r = yield from asyncio.sleep(1)
+ print(f'hello,again! from {threading.currentThread()}, n = {n}')
+
+loop = asyncio.get_event_loop()
+# execute coroutine
+tasks = [hello(1), hello(2)]
+loop.run_until_complete(asyncio.wait(tasks))
+loop.close()
\ No newline at end of file
diff --git a/AsynchronousIO/AsyncIoWget2.py b/AsynchronousIO/AsyncIoWget2.py
new file mode 100644
index 0000000..e7a0429
--- /dev/null
+++ b/AsynchronousIO/AsyncIoWget2.py
@@ -0,0 +1,21 @@
+import asyncio
+
+async def wget(host):
+ print('wget %s...' % host)
+ connect = asyncio.open_connection(host, 80) # connect is a coroutine
+ reader, writer = await connect
+ header = 'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' % host
+ writer.write(header.encode('utf-8'))
+ await writer.drain()
+ while True:
+ line = await 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()
\ No newline at end of file
diff --git a/AsynchronousIO/AsyncioWget.py b/AsynchronousIO/AsyncioWget.py
new file mode 100644
index 0000000..39ba0d2
--- /dev/null
+++ b/AsynchronousIO/AsyncioWget.py
@@ -0,0 +1,22 @@
+import asyncio
+
+@asyncio.coroutine
+def wget(host):
+ print('wget %s...' % host)
+ connect = asyncio.open_connection(host, 80) # connect is a coroutine
+ 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()
\ No newline at end of file
diff --git a/AsynchronousIO/CoroutineTest.py b/AsynchronousIO/CoroutineTest.py
new file mode 100644
index 0000000..2c3e73d
--- /dev/null
+++ b/AsynchronousIO/CoroutineTest.py
@@ -0,0 +1,22 @@
+def consumer():
+ print("hello")
+ r = ''
+ while True:
+ n = yield r # get message through return value of yield
+ if not n:
+ return
+ print('[CONSUMER] Consuming %s...' % n)
+ r = '200 OK'
+
+def produce(c):
+ c.send(None) # start generator, will first call generator, print hello, then run to first yield
+ 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() # close generator
+
+c = consumer()
+produce(c)
\ No newline at end of file
diff --git a/Basics/BuiltInFuncs.py b/Basics/BuiltInFuncs.py
new file mode 100644
index 0000000..e56bf75
--- /dev/null
+++ b/Basics/BuiltInFuncs.py
@@ -0,0 +1,427 @@
+# -*- coding: utf-8 -*-
+
+# test suite
+count = 0
+category = ""
+def myprint(*args, **kwargs):
+ global count
+ count += 1
+ print(f"{count} {category} : ", *args, **kwargs)
+
+def test(s):
+ global category
+ category = s
+
+# abs
+test("abs")
+myprint(abs(-10))
+
+# all any bool
+test("all any bool")
+myprint(all([]), all(()), all([0, 1]), all([True, False]))
+myprint(any([]), any([[]]), any([0, 1]), any([True, False]))
+myprint(bool([]), bool([[]]), bool([0, 1]), bool([True, False]))
+
+class Student:
+ def __repr__(self) -> str:
+ return b'asf\xe4\xb8\xad\xe6\x96\x87'.decode("utf-8")
+ def __bool__(self):
+ return False
+
+# ascii
+test("ascii repr")
+myprint(ascii(Student()), repr(Student()))
+
+# bin : to 0b10101... binary format string
+test("bin")
+myprint(bin(-10), bin(0xFFFF), type(bin(1)), f"{100:#b}")
+
+# class bool : __bool__() return False or __len__() return 0 -> False, else -> True
+test("bool")
+myprint(bool(Student()))
+
+# class bytearray([source[, encoding[, errors]]]), mutable version of bytes
+test("bytearray")
+myprint(bytearray(b"asdf\xff"), type(bytearray()))
+
+# class bytes([source[, encoding[, errors]]]), immutable version of bytearray
+test("bytes")
+myprint(bytes(b"asdf\xff"), type(bytes()))
+
+# callable(object), can call(the class of the object have __call__()) -> True, else -> False, a class is a callable and calling will return a new instance
+test("callable")
+myprint(callable(int), callable(callable), callable(lambda x : x * x))
+
+# chr(i) return a single character string of code point i
+# ord(c) inversion of chr, return code point of a single character string
+test("chr ord")
+myprint(chr(8364), ord(chr(8346)))
+
+# @classmethod, decorate a method to a class method, will pass the class itself at first argument implicitly
+class Person:
+ @classmethod
+ def f(cls, *args, **kwargs):
+ myprint("call function f in calss ", cls.__name__)
+ def f2():
+ pass
+test("@classmethod")
+Person.f()
+myprint(Person.f, Person.f2)
+
+# class complex
+test("complex")
+myprint(complex(1, 2), complex("1+2j"), complex())
+myprint(complex(1, 2.5) + complex(1, 3) - complex(1.5, 4))
+myprint(type(complex()))
+
+class MyComplex:
+ def __init__(self, a, b):
+ self._a = a
+ self._b = b
+ # if do not have __complex__, will call __float__ __index__ in order
+ # def __complex__(self):
+ # return complex(self._a, self._b)
+ def __float__(self):
+ return (self._a ** 2 + self._b ** 2) ** 0.5
+myprint(complex(MyComplex(1, 3)))
+
+# delattr(object, name) : delete attribute
+# setattr(object, name, value)
+# getattr(object, name[, default])
+# hasattr(object, name)
+test("delattr setattr getattr hasattr")
+delattr(MyComplex, "__float__")
+try:
+ myprint(complex(MyComplex(1, 3)))
+except Exception as e:
+ myprint(e)
+
+def special_complex(self):
+ return complex(self._a, self._b)
+setattr(MyComplex, "__complex__", special_complex)
+myprint(complex(MyComplex(1, 3)))
+myprint(getattr(MyComplex, "__complex__", None) == special_complex)
+myprint(hasattr(MyComplex, "justamethod"))
+
+# calss dict
+test("dict")
+myprint(dict((x, str(x)) for x in range(10)))
+
+# dir([object]) : return name list of current domain or specific object
+test("dir")
+myprint(dir())
+myprint(dir(MyComplex))
+myprint(dir(test))
+
+# divmod(a, b) : get (result of division, remainder), (a // b, a % b) for int, and (match.floor(a/b), a % b) for float usually
+test("divmod")
+myprint(divmod(10.5, 3.1))
+
+# enumerate(iterable, start=0)
+test("enumerate")
+myprint([t for t in enumerate(["hello", "world"], 10)])
+
+# eval(expression[, globals[, locals]]), eval as a python expression
+test("eval")
+a = 1
+myprint(eval("1+2+a"))
+
+# exec(object[, globals[, locals]])
+test("exec")
+exec("b = 1")
+myprint(b)
+
+# filter(function, iterable)
+test("filter")
+myprint([x for x in filter(lambda x : x % 2 == 0, [1, 2, 3, 4])])
+# supplement : itertools.filterfalse()
+from array import array
+from io import TextIOWrapper
+from itertools import filterfalse
+myprint([x for x in filterfalse(lambda x : x % 2 == 0, [1, 2, 3, 4])])
+
+# class float([x]), return float number from number or string
+# for normal object: call __float__, if not exist, call __index__ instead, else fail
+test("float")
+myprint(float(" -1234.5 "))
+myprint(float("1.4e300"))
+myprint(float("-InfInItY")) # case non-sensitive
+myprint(float("+InF"))
+class MyFloat:
+ def __init__(self, val) -> None:
+ self._val = val
+ def __float__(self):
+ return self._val * 10
+class MyInt:
+ def __init__(self, val):
+ self._val = int(val)
+ def __index__(self):
+ return self._val * 10
+
+myprint(float(MyFloat(10.0)))
+myprint(float(MyInt(100)))
+
+# format()
+test("format")
+myprint(format(101, "#X"))
+
+# class frozenset([iterable]), as inner elemnt of set, if there is a nested set
+# class set([iterable])
+test("set frozenset")
+myprint({frozenset([1, 2]), frozenset([2, 3])})
+myprint(frozenset([1, 2, 3, 3, 4]))
+myprint(set([1, 2, 3, 4]))
+
+# globals() : dict of global symbol table
+test("globals")
+myprint(globals())
+
+# hash(object) : get hash value, call object.__hash__()
+test("hash")
+myprint(hash(object))
+myprint(hash(1))
+myprint(hash(1.10))
+
+# hex(x) : integer to hex lower-case string with 0x prefix
+test("hex")
+myprint(hex(255))
+myprint(hex(46543468463545343))
+
+# id(object) : id of a oejct, unique and constant in it's lifetime
+test('id')
+myprint(id(object))
+myprint(id(1))
+myprint(id(1 + 2))
+
+# input([prompt]) : write prompt to stdout and read one line from input
+test("input")
+# a = input("input a integer: ")
+# myprint(a)
+
+# class int([x])
+# class int(x, base=10)
+# __int__, __index__, __trunc__
+test('int')
+myprint(int("10", base = 8))
+myprint(int(10.07))
+myprint(int())
+
+# RTTI
+# isinstance(object, classinfo)
+# issubclass(class, classinfo)
+class Person:
+ pass
+class Student(Person):
+ pass
+test("isinstance issubclass")
+myprint(isinstance(Student(), (Student, object)))
+myprint(isinstance(1, object))
+myprint(issubclass(Student, Person))
+myprint(issubclass(int, object))
+
+# iter(object[, sentinel]) : __iter__(), __getitem__()
+test("iter")
+myprint(iter([]))
+myprint(iter({}))
+myprint(iter({1, 2}))
+
+# len(s) : __len__
+test("len")
+myprint(len([]))
+myprint(len({1, 2}))
+
+# locals() : local symbol table, do not modify
+test("locals")
+myprint(locals())
+myprint(globals() == locals()) # True
+class Person:
+ name = "Kim"
+ age = 10
+ def __init__(self, *args, **kwargs):
+ pass
+ myprint(locals())
+
+# map(function, iterable, ...)
+from itertools import starmap
+test("map")
+myprint([elem for elem in map(lambda x, y: x * y, [x for x in range(10)], [y for y in range(0, -10, -1)])])
+myprint([elem for elem in starmap(lambda x, y: x * y, [(x, -x) for x in range(10)])]) # element for func are tuples
+
+# max(iterable, *[, key, default])
+# max(arg1, arg2, *args[, key])
+# min(iterable, *[, key, default])¶
+# min(arg1, arg2, *args[, key])
+test('max min')
+myprint(max([1, 2, 3], key = lambda x : -x))
+myprint(max(1, 2, 3))
+
+# class memoryview(object) : memory view of an object
+test("memoryview")
+myprint(memoryview(b"\xffasdfl")[1])
+
+# next(iterator[, default]) : call __next__ of iterator, return defualt at end, if no defualt, raise StopIteration
+test("next")
+try:
+ it = iter([1, 2, 3, 4])
+ while True:
+ myprint(next(it))
+except StopIteration as e:
+ myprint(e.value)
+
+# class object
+test('object')
+myprint(object())
+
+# oct(x) : to octal number with a 0o prefix
+test("oct")
+myprint(oct(0xff), oct(10), oct(8), oct(0o77))
+
+# open(file, mode='r', buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None) : open file
+test("open")
+with open("BuiltInFuncs.py", mode = "r") as f:
+ from functools import reduce
+ myprint(reduce(lambda x, y: x + 1, f, 0)) # get line of current file
+
+# pow(base, exp[, mod])
+test("pow")
+myprint(pow(10, 3, 512))
+myprint(pow(10, 100)) # equals to 10 ** 100
+
+# class property(fget=None, fset=None, fdel=None, doc=None)
+test("property")
+class C:
+ def __init__(self):
+ self._x = None
+ def getx(self):
+ return self._x
+ def setx(self, value):
+ self._x = value
+ def delx(self):
+ del self._x
+ x = property(getx, setx, delx, "I'm the 'x' property.") # defoine a delegate property
+c = C()
+c.x = 10
+myprint(c.x)
+del c.x
+# myprint(c.x) # will failed
+
+# or use as decorator, equals to definition of C
+class D:
+ def __init__(self):
+ self._x = None
+ @property
+ def x(self):
+ """I'm the 'x' property.""" # doc
+ return self._x
+ @x.setter
+ def x(self, value):
+ self._x = value
+ @x.deleter
+ def x(self):
+ del self._x
+d = D()
+d.x = 10
+myprint(d.x)
+del d.x
+# myprint(d.x)
+
+# reversed(seq) : __reversed__ or (__len__ and __getitem__)
+test("reversed")
+myprint([x for x in reversed(range(10))])
+
+# round(number[, ndigits])
+test("round")
+myprint(round(2.346, 2))
+
+# class slice(stop)
+# class slice(start, stop[, step])
+test("slice")
+myprint(slice(10))
+myprint(slice(0, 10, 2))
+myprint([x for x in range(10)][slice(0, 10, 2)])
+
+# sorted(iterable, *, key=None, reverse=False)
+test("sorted")
+import random
+L = [x for x in range(100)]
+random.shuffle(L)
+myprint(L)
+myprint(sorted(L, key = lambda x : -x, reverse = True))
+
+# @staticmethod, change a method to static method, will not pass class or object implicitly
+# just like static method in java/method
+test("@staticmethod")
+class A:
+ @staticmethod
+ def f(x):
+ return x * x
+ def f2(x): # just like f
+ return -x
+myprint(A.f) #
+myprint(A.f(20))
+myprint(A.f2) #
+myprint(A.f2(-10))
+
+# class str(object='')
+# class str(object=b'', encoding='utf-8', errors='strict')
+test("str")
+myprint(str("hello"))
+myprint(str(b"\x7fasdf"))
+
+# sum(iterable, /, start=0)
+test("sum")
+myprint(sum([x for x in range(11)], 0))
+myprint(sum([[x for x in range(10)], [x for x in range(30, 40)], [10, 100, 1000, 10000]], [])) # to one dim array
+
+# class super([type[, object-or-type]])
+# return a proxy object, delegate a method call to father or brother class
+test("super")
+class A:
+ def foo(self):
+ myprint("foo in A")
+class B(A):
+ def foo(self):
+ myprint("foo in B")
+class C(A):
+ def foo(self):
+ myprint("foo in C")
+class D(B, C):
+ def foo1(self):
+ super().foo() # B, super(D, self).foo()
+ def foo2(self):
+ super(B, self).foo() # C
+ def foo3(self):
+ super(C, self).foo() # A
+ def foo4(self):
+ super(C, D).foo(self) # A
+ def foo5(self):
+ super(B, D).foo(self) # C
+
+myprint(D.__mro__) # D -> B -> C -> A
+D().foo() # B
+D().foo1() # B
+D().foo2() # C
+D().foo3() # A
+D().foo4() # A
+D().foo5() # C
+
+# class tuple([iterable])
+test("tuple")
+myprint(tuple([1, 2, 3]))
+
+# class type(object), get type of object
+# class type(name, bases, dict, **kwds), return a new type
+test("type")
+myprint(type(1))
+Coord = type("Coord", (object, ), dict(x = 1, y = 2, res = lambda x, y : x + y))
+myprint(Coord)
+myprint(Coord.x, Coord.y, Coord.res(1, 2))
+
+# zip(*iterables, strict=False)
+test("zip")
+myprint(list(zip([x for x in range(10)], [chr(a) for a in range(ord('a'), ord('z'), 2)], [10 ** x for x in range(10)])))
+x, y = zip(*zip([1, 2, 3], [4, 5, 6])) # disassemable a tuple list to seperate tuple
+myprint(x, y)
+
+# __import__(name, globals=None, locals=None, fromlist=(), level=0)
+# import statement will call
\ No newline at end of file
diff --git a/Basics/ControlFlows.py b/Basics/ControlFlows.py
new file mode 100644
index 0000000..7794978
--- /dev/null
+++ b/Basics/ControlFlows.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+
+# if elif else
+a = False
+b = True
+if a:
+ print("a is True")
+elif b:
+ print("b is True")
+else:
+ print("a and b are False")
+
+
+# while
+n = 1
+sum = 0
+while (n < 10):
+ sum += n
+ n += 1
+print(sum)
+
+# for
+sum = 0
+for x in (1, 2, 3):
+ sum += x
+print(sum)
+
+
+sum = 0
+for x in range(0, 100, 10):
+ sum += x
+ c = 1
+print(sum)
+print(x)
+print(c) # scope ?
+
+s = ""
+for x in range(ord('a'), ord('z') + 1):
+ s += chr(x)
+print(s)
diff --git a/Basics/Function.py b/Basics/Function.py
new file mode 100644
index 0000000..8005354
--- /dev/null
+++ b/Basics/Function.py
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+
+def myabs(a):
+ if a < 0:
+ return -a
+ else:
+ return a
+
+print(myabs(-10))
+
+def swap(x, y):
+ return x, y # return as a tuple
+
+x = 1
+y = 2
+x, y = swap(x, y)
+print(x, y)
+(x, y) = (y, x)
+print(x, y)
+
+import math
+print(math.sin(math.pi / 4))
+
+# default arguments
+def power(x, n = 2):
+ res = 1
+ while n > 0:
+ res *= x
+ n -= 1
+ return res
+print(power(10))
+print(power(10, 3))
+
+# variable arguments
+def printargs(*args):
+ print(args)
+
+printargs()
+printargs((1, 2), 10)
+printargs(1, 2, 3)
+printargs(*[1, 2, 3], 10, 100)
+printargs([1, 2, 3])
+
+# keyword arguments
+def person(name, age, *, city, job):
+ print(f"name: {name}, age: {age}, city: {city}, jog: {job}")
+
+person("kim", 18, job = "waiter", city = "beijing")
+
+def person2(name, age, *args, city, job):
+ print(f"name: {name}, age: {age}, city: {city}, jog: {job}")
+
+person2("kim", 18, job = "waiter", city = "beijing")
+
+# named keyword arguments
+def person3(name, age, **args):
+ print(f"name: {name}, age: {age}, args: {args}")
+
+person3("kim", 18, job = "waiter", city = "beijing")
+person3("kim", 18, **{'job': 'waiter', 'city': 'beijing'})
+
+# combine multiple arguments
+def foo(a, b, c = 0, *args, d = 10, **kw):
+ print(a, b, c, args, d, kw)
+
+foo(1, 2)
+foo(1, 2, 3)
+foo(1, 2, 3, 100)
+foo(1, 2, 3, 100)
+foo(1, d = 10, b = 2, c = 3, args = {1, 2}, kw = {"hello": 10})
+
+# recursive
+def fib(n):
+ return fibonacci(n, 0, 1)
+
+def fibonacci(n, a, b):
+ if (n == 0):
+ return a
+ else:
+ return fibonacci(n-1, b, a+b)
+
+import sys
+sys.setrecursionlimit(2000)
+print(fib(1990))
\ No newline at end of file
diff --git a/Basics/String.py b/Basics/String.py
new file mode 100644
index 0000000..537dc56
--- /dev/null
+++ b/Basics/String.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+
+# string encoding
+print('\u4e2d\u6587') # unicode escape
+print(chr(74562))
+print(ord("𒍂"))
+print("asf中文".encode("utf-8"))
+print(b'asf\xe4\xb8\xad\xe6\x96\x87'.decode("utf-8")) # bytes
+
+# string format
+name = "michael"
+age = 18
+print("name = %s, age = %2d, %% {{ }}" % (name, age))
+
+# format()
+print("name = {0}, age = {1:2.3f} {{ }}".format(name, age))
+print(f"name = {name}, age = {age:2.3f} {{ }}")
diff --git a/Basics/VarAndTypes.py b/Basics/VarAndTypes.py
new file mode 100644
index 0000000..258edd4
--- /dev/null
+++ b/Basics/VarAndTypes.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+
+# int
+print(100_100)
+print(0xFFFF_FFFF)
+print(0xffff_ffff_ffff_ffff)
+print(0xffff_ffff_ffff_ffff_ffff)
+print(1234123423421324132341233541251134323145231)
+
+# float
+print(1.324e10)
+print(1.234213e300)
+print(1.1321e303)
+print(1.132423e309) # inf IEEE 754 64 bit
+print(1.324e135434134356143_131435143541313135135135145) # inf
+
+# string
+print("hello")
+print(r"\\\r\t\nhello") # raw string
+print("\r\nhello\ttest")
+print("""\
+ hello
+ world
+ asdfas
+ asdf
+ shit
+""")
+
+# bool
+print(True)
+print(False)
+print(True and False)
+print(True or False)
+
+# none
+print(None)
+
+# variable
+name = "nephren"
+# dynamic type, reference type
+a = "ABC"
+b = a
+b = "abc"
+print(a, b)
+
+# 中文标识符
+你好 = "你好"
+print(你好)
\ No newline at end of file
diff --git a/BuiltInModules/Base64.py b/BuiltInModules/Base64.py
new file mode 100644
index 0000000..dda3730
--- /dev/null
+++ b/BuiltInModules/Base64.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+
+import base64
+
+print(base64.b64encode(b'helloworld'))
+print(base64.b64decode(b'aGVsbG93b3JsZA=='))
+
+# safe url encoding and decoding
+print(base64.b64encode(b'\xff\xff\xff', altchars=b"-_"))
+print(base64.b64decode(b'____', altchars=b"-_"))
+
+# euqals to
+print(base64.urlsafe_b64encode(b'\xff\xff\xff'))
+print(base64.urlsafe_b64decode(b'____'))
\ No newline at end of file
diff --git a/BuiltInModules/Collections.py b/BuiltInModules/Collections.py
new file mode 100644
index 0000000..59cf60b
--- /dev/null
+++ b/BuiltInModules/Collections.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+
+from collections import defaultdict, namedtuple, deque
+from typing import ChainMap, Counter, OrderedDict
+
+# namedtuple
+Point = namedtuple('Point', ['x', 'y'])
+p = Point(10, 20)
+print(p, p.x, p.y, p[0], p[1])
+
+# deque
+q = deque([1, 2, 3, 'x'])
+print(q.pop())
+q.append(10) # return None
+print(q.popleft())
+q.appendleft(10)
+print(q)
+
+# defaultdict
+d = defaultdict(lambda: 'N/A')
+print(d[10], d['nonexistkey'])
+d[10] = 100
+print(d)
+
+# OrderedDict
+d = OrderedDict()
+d['x'] = 1
+d['y'] = 2
+print(d.keys())
+print(d)
+
+# ChainMap
+c = ChainMap(d, {'x' : 200})
+print(c['x'])
+
+# Counter
+c = Counter()
+for ch in "hello":
+ c[ch] = c[ch] + 1
+print(c)
\ No newline at end of file
diff --git a/BuiltInModules/ContextLib.py b/BuiltInModules/ContextLib.py
new file mode 100644
index 0000000..47afcb9
--- /dev/null
+++ b/BuiltInModules/ContextLib.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+
+# with statement
+class Query(object):
+ def __init__(self, name) -> None:
+ self.name = name
+ def __enter__(self):
+ print('Begin')
+ return self
+ def __exit__(self, exc_type, exc_value, traceback):
+ if exc_type:
+ print('Error')
+ else:
+ print('End')
+ def query(self):
+ print(f"Query info about {self.name}")
+
+with Query('Bob') as q:
+ q.query()
+
+
+from contextlib import contextmanager
+
+class Query2(object):
+ def __init__(self, name):
+ self.name = name
+ def query(self):
+ print(f"Query info about {self.name}")
+
+@contextmanager
+def create_query(name):
+ print("Begin")
+ q = Query2(name)
+ yield q
+ print('End')
+
+with create_query('Bob') as q:
+ q.query()
+
+# application auto generate xml tag
+@contextmanager
+def tag(name):
+ print(f"<{name}>")
+ yield
+ print(f"{name}>")
+
+with tag("h1"):
+ print("hello")
\ No newline at end of file
diff --git a/BuiltInModules/DateTime.py b/BuiltInModules/DateTime.py
new file mode 100644
index 0000000..6b97875
--- /dev/null
+++ b/BuiltInModules/DateTime.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+
+from datetime import date, datetime, timedelta, timezone
+import re
+
+now = datetime.now()
+print(now)
+print(type(now)) #
+print(datetime.fromtimestamp(datetime.now().timestamp()))
+
+# epoch time: 1970.01.01 UTC+0 zone 00::00
+# timstamp: epoch time to now, unit is seconds, a float point, precision to us
+print(datetime.now().timestamp())
+
+# construct specific datetime
+dt = datetime(2021, 10, 14, 0, 0, 1)
+print(dt)
+print(datetime.fromtimestamp(dt.timestamp())) # time in current zone
+print(datetime.utcfromtimestamp(dt.timestamp())) # UTC+0:00 time
+
+# user input string to datetime
+print(datetime.strptime("2021-1-1 10:00:01", "%Y-%m-%d %H:%M:%S")) # do not have a zone
+
+# datetime to string
+print(datetime.now().strftime('%a, %b %d %H:%M'))
+
+# calculate time interval
+print(datetime.now() - datetime(2021, 10, 14, 0, 0, 1))
+print(datetime.now() - timedelta(1, 1, 1))
+print(timedelta(10, 10, 10) - timedelta(1, 1, 1))
+
+# timezone
+# UTC+08:00 zone:
+print(timezone(timedelta(hours=8)))
+print(datetime.now().replace(tzinfo=timezone(timedelta(hours=7))).timestamp()) # enforce to change timezone, do not change date and time
+
+# change timezone
+print(datetime.utcnow())
+print(datetime.now().astimezone())
+print(datetime.now().astimezone(timezone(timedelta(hours=8))).timestamp())
+
+# timestamp from datetime and timezone string
+def to_timestamp(dt_str, tz_str):
+ dt = datetime.strptime(dt_str, "%Y-%m-%d %H:%M:%S")
+ m = re.match(r"(UTC)([-+]\d{1,2}):(\d{2})", tz_str)
+ dt = dt.replace(tzinfo=timezone(timedelta(hours=int(m.group(2)))))
+ return dt.timestamp()
+
+t1 = to_timestamp('2015-6-1 08:10:30', 'UTC+7:00')
+assert t1 == 1433121030.0, t1
+t2 = to_timestamp('2015-5-31 16:10:30', 'UTC-09:00')
+assert t2 == 1433121030.0, t2
\ No newline at end of file
diff --git a/BuiltInModules/HTMLParserTest.py b/BuiltInModules/HTMLParserTest.py
new file mode 100644
index 0000000..56e3205
--- /dev/null
+++ b/BuiltInModules/HTMLParserTest.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+
+# HTMLParser
+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('')
+
+ def handle_entityref(self, name):
+ print('&%s;' % name)
+
+ def handle_charref(self, name):
+ print('%s;' % name)
+
+parser = MyHTMLParser()
+parser.feed('''
+
+
+
+ Some html HTML tutorial... END
+''')
\ No newline at end of file
diff --git a/BuiltInModules/HashLib.py b/BuiltInModules/HashLib.py
new file mode 100644
index 0000000..1a683b5
--- /dev/null
+++ b/BuiltInModules/HashLib.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+
+import hashlib
+
+# hashlib
+
+# md5
+# result: 128bit byte, usually denoted with a hex charcter string which length is 32
+md5 = hashlib.md5()
+print(md5)
+md5.update('how to use md5 in python hashlib?'.encode('utf-8'))
+print(md5.hexdigest())
+
+# call update multiple times, equals to call it one time
+md5 = hashlib.md5()
+md5.update('how to use md5 in '.encode('utf-8'))
+md5.update('python hashlib?'.encode('utf-8'))
+print(md5.hexdigest())
+
+md5 = hashlib.md5()
+md5.update('how to use md5 in python hashlib'.encode('utf-8')) # modify one character, will cause a totally different result
+print(md5.hexdigest())
+
+
+# sha1
+# same as md5
+# result: 160 bit, hex character which length is 40
+sha1 = hashlib.sha1()
+sha1.update('how to use sha1 in '.encode('utf-8'))
+sha1.update('python hashlib?'.encode('utf-8'))
+print(sha1.hexdigest())
+
+
+# sha256 and sha512
+sha256 = hashlib.sha256()
+sha256.update('how to use md5 in python hashlib?'.encode('utf-8'))
+print(sha256.hexdigest())
+
+sha512 = hashlib.sha512()
+sha512.update('how to use md5 in python hashlib?'.encode('utf-8'))
+print(sha512.hexdigest())
\ No newline at end of file
diff --git a/BuiltInModules/Hmac.py b/BuiltInModules/Hmac.py
new file mode 100644
index 0000000..bf804b1
--- /dev/null
+++ b/BuiltInModules/Hmac.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+
+# hashing for message authentication
+import hmac
+import hashlib
+message = b"hello,world!"
+key = b"sercet"
+h = hmac.new(key, message, digestmod="MD5")
+print(h.hexdigest())
+
+h = hmac.new(key, message, digestmod="SHA1")
+print(h.hexdigest())
+
+h = hmac.new(key, message, digestmod="SHA256")
+print(h.hexdigest())
+
+h = hmac.new(key, message, digestmod="SHA512")
+print(h.hexdigest())
\ No newline at end of file
diff --git a/BuiltInModules/Itertools.py b/BuiltInModules/Itertools.py
new file mode 100644
index 0000000..5c156e4
--- /dev/null
+++ b/BuiltInModules/Itertools.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+
+import itertools
+
+# infinite iterators: count, cycle, repeat
+naturals = itertools.count(10, 10)
+for i, n in enumerate(naturals):
+ if (i >= 10):
+ break
+ print(n)
+
+cs = itertools.cycle([1, 2, 3])
+for i,n in enumerate(cs):
+ if (i >= 10):
+ break
+ print(n)
+
+riter = itertools.repeat('A', 10)
+for elem in riter:
+ print(elem)
+
+# chain
+for elem in itertools.chain([1, 2, 3], ('x', 'y', 'z'), (x for x in range(10) if x % 2 == 0)):
+ print(elem)
+
+# groupby
+for key, group in itertools.groupby('AAaaBBbbCccC', lambda c : c.upper()):
+ print(key, list(group))
+
+# calculate PI
+def pi(N):
+ oddnums = itertools.count(1, 2) # 1, 3, 5, 7, ...
+ ns = itertools.takewhile(lambda x : x <= 2*N-1, oddnums) # 1, 3, ..., 2*N-1
+ nss = map(lambda x : (-1)**(x//2)*4/x, ns)
+ return sum(nss) # PI = (1 - 1/3 + 1/5 + ...) * 4
+
+print(pi(10))
+print(pi(100))
+print(pi(1000))
+print(pi(10000))
\ No newline at end of file
diff --git a/BuiltInModules/Struct.py b/BuiltInModules/Struct.py
new file mode 100644
index 0000000..24872c2
--- /dev/null
+++ b/BuiltInModules/Struct.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+
+import struct
+
+# > big endian
+# < little endian
+# I 32-bit unsinged integer
+# https://docs.python.org/zh-cn/3/library/struct.html#format-characters
+print(struct.pack('>I', 10234))
+print(struct.unpack('>I', b"\x00\x00'\xfa"))
\ No newline at end of file
diff --git a/BuiltInModules/UrlLib.py b/BuiltInModules/UrlLib.py
new file mode 100644
index 0000000..2b272d7
--- /dev/null
+++ b/BuiltInModules/UrlLib.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+
+from urllib import request
+
+with request.urlopen('https://baidu.com') 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'))
+
+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'))
\ No newline at end of file
diff --git a/BuiltInModules/XML.py b/BuiltInModules/XML.py
new file mode 100644
index 0000000..e8c1f39
--- /dev/null
+++ b/BuiltInModules/XML.py
@@ -0,0 +1,27 @@
+# -*- 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'''
+
+ Python
+ Ruby
+
+'''
+
+handler = DefaultSaxHandler()
+parser = ParserCreate()
+parser.StartElementHandler = handler.start_element
+parser.EndElementHandler = handler.end_element
+parser.CharacterDataHandler = handler.char_data
+parser.Parse(xml)
\ No newline at end of file
diff --git a/Collections/Collections.py b/Collections/Collections.py
new file mode 100644
index 0000000..355590e
--- /dev/null
+++ b/Collections/Collections.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+
+# list
+print("list============================")
+l = list([1, 3, 4])
+print([1, 3, 4][2])
+print(l)
+
+print(len([1, 3, 4]))
+
+# tuple
+print("tuple============================")
+print((1, 2, "hello"))
+t = ()
+print(t) # empty tuple
+print(())
+print((1)) # just 1
+print((1, )) # tuple with one element
+
+a = 1
+b = 2
+t = (a, b, "hello")
+b = 3
+print(t) # keep (1, 2, "hello")
+
+# range
+print("range============================")
+print(range(10)) # 0 to 9 by step 1
+print(list(range(10))) # 0 to 9 by step 1
+print(range(1, 5))
+print(list(range(1, 5)))
+print(range(1, 100, 10))
+print(list(range(1, 100, 10)))
+
+
+# dict
+print("dict============================")
+d = {"hello": 1, "world": 2}
+print(d)
+print(d["hello"])
+print(d.get("yes", -1))
+print(d.get("yes"))
+d["yes"] = 100
+d.pop("hello")
+print(d)
+
+
+# set
+print("set============================")
+s = {1, 3, 100, "hello", "yes"}
+print(s)
+s = set([1, 3, 100, "hello"])
+print(s)
+s.add(1024)
+s.remove("hello")
+print(s)
+print("hello" in s)
+
+s.add((1, 2, 3))
+print(s)
\ No newline at end of file
diff --git a/Collections/Generator.py b/Collections/Generator.py
new file mode 100644
index 0000000..b7e756d
--- /dev/null
+++ b/Collections/Generator.py
@@ -0,0 +1,71 @@
+# -*- coding -*-
+
+from re import I
+from typing import Iterable, Iterator
+
+# list comprehension
+print(list(range(100)))
+print([n for n in range(100) if n % 10 + n // 10 == 9])
+print([x*x for x in range(10) if x % 2 == 0])
+
+print([m + n for m in "ABC" for n in "XYZ"])
+
+L1 = ['Hello', 'World', 18, 'Apple', None]
+L2 = [s.lower() for s in L1 if isinstance(s, str)]
+print(L2)
+
+# generator
+g = (x * x for x in range(10) if x % 2 == 0)
+
+def fib(max):
+ n, a, b = 0, 0, 1
+ while (n < max):
+ yield a
+ a, b = b, a + b
+ n += 1
+ return "done"
+
+print([x for x in fib(10)])
+
+g = fib(10)
+while True:
+ try:
+ print(next(g))
+ except StopIteration as e:
+ print("Generator return value: ", e.value)
+ break
+
+# pascal triangles
+def triangles(max):
+ n, L = 0, [1]
+ while n < max:
+ yield L.copy()
+ L.append(0)
+ L = [L[i] + L[i-1] for i in range(len(L))]
+ n += 1
+ return "done"
+
+g = triangles(10)
+res = [elem for elem in g]
+print(res)
+print(isinstance(g, Iterator)) # True
+print(isinstance(g, Iterable)) # True
+
+print(isinstance([1, 2], Iterable)) # True
+print(isinstance([1, 2], Iterator)) # False
+print(isinstance(iter([1, 2]), Iterator)) # True, collections to Iterator
+
+# the natrue of for
+for x in [1, 2, 3, 4, 5]:
+ print(x)
+
+# equals to
+it = iter([1, 2, 3, 4, 5])
+while True:
+ try:
+ x = next(it)
+ print(x)
+ except StopIteration:
+ break
+
+print(triangles)
\ No newline at end of file
diff --git a/Collections/Iteration.py b/Collections/Iteration.py
new file mode 100644
index 0000000..e07e7ae
--- /dev/null
+++ b/Collections/Iteration.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+
+# use for to iterate collections, aka range for
+
+from collections.abc import Iterable
+
+
+for x in [12, 124, 1234]:
+ print(x)
+
+for x in (1, 2, 3):
+ print(x)
+
+for x in {1, 2, 3, 1, 4}:
+ print(x)
+
+d = {"hello": 10, 2 : 100, "world": "yes"}
+for k in d:
+ print(k)
+for k, v in d.items():
+ print(k, v)
+for kv in d.items():
+ print(kv)
+for v in d.values():
+ print(v)
+
+print(isinstance([1, 2, 3], Iterable))
+print(isinstance((1, 2, 3), Iterable))
+print(isinstance({1, 2, 3}, Iterable))
+print(isinstance({1:2}, Iterable))
+print(isinstance(range(100), Iterable))
+print(isinstance('abc', Iterable))
+
+a = [1, 2, "hello"]
+for i, val in enumerate(a):
+ print(i, val)
+
+for i, pair in enumerate(d.items()):
+ print(i, pair)
+
+for x in range(100):
+ print(x)
\ No newline at end of file
diff --git a/Collections/Slicing.py b/Collections/Slicing.py
new file mode 100644
index 0000000..fae2687
--- /dev/null
+++ b/Collections/Slicing.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+# slicing of collections: tuple and list
+l = list(range(101))
+print(l[:])
+print(l[:10])
+print(l[10:20])
+print(l[::5])
+print(l[-20:]) # last 20 elements
+print(l[-1:]) # last element
+print(l[70:40:-1])
+
+# slicing of string
+s = "abcdefghijklmnopqrstuvwxyz"
+print(s[10:20:2])
+print(s[2:])
+print(s)
+
+print(range(0, 10)[:50:2])
+print(list(range(1, 100)[::2]))
+print(range(0, 10))
\ No newline at end of file
diff --git a/Concurrent/DistributedProcess/TaskMaster.py b/Concurrent/DistributedProcess/TaskMaster.py
new file mode 100644
index 0000000..5205eed
--- /dev/null
+++ b/Concurrent/DistributedProcess/TaskMaster.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+# TaskMaster.py
+
+# distributed multi process, task manager
+import random, time, queue
+from multiprocessing.managers import BaseManager
+
+# queue that send tasks
+task_queue = queue.Queue()
+# queue that receive tasks
+result_queue = queue.Queue()
+
+class QueueManager(BaseManager):
+ pass
+
+def get_task_q():
+ return task_queue
+def get_result_q():
+ return result_queue
+
+if __name__ == '__main__':
+ # register two queues to network
+ QueueManager.register('get_task_queue', callable=get_task_q)
+ QueueManager.register('get_result_queue', callable=get_result_q)
+ # bind to port 5000, authentication code abc
+ manager = QueueManager(address=('127.0.0.1', 5000), authkey=b'abc')
+
+ # start the manager
+ manager.start()
+ # get Queue object through network
+ task = manager.get_task_queue()
+ result = manager.get_result_queue()
+
+ # put some tasks to task queue
+ for i in range(10):
+ n = random.randint(0, 10000)
+ print(f"Put task {n}")
+ task.put(n)
+
+ # read result from result queue
+ print("Try get results...")
+ for i in range(10):
+ try:
+ r = result.get(timeout=10)
+ print(f"Result : {r}")
+ except queue.Empty:
+ print("The queue is empty...")
+
+ # shudown manager
+ manager.shutdown()
+ print("Master exit.")
\ No newline at end of file
diff --git a/Concurrent/DistributedProcess/TaskWorker.py b/Concurrent/DistributedProcess/TaskWorker.py
new file mode 100644
index 0000000..e3f3115
--- /dev/null
+++ b/Concurrent/DistributedProcess/TaskWorker.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+# TaskWorker.py
+
+# distributed multi process, task wroker
+import time, sys, queue
+from multiprocessing.managers import BaseManager
+
+class QueueManager(BaseManager):
+ pass
+
+if __name__ == '__main__':
+ QueueManager.register('get_task_queue')
+ QueueManager.register('get_result_queue')
+ server_addr = "127.0.0.1"
+ print(f"Connect to server {server_addr}...")
+ m = QueueManager(address=(server_addr, 5000), authkey=b'abc')
+ # connect manager obejct to server
+ m.connect()
+ # get Queue from network
+ task = m.get_task_queue()
+ result = m.get_result_queue()
+ # get task from task queue, calculate and put result to result queue
+ for i in range(10):
+ try:
+ n = task.get(timeout=1)
+ print(f"Run task {n} * {n}...")
+ r = f"{n} * {n} = {n * n}"
+ time.sleep(1)
+ result.put(r)
+ except queue.Empty:
+ print("task queue is empty.")
+
+ # end wrok process
+ print("Worker exit.")
diff --git a/Concurrent/MultiProcessing.py b/Concurrent/MultiProcessing.py
new file mode 100644
index 0000000..85e22b0
--- /dev/null
+++ b/Concurrent/MultiProcessing.py
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+
+import os
+print(f"porcess {os.getpid()} start ...")
+
+# only works on *nix(Linux/Unix/MacOS)
+pid = os.fork()
+if pid == 0:
+ print(f"This is child process {os.getpid()}, and parent is {os.getppid()}.")
+else:
+ print(f"This is parent process {os.getpid()}, and just created a child process {pid}")
diff --git a/Concurrent/ProcessCommunication.py b/Concurrent/ProcessCommunication.py
new file mode 100644
index 0000000..df93c69
--- /dev/null
+++ b/Concurrent/ProcessCommunication.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+
+from multiprocessing import Process, Queue
+import os, time, random
+
+# write to queue
+def write(q):
+ print(f"Process to write : {os.getpid()}")
+ for value in ['A', 'B', 'C']:
+ print(f"Put {value} in queue...")
+ q.put(value)
+ time.sleep(random.random())
+
+# read from queue
+def read(q : Queue):
+ print(f"Process to read : {os.getpid()}")
+ while True:
+ value = q.get(True) # block = True
+ print(f"Get value {value} from queue.")
+
+if __name__ == "__main__":
+ # create queue and pass to subprocess
+ q = Queue()
+ pw = Process(target=write, args=(q,))
+ pr = Process(target=read, args=(q,))
+ # start subprocess to write
+ pw.start()
+ # start subprocess to read
+ pr.start()
+ # wait pw end
+ pw.join()
+ # pr is infinite loop, can not end by itself, must be terminated.
+ pr.terminate()
diff --git a/Concurrent/ProcessCrossPlatfrom.py b/Concurrent/ProcessCrossPlatfrom.py
new file mode 100644
index 0000000..d54ebf7
--- /dev/null
+++ b/Concurrent/ProcessCrossPlatfrom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from multiprocessing import Process
+import os
+
+# subprocess will execute
+def run_proc(name):
+ print(f"Run child process {name} ({os.getpid()})...")
+
+if __name__ == "__main__":
+ print(f"Parent process {os.getpid()}.")
+ p = Process(target = run_proc, args = ('test', ))
+ print("Child process will start.")
+ p.start()
+ p.join()
+ print("Child process end.")
\ No newline at end of file
diff --git a/Concurrent/ProcessPool.py b/Concurrent/ProcessPool.py
new file mode 100644
index 0000000..ba7414e
--- /dev/null
+++ b/Concurrent/ProcessPool.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+from multiprocessing import Pool, Process
+import os, time, random
+
+def long_time_task(name):
+ print(f"Run task {name} ({os.getpid()})...")
+ start = time.time()
+ time.sleep(random.random() * 3)
+ end = time.time()
+ print(f"Task {name} runs {end-start:0.2f} seconds.")
+
+if __name__ == "__main__":
+ print(f"Parent process {os.getpid()}.")
+ p = Pool(4)
+ for i in range(5):
+ p.apply_async(long_time_task, args = (i, ))
+ print("Waiting for all subprocess done...")
+ p.close()
+ p.join()
+ print("All subprocess done.")
\ No newline at end of file
diff --git a/Concurrent/SubProcess.py b/Concurrent/SubProcess.py
new file mode 100644
index 0000000..52bde26
--- /dev/null
+++ b/Concurrent/SubProcess.py
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+
+import subprocess
+
+p = subprocess.Popen(['python', '-c', 'print("hello,world!")'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+out, err = p.communicate()
+print(out.decode("utf-8"), err.decode("utf-8"))
+print("exit code: ", p.returncode)
\ No newline at end of file
diff --git a/Concurrent/ThreadLocal.py b/Concurrent/ThreadLocal.py
new file mode 100644
index 0000000..6988715
--- /dev/null
+++ b/Concurrent/ThreadLocal.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+
+import threading
+
+class Student():
+ def __init__(self, name) -> None:
+ self.name = name
+ def __str__(self) -> str:
+ return f"Student {self.name}"
+
+# create global ThreadLocal object
+local_shool = threading.local()
+
+def process_student():
+ std = local_shool.student
+ print(f"hello, {std} in thread {threading.current_thread().name}")
+
+def process_thread(name):
+ local_shool.student = Student(name) # bind thread local object to atrribute of global threading.local object
+ process_student()
+
+if __name__ == "__main__":
+ t1 = threading.Thread(target=process_thread, args=("Alice",), name="Thread-A")
+ t2 = threading.Thread(target=process_thread, args=("Bob",), name="Thread-B")
+ t1.start()
+ t2.start()
+ t1.join()
+ t2.join()
\ No newline at end of file
diff --git a/Concurrent/Threading.py b/Concurrent/Threading.py
new file mode 100644
index 0000000..99ca74a
--- /dev/null
+++ b/Concurrent/Threading.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+
+import time, threading
+
+def loop():
+ print(f"thread {threading.current_thread().name} is running...")
+ for i in range(5):
+ print(f"thread {threading.current_thread().name} >>> {i}")
+ time.sleep(1)
+ print(f"thread {threading.current_thread().name} end.")
+
+if __name__ == "__main__":
+ print(f"thread {threading.current_thread().name} is running...")
+ t = threading.Thread(target=loop, name="LoopThread")
+ t.start()
+ t.join()
+ print(f"thread {threading.current_thread().name} end.")
\ No newline at end of file
diff --git a/Email/POP3.py b/Email/POP3.py
new file mode 100644
index 0000000..f35204e
--- /dev/null
+++ b/Email/POP3.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+
+import poplib
+from email.parser import Parser
+from email.header import decode_header
+from email.utils import parseaddr
+
+# utils to parse mail content
+def decode_str(s):
+ value, charset = decode_header(s)[0]
+ if charset:
+ value = value.decode(charset)
+ return value
+
+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
+
+# print mail info recursively
+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))
+
+
+if __name__ == '__main__':
+ # input email
+ email = input('Email: ')
+ password = input('Password: ')
+ pop3_server = input('POP3 server: ')
+
+ # connect to POP3 server
+ server = poplib.POP3(pop3_server)
+ server.set_debuglevel(1)
+ print(server.getwelcome().decode('utf-8'))
+
+ # authentication
+ server.user(email)
+ server.pass_(password)
+
+ # email number and space
+ print('Message: %s, Size: %s', server.stat())
+
+ # get numbers of all mails
+ resp, mails, octets = server.list()
+ print(mails)
+
+ # get newest mail
+ index = len(mails)
+ resp, lines, octets = server.retr(index)
+
+ # get raw content of mail
+ msg_content = b'\r\n'.join(lines).decode('utf-8')
+ # parse mail content
+ msg = Parser().parsestr(msg_content)
+
+ server.quit()
+
+ # print mail
+ print_info(msg)
diff --git a/Email/SMTP.py b/Email/SMTP.py
new file mode 100644
index 0000000..fcbb7e2
--- /dev/null
+++ b/Email/SMTP.py
@@ -0,0 +1,32 @@
+# -*- coding:utf-8 -*-
+
+from email.mime.text import MIMEText
+from email.header import Header
+from email.utils import parseaddr, formataddr
+
+def _format_addr(s):
+ name, addr = parseaddr(s)
+ return formataddr((Header(name, 'utf-8').encode(), addr))
+
+# input email and passwd
+from_addr = input('From: ')
+password = input('password: ')
+to_addr = input('To: ')
+
+# input SMTP server address
+smtp_server = input('SMTP server: ')
+
+# plain text email
+msg = MIMEText("hello, send by Python...", 'Plain', 'utf-8')
+msg['From'] = _format_addr('暗之恶魔 <%s>' % from_addr) # 发件人
+msg['To'] = _format_addr('光之使者 <%s>' % to_addr) # 收件人
+msg['Subject'] = Header("接受地狱的审判吧!", 'utf-8').encode() # 主题
+
+# send to MTA
+import smtplib
+server = smtplib.SMTP(smtp_server, 25)
+server.starttls()
+server.set_debuglevel(1) # print interactive info with the server
+server.login(from_addr, password)
+server.sendmail(from_addr, [to_addr], msg.as_string())
+server.quit()
\ No newline at end of file
diff --git a/ErrorsAndDebug/Debug.py b/ErrorsAndDebug/Debug.py
new file mode 100644
index 0000000..72c4910
--- /dev/null
+++ b/ErrorsAndDebug/Debug.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+
+
+import logging
+import pdb
+logging.basicConfig(level = logging.INFO, filename="Debug.log", encoding="utf-8", filemode="w")
+
+# assert
+def test1():
+ n = 11
+ assert n == 10, "n is not 10"
+ print(n)
+
+# logging
+def Fib(n, a, b):
+ logging.info(f"call Fib({n}, {a}, {b})")
+ # pdb.set_trace()
+ if (n == 0):
+ return a
+ else:
+ return Fib(n-1, b, a + b)
+
+def test2():
+ n = Fib(10, 0, 1)
+ print(n)
+
+
+if __name__ == "__main__":
+ # test1()
+ test2()
\ No newline at end of file
diff --git a/ErrorsAndDebug/TryExcept.py b/ErrorsAndDebug/TryExcept.py
new file mode 100644
index 0000000..85e0317
--- /dev/null
+++ b/ErrorsAndDebug/TryExcept.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+
+import logging
+def f():
+ try:
+ a = 10 / 0
+ except ValueError as e:
+ print("except :", e)
+ raise
+ except ZeroDivisionError as e:
+ print('except: ', e)
+ raise
+ finally:
+ print("finally...")
+
+def main():
+ try:
+ f()
+ except Exception as e:
+ logging.exception(e) # log error and continue to execute
+
+if __name__ == "__main__":
+ main()
+
+ print("END")
diff --git a/ErrorsAndDebug/UnitTest.py b/ErrorsAndDebug/UnitTest.py
new file mode 100644
index 0000000..8c261ab
--- /dev/null
+++ b/ErrorsAndDebug/UnitTest.py
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+
+class Dict(dict):
+ """
+ >>> d1 = Dict()
+ >>> d1['x'] = 100
+ >>> d1.x
+ 100
+ >>> d1.y = 200
+ >>> d1['y']
+ 200
+ >>> d2 = Dict(a=1, b=2, c='3')
+ >>> d2.c
+ '3'
+ >>> d2['empty']
+ Traceback (most recent call last):
+ ...
+ KeyError: 'empty'
+ >>> d2.empty
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'Dict' object has no attribute 'empty'
+ """
+ def __init__(self, **kw):
+ super().__init__(**kw)
+ def __getattr__(self, key):
+ try:
+ return self[key]
+ except:
+ raise AttributeError(f"'Dict' object has no attribute '{key}'")
+ def __setattr__(self, key, value):
+ self[key] = value
+
+import unittest
+class DictTest(unittest.TestCase):
+ def test_init(self):
+ d = Dict(a = 1, b = "test")
+ self.assertEqual(d.a, 1)
+ self.assertEqual(d.b, 'test')
+ self.assertTrue(isinstance(d, dict))
+
+ def test_key(self):
+ d = Dict()
+ d['key'] = 'value'
+ self.assertEqual(d.key, 'value')
+
+ def test_attr(self):
+ d = Dict()
+ with self.assertRaises(KeyError):
+ value = d['empty']
+
+ def test_attrerror(self):
+ d = Dict()
+ with self.assertRaises(AttributeError):
+ value = d.empty
+
+ # call before every test
+ def setUp(self) -> None:
+ print("setUp()...")
+
+ # call after every test
+ def tearDown(self) -> None:
+ print("tearDown()...")
+
+
+if __name__ == '__main__':
+ # unittest
+ unittest.main()
+ # doctest
+ import doctest
+ doctest.testmod()
\ No newline at end of file
diff --git a/Functional/Closure.py b/Functional/Closure.py
new file mode 100644
index 0000000..7c51d1d
--- /dev/null
+++ b/Functional/Closure.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+
+# do not use a loop variable if return a closure
+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(), f2(),f3()) # 9 9 9
+
+# bind before i chagne
+def count2():
+ def f(j):
+ def g():
+ return j*j
+ return g
+ fs = []
+ for i in range(1, 4):
+ fs.append(f(i))
+ return fs
+
+f1, f2, f3 = count2()
+print(f1(), f2(), f3())
+
+# every call will return a incresing value
+def createCounter():
+ n = 0
+ def counter():
+ nonlocal n # need define as nonlocal, if call outter local variable
+ n = n + 1
+ return n
+ return counter
+
+c = createCounter()
+print([c() for _ in range(10)])
+d = createCounter()
+print([d() for _ in range(10)])
\ No newline at end of file
diff --git a/Functional/Decorator.py b/Functional/Decorator.py
new file mode 100644
index 0000000..79097be
--- /dev/null
+++ b/Functional/Decorator.py
@@ -0,0 +1,69 @@
+# -*- coding: utf-8 -*-
+
+import functools, time
+
+# __name__ of a function
+def f(x):
+ return x * x
+
+print(f.__name__) # f
+print((lambda x : x * x).__name__) #
+
+# decorator
+def log(func):
+ def warpper(*args, **kv):
+ print(f"call {func.__name__}")
+ return func(*args, **kv)
+ return warpper
+
+@log # equals to log = log(now2)
+def now():
+ print('2021-10-2')
+
+def now2():
+ print('2021-10-2')
+
+now()
+log(now2)() # equals to now()
+print(now.__name__) # wrapper
+
+# decorator with arguments
+def log2(text):
+ def decorator(func):
+ @functools.wraps(func)
+ def warpper(*args, **kv):
+ print(f"{text} : {func.__name__}")
+ return func(*args, **kv)
+ return warpper
+ return decorator
+
+@log2("execute") # equals to now3 = log("execute")(now3)
+def now3():
+ print('2021-10-2')
+
+now3()
+print(now3.__name__) # now3, if without @functools.wraps(func), will be wrapper
+
+
+# example: for any functions, print time of the execution in miniseconds
+def metric(func):
+ t = time.time()
+ @functools.wraps(func)
+ def warpper(*args, **kv):
+ k = func(*args, **kv)
+ print(f"{func.__name__} executed in {(time.time() - t) * 1000} ms")
+ return k
+ return warpper
+
+@metric
+def fast(x, y):
+ time.sleep(0.0012)
+ return x + y
+
+@metric
+def slow(x, y, z):
+ time.sleep(0.1234)
+ return x + y + z
+
+print(fast(10, 20))
+print(slow(20, 30, 134))
diff --git a/Functional/HighOrderFunction.py b/Functional/HighOrderFunction.py
new file mode 100644
index 0000000..b22dc35
--- /dev/null
+++ b/Functional/HighOrderFunction.py
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+
+from functools import reduce
+
+# assignment
+print(abs)
+a = abs
+print(a)
+print(a(-10))
+
+# as parameter
+def add(x, y, f):
+ return f(x) + f(y)
+
+print(add(10, -5, abs))
+
+# as return value
+def addz(x, y):
+ def other(z):
+ return x + y + z
+ return other
+
+print(addz)
+print(addz(1, 2))
+print(addz(1, 2) == addz(1, 2)) # False
+print(addz(1, 2)(3))
+
+# map
+def add10(x):
+ return x + 10
+print(list(map(add10, [1, 2, 3])))
+
+def add(x, y):
+ return x + y
+print(list(map(add, range(100)[::-1], [-x for x in range(100, 250)])))
+
+# reduce
+def sum(x, y):
+ return x + y
+print(reduce(sum, range(101)))
+
+# example
+DIGITS = dict((chr(ord('0') + val), val) for val in range(10)) # '0': 0, '1': 1, ...
+def str2int(s):
+ def fn(x, y):
+ return x * 10 + y
+ def char2num(s):
+ return DIGITS[s]
+ return reduce(fn, map(char2num, s))
+
+print(str2int("1024"))
+
+def str2float(s):
+ loc = s.find('.')
+ def char2num(s):
+ return DIGITS[s]
+ part1 = reduce(lambda x, y: x * 10 + y, map(char2num, s[:loc]))
+ part2 = reduce(lambda x, y: x / 10 + y, map(char2num, s[-1:loc:-1]))
+ return part1 + part2/10
+
+print(str2float("1.234"))
+
+# filter
+print(list(filter(lambda x: x % 5 == 0, range(100, 200))))
+
+# example: use Sieve of Eratosthenes to find all prime nunbers
+# https://zh.wikipedia.org/wiki/%E5%9F%83%E6%8B%89%E6%89%98%E6%96%AF%E7%89%B9%E5%B0%BC%E7%AD%9B%E6%B3%95
+def _odd_iter():
+ n = 1
+ while True:
+ n = n + 2
+ yield n
+
+def _not_division(n):
+ return lambda x: x % n > 0
+
+def primes():
+ yield 2
+ it = _odd_iter() # generate odd numbers
+ while True:
+ n = next(it)
+ yield n
+ it = filter(_not_division(n), it) # construct new Iterator
+
+gp = primes()
+print([next(gp) for _ in range(100)])
+
+# sorted
+s = ['bob', 'about', 'Zoo', 'Credit']
+print(sorted(s, key = str.lower, reverse=True))
diff --git a/Functional/Lambda.py b/Functional/Lambda.py
new file mode 100644
index 0000000..d120c06
--- /dev/null
+++ b/Functional/Lambda.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+# anonymous function aka lambda expression
+# with limited support in Python
+
+print(list(map(lambda x : x * x, range(0, 10))))
+
+f = lambda x : x * x
+print(f(10))
+
+def fn(x):
+ return x * x
+
+print(f) # at 0x000002A39C515040>
+print(fn) #
+
+f = lambda x : (lambda y : (lambda z : x + y + z))
+print(f) # at 0x000001B74BF061F0>
+print(f(1)) # .. at 0x000001B74BF060D0>
+print(f(1)(2)) # .... at 0x000001B74BF06280>
+print(f(1)(2)(3))
diff --git a/Functional/PartialFunction.py b/Functional/PartialFunction.py
new file mode 100644
index 0000000..7f82408
--- /dev/null
+++ b/Functional/PartialFunction.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+from functools import partial
+from math import log
+
+# partial function
+int2 = partial(int, base = 2)
+print(int2("1000")) # 8
+
+# equals to
+kw = {"base": 2}
+print(int("1000", **kw))
+
+def f(a, b, *, c, d):
+ print(f"{a}, {b}, {c}, {d}")
+
+f1 = partial(f, 10, d = 40)
+f1(20, c = 30, d = 50) # named arguemnt from partial function can be overrided
+
+f2 = partial(f, b = 20)
+f2(10, c = 30, d = 40)
\ No newline at end of file
diff --git a/GUI/HelloInput.py b/GUI/HelloInput.py
new file mode 100644
index 0000000..7a2a938
--- /dev/null
+++ b/GUI/HelloInput.py
@@ -0,0 +1,23 @@
+# -*- 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()
\ No newline at end of file
diff --git a/GUI/HelloWorld.py b/GUI/HelloWorld.py
new file mode 100644
index 0000000..0969d2c
--- /dev/null
+++ b/GUI/HelloWorld.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+
+from tkinter import *
+
+class Application(Frame):
+ def __init__(self, master = None):
+ Frame.__init__(self, master)
+ self.pack()
+ self.createWidgets()
+ def createWidgets(self):
+ self.helloLabel = Label(self, text='Hello, world!')
+ self.helloLabel.pack()
+ self.quitButton = Button(self, text='Quit', command=self.quit)
+ self.quitButton.pack()
+
+app = Application()
+app.master.title('hello,world')
+app.mainloop()
\ No newline at end of file
diff --git a/GUI/TurtleTest.py b/GUI/TurtleTest.py
new file mode 100644
index 0000000..352425c
--- /dev/null
+++ b/GUI/TurtleTest.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+
+# example
+from turtle import *
+
+color('red', 'yellow')
+begin_fill()
+while True:
+ forward(200)
+ left(170)
+ if abs(pos()) < 1:
+ break
+end_fill()
+done()
\ No newline at end of file
diff --git a/IO/FileIO.py b/IO/FileIO.py
new file mode 100644
index 0000000..92d85e0
--- /dev/null
+++ b/IO/FileIO.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+# synchronous IO : simple but inefficient
+# asynchronous IO : complicated and efficient
+
+with open("Test.txt", "r") as f:
+ for line in f.readlines():
+ print(line.strip())
+
+try:
+ f = open("Test.txt", "r")
+ print(f.read())
+finally:
+ if f:
+ f.close()
\ No newline at end of file
diff --git a/IO/OS.py b/IO/OS.py
new file mode 100644
index 0000000..b8e8864
--- /dev/null
+++ b/IO/OS.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+
+import os
+import shutil
+
+print(os.name) # posix fox Unix-like, nt for windows
+
+# prrint(os.uname()) # detailed system info, do not support in windows
+
+print(os.environ) # all environment variables
+print(os.environ.get("path")) # get specific environment variable
+
+
+# file and directory operations
+print(os.path.abspath('.'))
+print(os.path.join('..', "test", "hello")) # ../test/hello in Unix-like, ..\test\hello in windows
+print(os.path.split("./test/hello.txt"))
+print(os.path.splitext("./test/hello.txt"))
+
+# crate and remove dir file
+try:
+ os.mkdir("./test")
+except:
+ pass
+shutil.copyfile("./OS.py", "./test/OS.py")
+
+testdir = "./test"
+for f in os.listdir(testdir):
+ os.remove(os.path.join(testdir, f))
+os.rmdir(testdir)
+
+# list all files in .
+print(os.listdir('.'))
diff --git a/IO/Serilization.py b/IO/Serilization.py
new file mode 100644
index 0000000..fa45554
--- /dev/null
+++ b/IO/Serilization.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+
+# pickling and unpickling
+import pickle
+
+d = {chr(c) : c for c in range(ord('a'), ord('z') + 1)}
+with open("dump.hex", "wb") as f:
+ pickle.dump(d, f)
+ print(pickle.dumps(d))
+
+with open("dump.hex", 'rb') as f:
+ print(pickle.load(f)) # dict
+
+# JSON serilization
+import json
+with open('dump.json', "wt") as f:
+ json.dump(d, f)
+
+with open('dump.json', 'rt') as f:
+ print(json.load(f))
+
+# normal object json serilization
+
+class Person:
+ def __init__(self, name, age):
+ self.name = name
+ self.age = age
+ def __str__(self) -> str:
+ return f"Person -> name : {self.name}, age : {self.age}"
+
+def person2dict(p):
+ return {
+ "name": p.name,
+ "age": p.age
+ }
+
+def dict2person(d):
+ return Person(d['name'], d['age'])
+
+json_str = json.dumps(Person("Kim", 18), default=person2dict)
+print(json_str)
+print(json.dumps(Person("Jim", 17), default=lambda x : x.__dict__))
+print(json.loads(json_str, object_hook=dict2person))
+
+obj = dict(name="小明", age = 20)
+print(json.dumps(obj, ensure_ascii=False)) # {"name": "\u5c0f\u660e", "age": 20}, use \uxxxx represent non-ascii character
\ No newline at end of file
diff --git a/IO/StringByteIO.py b/IO/StringByteIO.py
new file mode 100644
index 0000000..5f345e8
--- /dev/null
+++ b/IO/StringByteIO.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+
+from io import StringIO, BytesIO
+
+f = StringIO("hello,world!\r\nyes\r\nno\r\n")
+while True:
+ s = f.readline()
+ if s == '':
+ break
+ print(s.strip())
+
+print(f.getvalue())
+
+f = BytesIO()
+f.write("中文".encode('utf-8'))
+print(f.getvalue()) # b'\xe4\xb8\xad\xe6\x96\x87'
+print(f.tell()) # 6
+f.seek(-6, 1) # move current positiont to begin
+print(f.read())
\ No newline at end of file
diff --git a/IO/Test.txt b/IO/Test.txt
new file mode 100644
index 0000000..2c5f49b
--- /dev/null
+++ b/IO/Test.txt
@@ -0,0 +1,2 @@
+Nehpren Ruq Insania
+Catholly Nota Seniorious
\ No newline at end of file
diff --git a/IO/dump.hex b/IO/dump.hex
new file mode 100644
index 0000000..4763074
Binary files /dev/null and b/IO/dump.hex differ
diff --git a/IO/dump.json b/IO/dump.json
new file mode 100644
index 0000000..a4447ba
--- /dev/null
+++ b/IO/dump.json
@@ -0,0 +1 @@
+{"a": 97, "b": 98, "c": 99, "d": 100, "e": 101, "f": 102, "g": 103, "h": 104, "i": 105, "j": 106, "k": 107, "l": 108, "m": 109, "n": 110, "o": 111, "p": 112, "q": 113, "r": 114, "s": 115, "t": 116, "u": 117, "v": 118, "w": 119, "x": 120, "y": 121, "z": 122}
\ No newline at end of file
diff --git a/Module/Bar.py b/Module/Bar.py
new file mode 100644
index 0000000..8589f75
--- /dev/null
+++ b/Module/Bar.py
@@ -0,0 +1,7 @@
+# -*- coding: utf-8 -*-
+
+print(f"__name__ in Bar.py is {__name__}")
+
+import Foo
+
+print(f"__name__ in Bar.py is {__name__}")
\ No newline at end of file
diff --git a/Module/Foo.py b/Module/Foo.py
new file mode 100644
index 0000000..821e498
--- /dev/null
+++ b/Module/Foo.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+
+print(f"__name__ in Foo.py is {__name__}")
+
+if __name__ == "__main__":
+ print("__name__ in foo.py is __main__")
\ No newline at end of file
diff --git a/Network/TCP/Client.py b/Network/TCP/Client.py
new file mode 100644
index 0000000..a4cf193
--- /dev/null
+++ b/Network/TCP/Client.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+import socket, time
+
+# create a socket
+s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+s.connect(('127.0.0.1', 9999))
+
+# send requests
+print(s.recv(1024).decode('utf-8'))
+for data in [b"Alice", b"Bob", b"Mary"]:
+ s.send(data)
+ print(s.recv(1024).decode('utf-8'))
+s.send(b'exit')
+s.close()
\ No newline at end of file
diff --git a/Network/TCP/Server.py b/Network/TCP/Server.py
new file mode 100644
index 0000000..3f49c2a
--- /dev/null
+++ b/Network/TCP/Server.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+
+import socket, threading, time
+
+def tcplink(sock, addr):
+ print('Accept new connection from %s:%s...' % addr)
+ sock.send(b"Welcome!")
+ while True:
+ data = sock.recv(1024)
+ time.sleep(1)
+ if not data or data.decode('utf-8') == 'exit':
+ break
+ sock.send((f"hello {data.decode('utf-8')}").encode('utf-8'))
+ sock.close()
+ print("Connection from %s:%s closed." % addr)
+
+if __name__ == "__main__":
+ # create a socket: Ipv4, TCP
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ # bind a port
+ s.bind(('127.0.0.1', 9999))
+
+ # listen a port, argument is max connection count
+ s.listen(5)
+ print("waiting for connection...")
+ # accept connection from client
+ while True:
+ # accept a new conection
+ sock, addr = s.accept()
+ # create a new thread to handle TCP connection
+ t = threading.Thread(target=tcplink, args=(sock, addr))
+ t.start()
diff --git a/Network/TCP/TCPConnection.py b/Network/TCP/TCPConnection.py
new file mode 100644
index 0000000..738d228
--- /dev/null
+++ b/Network/TCP/TCPConnection.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+
+
+import socket
+
+# create a socket: AF_INET -> ipv4, SOCK_STREAM -> TCP
+s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+s.connect(('www.baidu.com', 80))
+
+# send a request
+s.send(b'GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n')
+
+# receive data
+buffer = []
+while True:
+ # 1 KB every time
+ 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')
+print(header.decode('utf-8'))
+with open('baidu.html', 'wb') as f:
+ f.write(html)
\ No newline at end of file
diff --git a/Network/TCP/baidu.html b/Network/TCP/baidu.html
new file mode 100644
index 0000000..825a874
--- /dev/null
+++ b/Network/TCP/baidu.html
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 百度一下,你就知道
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Network/UDP/Client.py b/Network/UDP/Client.py
new file mode 100644
index 0000000..15270fa
--- /dev/null
+++ b/Network/UDP/Client.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+
+import socket
+
+# IPv4, UDP
+s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+for data in [b"Alice", b"Bob", b"Mary"]:
+ s.sendto(data, ('127.0.0.1', 9999))
+ print(s.recv(1024).decode('utf-8'))
+s.close()
\ No newline at end of file
diff --git a/Network/UDP/Server.py b/Network/UDP/Server.py
new file mode 100644
index 0000000..f835546
--- /dev/null
+++ b/Network/UDP/Server.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+import socket
+
+# create a socket: IPv4, UDP
+s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+# bind to port
+s.bind(('127.0.0.1', 9999))
+print("Bind UDP on 9999...")
+
+# do not need listen, just receive
+while True:
+ data, addr = s.recvfrom(1024)
+ print("Received from %s:%s" % addr)
+ s.sendto(b'hello, %s' % data, addr)
\ No newline at end of file
diff --git a/OOP/AdvancedOO.py b/OOP/AdvancedOO.py
new file mode 100644
index 0000000..b6150f9
--- /dev/null
+++ b/OOP/AdvancedOO.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+
+from types import MethodType
+from typing import SupportsAbs
+from functools import partial
+
+# bind attribute to obejct dynamically
+class Person:
+ def __init__(self, *args, **kwargs) -> None:
+ self.age = kwargs.pop("age")
+
+def setAge(self, age):
+ self.age = age
+def getAge(self):
+ return self.age
+def hello():
+ print("hello")
+
+# bind to a single object
+p = Person(age = 20)
+p.setAge = MethodType(setAge, p)
+p.getAge = MethodType(getAge, p)
+p.setAge(10)
+print(p.age) # 10
+print(p.getAge()) # 10
+
+# bind to class
+Person.setAge = MethodType(setAge, Person)
+Person.getAge = MethodType(getAge, Person)
+Person.setAge(18)
+print(Person.getAge()) # 18
+print(Person.age) # 18
+
+# bind instance method to class
+Person.setAge = setAge
+p = Person(age = 10)
+p.setAge(100)
+print(p.age) # 100
+print(p.getAge()) # 18
+Person.getAge = getAge
+print(p.getAge()) # 100
+
+
+# __slots__
+class Student(object):
+ __slots__ = ("name", "age", "getName")
+ def getAge(self):
+ return self.age
+
+s = Student()
+s.age = 10
+s.name = "Adam"
+
+def getName(self):
+ return self.name
+
+s2 = Student()
+s2.age = 20
+s2.name = "lisa"
+s2.getName = MethodType(getName, s)
+print(s2.getName()) # Adam
+
+# bound method & function
+s = Student()
+s.age = 10
+f = s.getAge
+print(f) # >
+print(Student.getAge) #
+print(f()) # 10
+print(Student.getAge(s)) # 10
+
+# define a function just like MethodType
+def MyMethodType(f, obj):
+ return partial(f, self = obj)
+
+print(MyMethodType(getAge, s))
+Student.getName = MyMethodType(getName, Student)
+Student.getName()
+Student.name = "hello"
+print(Student.name)
diff --git a/OOP/Class.py b/OOP/Class.py
new file mode 100644
index 0000000..ade42a6
--- /dev/null
+++ b/OOP/Class.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+class Person(object):
+ def __init__(self, name, age) -> None:
+ super().__init__()
+ self.name = name
+ self.age = age
+ self.__gender = "female"
+ def put(self):
+ print(f"name: {self.name}, age: {self.age}")
+ def hi(self):
+ print("hello, self")
+ self.put()
+ Person.hello()
+ def hello():
+ print("hello")
+
+p = Person("lisa", 10)
+p.__init__("Adam", 20)
+p.put()
+p.hi()
+Person.hello()
+
+# add property dynamically
+p.gender = "male"
+print(p.gender)
+print(p._Person__gender) # decorated name
\ No newline at end of file
diff --git a/OOP/Enum.py b/OOP/Enum.py
new file mode 100644
index 0000000..79c45a2
--- /dev/null
+++ b/OOP/Enum.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+from enum import Enum, unique
+WeekDay = Enum('WeekDay', ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'))
+
+print(WeekDay)
+print(WeekDay.Monday)
+print(WeekDay['Tuesday'])
+
+# more precise control about enum
+@unique
+class WeekD(Enum):
+ Sun = 0
+ Mon = 1
+ Tue = 2
+ Wed = 3
+ Thu = 4
+ Fri = 5
+ Sat = 6
+print(WeekD) #
+print(WeekD.Sun)
+print(WeekD["Tue"])
+print(WeekD(1))
+print(WeekD.Fri.value)
+
+for name, member in WeekD.__members__.items():
+ print(name, "->", member)
\ No newline at end of file
diff --git a/OOP/Inheritance.py b/OOP/Inheritance.py
new file mode 100644
index 0000000..70f874d
--- /dev/null
+++ b/OOP/Inheritance.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+
+class Person:
+ def __init__(self, name, age) -> None:
+ super().__init__()
+ self.__name = name
+ self.age = age
+ def sayHello(self):
+ print("hello in Person")
+ def getName(self):
+ return self.__name
+ def getAge(self):
+ return self.age
+ def hi():
+ print("hi in Person")
+
+class Student(Person):
+ def __init__(self, name, age, score) -> None:
+ super().__init__(name, age)
+ self.__name = "default" # new variable, not the __name from Person
+ self.age = 20
+ self.__score = score
+ def sayHello(self): # override
+ super().sayHello()
+ print("hello in Student")
+ def getName2(self):
+ return self.__name
+ def getAge2(self):
+ return self.age
+ def hi():
+ print("hi in Student")
+
+p = Person("lisa", 18)
+p.sayHello()
+
+s = Student("lisa", 18, 100)
+s.sayHello()
+print(s._Person__name) # lisa
+print(s._Student__name) # default
+print(s.getAge()) # 20
+print(s.getAge2()) # 20
+print(isinstance(s, Person)) # True
+print(isinstance(s, object)) # True
+
+Student.hi()
+Person.hi()
+
+print(isinstance(1, object)) # True
+print(isinstance(None, object)) # True
+print(isinstance("hello", object)) # True
+print(isinstance(True, object)) # True
\ No newline at end of file
diff --git a/OOP/MeteClass.py b/OOP/MeteClass.py
new file mode 100644
index 0000000..1d057dc
--- /dev/null
+++ b/OOP/MeteClass.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+
+
+# create class dynamically using type()
+def fn(self, name = "world"):
+ print(f"hello, {name}!")
+
+Hello = type("Hello", (object, ), dict(hello = fn))
+
+h = Hello()
+h.hello()
+print(type(h)) #
+print(Hello)
+
+
+# create class dynamically using metaclass
+
+# first define metaclass, derived from type
+class ListMetaClass(type):
+ def __new__(cls, name, bases, attrs):
+ attrs['add'] = lambda self, value: self.append(value)
+ return type.__new__(cls, name, bases, attrs)
+
+# create class using metaclass
+class MyList(list, metaclass = ListMetaClass):
+ pass
+
+print(MyList) #
+print(type(MyList)) #
+print(type(ListMetaClass)) #
+
+l = MyList()
+l.add(10)
+l.add(100)
+print(l) # [10, 100]
\ No newline at end of file
diff --git a/OOP/MixIn.py b/OOP/MixIn.py
new file mode 100644
index 0000000..250f88c
--- /dev/null
+++ b/OOP/MixIn.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+
+class A(object):
+ def foo(self):
+ print('A foo')
+ def bar(self):
+ print('A bar')
+
+class B(object):
+ def foo(self):
+ print('B foo')
+ def bar(self):
+ print('B bar')
+
+class C1(A, B):
+ pass
+
+class C2(A, B):
+ def bar(self):
+ super().bar()
+ print('C2-bar')
+
+class D(C1, C2):
+ pass
+
+if __name__ == '__main__':
+ print(D.__mro__) # (, , , , , )
+ d = D()
+ d.foo() # A foo
+ d.bar() # C2-bar
\ No newline at end of file
diff --git a/OOP/ORM.py b/OOP/ORM.py
new file mode 100644
index 0000000..8a126a6
--- /dev/null
+++ b/OOP/ORM.py
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+
+# a simple ORM(Object Relational Mapping) framwork
+# maping one line in database to an object, a table to a class
+# define a class according to the data dynamically.
+
+# ORM frame Model
+class Field(object):
+ def __init__(self, name, column_type):
+ self.name = name
+ self.column_type = column_type
+ def __str__(self):
+ return f"<{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(f'Found Model: {name}')
+ mappings = dict()
+ for k, v in attrs.items():
+ if isinstance(v, Field):
+ print(f'Found mapping: {k} => {v}')
+ mappings[k] = v
+ for k in mappings.keys(): # delete class attributes from table class.
+ attrs.pop(k)
+ attrs['__mappings__'] = mappings # save the mapping between atrribute and column
+ attrs['__table__'] = name # name of table, assume that is same as class name
+ return type.__new__(cls, name, bases, attrs)
+
+# derived from dict, add an attribute will add to dict
+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(f"'Model' objct has no attribute {key}")
+
+ def __setattr__(self, key, value) -> None:
+ 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 = f"insert into {self.__table__} ({','.join(fields)}) values {','.join(params)}"
+ print(f"SQL: {sql}")
+ print(f'ARGS: {args}')
+
+ # other operations like: delete, find, update, ...
+
+
+# using like this
+# map to table User
+class User(Model):
+ id = IntegerField('id')
+ name = StringField("username")
+ email = StringField("email")
+ password = StringField("password")
+
+# create instance, map to one line in table User
+u = User(id = 12345, name = "Adam", email = "Adam@orm.org", password = "my-passwd")
+# save to databse
+u.save()
diff --git a/OOP/ObjectTypeInfo.py b/OOP/ObjectTypeInfo.py
new file mode 100644
index 0000000..531e1d5
--- /dev/null
+++ b/OOP/ObjectTypeInfo.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+
+import types
+from typing import get_args
+
+print(type(1)) #
+print(type(1) == type(13))
+
+print(type(type(1))) #
+print(type(abs)) #
+print(type(int)) #
+
+print(int)
+
+def f():
+ pass
+
+# all True
+print(type(1) == int)
+print(type(type) == type)
+print(type(object) == type)
+print(type(int) == type)
+print(type(f) == types.FunctionType)
+print(type(abs) == types.BuiltinFunctionType)
+print(type(x for x in range(100)) == types.GeneratorType)
+print(type([].append) == types.BuiltinMethodType)
+print(type(lambda x : x) == types.LambdaType)
+
+# isinstance
+print(isinstance([], (list, tuple)))
+
+print("===============================")
+# dir, getattr(), setattr(), hasattr()
+class Person():
+ className = "Person"
+ def __init__(self, name) -> None:
+ self.name = name
+ def sayHi(self):
+ print(f"hi, {self.name}")
+ def sayHello():
+ print("hello")
+
+p = Person("Adam")
+print(dir(p))
+print(hasattr(p, "name"))
+setattr(p, "age", 10)
+print(p.age)
+print(getattr(p, "age"))
+print(getattr(p, "nonexist", "default value"))
+
+f = getattr(Person, "sayHello")
+f()
+print(f) #
+f = getattr(p, "sayHi")
+f()
+print(f) # >
+
+print(p.className)
+print(Person.className)
\ No newline at end of file
diff --git a/OOP/Property.py b/OOP/Property.py
new file mode 100644
index 0000000..5cfcbe2
--- /dev/null
+++ b/OOP/Property.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+
+class Person:
+ __slots__ = ("_age")
+ @property
+ def age(self):
+ return self._age
+ @age.setter
+ def age(self, value):
+ if not isinstance(value, int):
+ raise ValueError("age must be a integer!")
+ if value < 0:
+ raise ValueError("age must non-negative!")
+ self._age = value
+
+p = Person()
+p.age = 10
+print(p.age)
+p.age = "18" # ValueError: age must be a integer!
\ No newline at end of file
diff --git a/OOP/SpecialMethods.py b/OOP/SpecialMethods.py
new file mode 100644
index 0000000..fb5d22a
--- /dev/null
+++ b/OOP/SpecialMethods.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+
+from typing import Iterable, Iterator
+
+# more about special methods and attributes: https://docs.python.org/zh-cn/3/reference/datamodel.html#special-method-names
+
+# __str__
+class Person:
+ def __init__(self, name, age) -> None:
+ self.name = name
+ self.age = age
+ def __str__(self) -> str:
+ return f"Person: name: {self.name}, age: {self.age}"
+ __repr__ = __str__
+ def __call__(self):
+ print(f"Call from Person object")
+
+if __name__ == "__main__":
+ print(Person("Adam", 20))
+ Person("Adam", 18)()
\ No newline at end of file
diff --git a/README.md b/README.md
index da477ba..57c915b 100644
--- a/README.md
+++ b/README.md
@@ -1,114 +1,3 @@
-# 个人备忘录
-
-# Github上的仓库
-
-选入标准:觉得有趣,拿来玩,看一看学习,很牛,学习方向,时下流行。
-
-
-## Cpp
-
-- [vczh/vczh_toys][cpp-1]——轮子哥的黑魔法玩具与实验,学习学习。
-- [vczh/tinymoe][cpp-2]——轮子哥的动态类型编程语言,学习编译原理。
-- [vczh-libraries/GacUI][cpp-3]——轮子哥的C++界面库,支持GPU加速。
-- [wuye9036/cppTemplateTutorial][cpp-4]——C++模板编程入门进阶教程,可惜作者没有写完,有机会的话可以PR。
-- [duilib/duilib][cpp-5]——一个C++轻量级UI库。
-
-[cpp-1]: https://github.com/vczh/vczh_toys
-[cpp-2]: https://github.com/vczh/tinymoe
-[cpp-3]: https://github.com/vczh-libraries/GacUI
-[cpp-4]: https://github.com/wuye9036/cppTemplateTutorial
-[cpp-5]: https://github.com/duilib/duilib
-
-
-## 图形学
-
-- [ssloy/tinyrenderer][graphics-1]——OpenGL的渲染器课程,使用OpenGL。
-- [TensShinet/toy_renderer][graphics-2]——一个大佬学习上面课程的记录。
-- [yangzhenzhuozz/Renderer][graphics-3]——基于EasyX实现一个3D渲染器,有文档提供入门教程。
-- [matrixcascade/PainterEngine][graphics-4]——一个高度可移植完整开源的游戏引擎,使用C/C++。
-- [miloyip/light2d][graphics-5]——2D图形学光照入门。
-
-
-[graphics-1]: https://github.com/ssloy/tinyrenderer
-[graphics-2]: https://github.com/TensShinet/toy_renderer
-[graphics-3]: https://github.com/yangzhenzhuozz/Renderer
-[graphics-4]: https://github.com/matrixcascade/PainterEngine
-[graphics-5]: https://github.com/miloyip/light2d
-
-
-## Windows/Microsoft
-
-- [PowerShell/PowerShell][windows-1]——Windows PowerShell。
-- [microsoft/TypeScript][windows-2]——微软亲生TS语言。
-- [microsoft/Windows-classic-samples][windows-3]——WindowsAPI编程实例。
-- [microsoft/calculator][windows-4]——win10上的计算器。
-
-[windows-1]: https://github.com/PowerShell/PowerShell
-[windows-2]: https://github.com/microsoft/TypeScript
-[windows-3]: https://github.com/microsoft/Windows-classic-samples
-[windows-4]: https://github.com/microsoft/calculator
-
-
-## VSCode插件
-
-- [hediet/vscode-drawio][vscode-1]——在VSCode里面画图。
-- [shd101wyy/markdown-preview-enhanced][vscode-2]——MarkDown插件。
-
-[vscode-1]: https://github.com/hediet/vscode-drawio
-[vscode-2]: https://github.com/shd101wyy/markdown-preview-enhanced
-
-
-## 面试、知识体系、技能树、教程
-
-- [qianguyihao/Web][skilltree-1]——前端入门进阶学习笔记。
-- [LearnOpenGL-CN/LearnOpenGL-CN][skilltree-2]——LeanOpenGL教程中文翻译。
-- [linw7/Skill-Tree][skilltree-3]——后端开发面试知识体系。
-- [zhengjianglong915/note-of-interview][skilltree-4]——互联网面试笔记。
-- [CyC2018/CS-Notes][skilltree-5]——技术面试必备基础知识,计算机体系。
-
-[skilltree-1]: https://github.com/qianguyihao/Web
-[skilltree-2]: https://github.com/LearnOpenGL-CN/LearnOpenGL-CN
-[skilltree-3]: https://github.com/linw7/Skill-Tree
-[skilltree-4]: https://github.com/zhengjianglong915/note-of-interview
-[skilltree-5]: https://github.com/CyC2018/CS-Notes
-
-
-## 前端
-
-- [markdown-it/markdown-it][frontend-1]——一个MarkDown解析器。
-
-[frontend-1]: https://github.com/markdown-it/markdown-it
-
-## AI
-
-- [lllyasviel/style2paints][ai-1]——二次元线稿自动上色的引擎。
-
-
-[ai-1]: https://github.com/lllyasviel/style2paints
-
-
-## 工具
-
-- [OpenCppCoverage/OpenCppCoverage][tools-1]——C++覆盖率测试工具。
-- [skywind3000/awesome-cheatsheets][tools-2]——编程语言、开发工具速查表。
-
-[tools-1]: https://github.com/OpenCppCoverage/OpenCppCoverage
-[tools-2]: https://github.com/skywind3000/awesome-cheatsheets
-
-
-## 编译原理
-
-- [miloyip/json-tutorial][compiler-1]——从零开始的JSON库教程。
-- [fool2fish/dragon-book-exercise-answers][compiler-2]——龙书第二版课后习题答案。
-
-[compiler-1]: https://github.com/miloyip/json-tutorial
-[compiler-2]: https://github.com/fool2fish/dragon-book-exercise-answers
-
-
-## 娱乐项目
-
-- [komeiji-satori/Dress][fun-1]——女装。
-- [995icu/996ICU][fun-2]——996.ICU。
-
-[fun-1]: https://github.com/komeiji-satori/Dress
-[fun-2]: https://github.com/995icu/996ICU
\ No newline at end of file
+## Python入门笔记
+
+测试用的代码,笔记在[主分支的Python.md](../../blob/master/Python.md)。
\ No newline at end of file
diff --git a/Regex/Re.py b/Regex/Re.py
new file mode 100644
index 0000000..5a286c2
--- /dev/null
+++ b/Regex/Re.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+print(re.match(r"^\d{3}-\d{3,8}", "012-23423"))
+print(re.split(r'\s+', 'a b c')) # ['a', 'b', 'c']
+print(re.split(r'\$\^\.\{\}', 'a$^.{}b$^.c$'))
+print(re.match(r'^(\d+?)(0*)$', '102300').groups()) # non-greedy matching of \d+?
+
+print(type(re.compile(r"\d+$")))
+
+# test if a string is a email address
+def is_valid_email(addr):
+ regex = r"\w+(\.\w+)*@\w+.\w+"
+ return re.match(regex, addr) != None
+
+assert is_valid_email('someone@gmail.com')
+assert is_valid_email('bill.gates@microsoft.com')
+assert not is_valid_email('bob#example.com')
+assert not is_valid_email('mr-bob@example.com')
+
+def name_of_email(addr):
+ m1 = re.match(r"<([\w\s]+)>\s([a-zA-Z]+)@\w+.\w+", addr)
+ m2 = re.match(r"([a-zA-Z]+)@\w+.\w+", addr)
+ if m1 == None and m2 == None:
+ return None
+ elif m1 != None:
+ return m1.group(1)
+ else:
+ return m2.group(1)
+
+assert name_of_email(' tom@voyager.org') == 'Tom Paris'
+assert name_of_email('tom@voyager.org') == 'tom'
\ No newline at end of file
diff --git a/SQL/MySQLTest.py b/SQL/MySQLTest.py
new file mode 100644
index 0000000..0557f95
--- /dev/null
+++ b/SQL/MySQLTest.py
@@ -0,0 +1,24 @@
+import mysql.connector
+
+with mysql.connector.connect(host = 'localhost', user = 'root', password = 'aojue', database = 'test') as conn:
+ cursor = conn.cursor()
+ cursor.execute('select * from students')
+ values = cursor.fetchall()
+ for x in values:
+ print(x)
+ cursor.execute("show tables")
+ for x in cursor:
+ print(x)
+ cursor.close()
+
+import pymysql
+with pymysql.connect(host = 'localhost', user='root', password='aojue', database='test') as conn:
+ cursor = conn.cursor()
+ cursor.execute('select * from students')
+ values = cursor.fetchall()
+ for x in values:
+ print(x)
+ cursor.execute("show tables")
+ for x in cursor:
+ print(x)
+ cursor.close()
\ No newline at end of file
diff --git a/SQL/SQLAlchemyTest.py b/SQL/SQLAlchemyTest.py
new file mode 100644
index 0000000..e3ae025
--- /dev/null
+++ b/SQL/SQLAlchemyTest.py
@@ -0,0 +1,50 @@
+from sqlalchemy import Column, String, create_engine
+from sqlalchemy.orm import sessionmaker
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy.sql.ddl import DDLBase
+import sqlalchemy
+
+# create a base class
+Base = declarative_base()
+
+# define ORM class
+class User(Base):
+ # table name
+ __tablename__ = 'user'
+ # table structrue
+ id = Column(String(20), primary_key=True)
+ name = Column(String(20))
+
+# initialize database connection
+# databse+connector://user:password@host:port/database
+engine = create_engine('mysql+mysqlconnector://root:aojue@localhost:3306/test')
+# create DBSession class
+DBSession = sessionmaker(bind=engine)
+
+### create table: CREATE TABLE ...
+Base.metadata.create_all(engine)
+
+### add new record: INSERT INTO ...
+# create DbSession object
+session = DBSession()
+
+# delete all records in User table
+users = session.query(User).filter()
+print(users.all())
+for user in users.all():
+ session.delete(user)
+
+# create new User object
+new_user = User(id = '5', name = 'Bob')
+# add to session
+session.add(new_user)
+# commit to database
+session.commit()
+session.close()
+
+### query: SELECT ... FROM ...
+session = DBSession()
+user = session.query(User).filter(User.id == 5).one()
+print('type: ', type(user))
+print('name: ', user.name)
+session.close()
\ No newline at end of file
diff --git a/SQL/SQLiteTest.py b/SQL/SQLiteTest.py
new file mode 100644
index 0000000..f008fcc
--- /dev/null
+++ b/SQL/SQLiteTest.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+
+import sqlite3
+
+import sqlite3
+
+# connect to sqlite3 database, the database is file test.db, if not exist, will create a new file
+with sqlite3.connect('test.db') as conn:
+ # creat a cursor
+ cursor = conn.cursor()
+ # execute SQL
+ cursor.execute('drop table if exists user')
+ cursor.execute('create table user (id varchar(20) primary key, name varchar(20), score int)')
+ cursor.execute(r'insert into user (id, name, score) values ("1", "Michael", 90)')
+ cursor.execute(r'insert into user (id, name, score) values ("2", "Kim", 80)')
+ cursor.execute(r'insert into user (id, name, score) values ("3", "Bob", 65)')
+
+ print(cursor.rowcount)
+
+ # querys
+ cursor.execute('select * from user where id=? or id=?', ('1','2'))
+
+ values = cursor.fetchall()
+ print(values)
+
+ # close
+ cursor.close() # not necessary, __del__ will close automatically
+ conn.commit()
+
+ def get_score_in(con, min, max):
+ cursor = conn.cursor()
+ cursor.execute(r'select name from user where score >= ? and score <= ?', (min, max))
+ values = cursor.fetchall()
+ cursor.close()
+ return [v[0] for v in values]
+
+ assert get_score_in(conn, 85, 100) == ['Michael']
+ assert get_score_in(conn, 70, 100) == ['Michael', 'Kim']
+ assert get_score_in(conn, 60, 100) == ['Michael', 'Kim', 'Bob']
\ No newline at end of file
diff --git a/ThirdPartyLibs/ChardetTest.py b/ThirdPartyLibs/ChardetTest.py
new file mode 100644
index 0000000..5e5097a
--- /dev/null
+++ b/ThirdPartyLibs/ChardetTest.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+
+import chardet
+print(chardet.detect(b'Hello, world!'))
+
+data = '你好,世界!'.encode('gbk')
+print(chardet.detect(data)) # {'encoding': None, 'confidence': 0.0, 'language': None}, why?
+
+data = '你好,世界!'.encode('utf-8')
+print(chardet.detect(data))
+
+data = '最新の主要ニュース'.encode('euc-jp')
+print(chardet.detect(data))
\ No newline at end of file
diff --git a/ThirdPartyLibs/PillowTest.py b/ThirdPartyLibs/PillowTest.py
new file mode 100644
index 0000000..e276d7c
--- /dev/null
+++ b/ThirdPartyLibs/PillowTest.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+
+from PIL import Image, ImageFilter
+
+# open an image
+im = Image.open('nephren.png')
+# get image size
+w, h = im.size
+print('Original image size: %sx%s' % (w, h))
+# resize to 50%
+im.thumbnail((w//2, h//2))
+print('Resize image to: %sx%s' % (w//2, h//2))
+# save scaled image
+im.save('thumbnail.png', 'png')
+
+# blur an iamge
+im = Image.open('nephren.png')
+im2 = im.filter(ImageFilter.BLUR)
+im2.save('blur.png', 'png')
\ No newline at end of file
diff --git a/ThirdPartyLibs/PsUtilTest.py b/ThirdPartyLibs/PsUtilTest.py
new file mode 100644
index 0000000..5e45fb3
--- /dev/null
+++ b/ThirdPartyLibs/PsUtilTest.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+
+import psutil
+
+# CPU info
+print(psutil.cpu_count()) # logical cpu count
+print(psutil.cpu_count(logical=False)) # physical cpy count
+print(psutil.cpu_times())
+
+# print the usage of every cpu core, 5 times in one second
+for x in range(5):
+ print(psutil.cpu_percent(interval=0.2, percpu=True))
+
+# memory and swap memory info
+print(psutil.virtual_memory())
+print(psutil.swap_memory())
+
+# internet
+print(psutil.net_io_counters())
+print(psutil.net_if_addrs()) # port info
+print(psutil.net_if_stats()) # port status
+print(psutil.net_connections())
+
+# process
+print(psutil.pids())
+p = psutil.Process(psutil.pids()[-1])
+print(p.exe()) # executable of process
+print(p.cwd()) # working directory of process
+print(p.cmdline()) # cmd line of process
+print(p.ppid()) # parent process id
+print(p.parent()) # parent process
+print(p.children()) # children processes
+print(p.status()) # status
+print(p.username())
+print(p.create_time())
+# print(p.terminal()) # Unix only
+print(p.cpu_times())
+print(p.memory_info())
+print(p.connections()) # internet connections
+print(p.num_threads())
+print(p.threads())
+print(p.environ()) # environment variables of process
+
+# like ps command
+print(psutil.test())
\ No newline at end of file
diff --git a/ThirdPartyLibs/RequestsTest.py b/ThirdPartyLibs/RequestsTest.py
new file mode 100644
index 0000000..f29afc1
--- /dev/null
+++ b/ThirdPartyLibs/RequestsTest.py
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+
+import requests
+r = requests.get('https://baidu.com')
+print(r.status_code)
+print(r.text)
+print(r.encoding)
+print(r.content.decode('utf-8'))
diff --git a/ThirdPartyLibs/nephren.png b/ThirdPartyLibs/nephren.png
new file mode 100644
index 0000000..336f085
Binary files /dev/null and b/ThirdPartyLibs/nephren.png differ
diff --git a/VeryStarted/hello.py b/VeryStarted/hello.py
new file mode 100644
index 0000000..6909ee2
--- /dev/null
+++ b/VeryStarted/hello.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+print("hello,world!")
+
+print("the quick brown fox jumps over the lazy dog's back.")
\ No newline at end of file
diff --git a/Web/FlaskTemplateTest.py b/Web/FlaskTemplateTest.py
new file mode 100644
index 0000000..9e4b33f
--- /dev/null
+++ b/Web/FlaskTemplateTest.py
@@ -0,0 +1,22 @@
+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()
\ No newline at end of file
diff --git a/Web/FlaskTest.py b/Web/FlaskTest.py
new file mode 100644
index 0000000..87b67be
--- /dev/null
+++ b/Web/FlaskTest.py
@@ -0,0 +1,26 @@
+from flask import Flask
+from flask import request
+
+app = Flask(__name__)
+
+@app.route('/', methods=['GET', 'POST'])
+def home():
+ return 'Home '
+
+@app.route('/signin', methods=['GET'])
+def signin_form():
+ return ''''''
+
+@app.route('/signin', methods=['POST'])
+def signin():
+ # 需要从request对象读取表单内容:
+ if request.form['username']=='admin' and request.form['password']=='password':
+ return 'Hello, admin! '
+ return 'Bad username or password. '
+
+if __name__ == '__main__':
+ app.run()
\ No newline at end of file
diff --git a/Web/WSGITest.py b/Web/WSGITest.py
new file mode 100644
index 0000000..ef969a4
--- /dev/null
+++ b/Web/WSGITest.py
@@ -0,0 +1,10 @@
+from wsgiref.simple_server import make_server
+
+def application(environ, start_response):
+ start_response('200 OK', [('Content-Type', 'text/html')]) # header, response code and header content
+ return [b'Hello, web! '] # body
+
+# create a http server
+httpd = make_server('', 8000, application)
+print("Serving HTTP on port 8000...")
+httpd.serve_forever()
\ No newline at end of file
diff --git a/Web/templates/form.html b/Web/templates/form.html
new file mode 100644
index 0000000..29c260b
--- /dev/null
+++ b/Web/templates/form.html
@@ -0,0 +1,16 @@
+
+
+ Please Sign In
+
+
+ {% if message %}
+ {{ message }}
+ {% endif %}
+
+
+
\ No newline at end of file
diff --git a/Web/templates/home.html b/Web/templates/home.html
new file mode 100644
index 0000000..d310726
--- /dev/null
+++ b/Web/templates/home.html
@@ -0,0 +1,8 @@
+
+
+ Home
+
+
+ Home
+
+
\ No newline at end of file
diff --git a/Web/templates/signin-ok.html b/Web/templates/signin-ok.html
new file mode 100644
index 0000000..5469d13
--- /dev/null
+++ b/Web/templates/signin-ok.html
@@ -0,0 +1,8 @@
+
+
+ Welcome, {{ username }}
+
+
+ Welcome, {{ username }}!
+
+
\ No newline at end of file