Python: Exercise Examples
- 从低位依次打印,并计算位数
n = int(input('number: ')) count = 0 while True: print(n % 10) n = n // 10 count += 1 if n == 0: break print('number of digits: ', count)
- 从高位依次打印(必须先得到位数)
n = int(input('number: ')) count = 0 if n > 1000: if n > 10000: count = 5 else: count = 4 else: if n > 100: count = 3 elif n > 10: count = 2 else: count = 1 print('digits: {0}'.format(count)) prev = 0 for i in range(count, 0, -1): curr = n // (10 ** (i - 1)) print(curr - prev * 10) prev = curr
- 求1-5 factorial 和
sum = 0 for i in range(1, 6): n = 1 for j in range(1, i + 1): n *= j sum += n else: print(sum) tmp = 1 # method 2 sum = 0 for i in range(1, 6): tmp *= i sum += tmp else: print(sum)
- prime number
- 九九乘法表
for i in range(1,10): for j in range(1,i+1): print('{1} * {0} = {2}\t'.format(i,j,i*j),end='') print()
for i in range(1,10): for j in range(1,i+1): product=i*j if j>1 and product<10: product=str(product)+' ' else: product=str(product) print(str(j)+'*'+str(i)+'='+product,end=' ') print()
for i in range(1,10): line='' for j in range(1,i+1): line+='{0}*{1}={2:<2} '.format(j,i,i*j) print(line)
for i in range(1, 10): line = '' for j in range(1, 10): if j < i: line += ' ' * 7 else: line += '{}*{}={:<2} '.format(i, j, i * j) print(line)
for i in range(1, 10): print(' ' * 7 * (i - 1), end='') # print space for j in range(i, 10): print('{0}*{1}={2:<2} '.format(i, j, i * j), end='') print()
- 打印 rhombus
for i in range(-3, 4): if i < 0: prespace = -i else: prespace = i print(' ' * prespace + '*' * (7 - 2 * prespace)) for i in range(-3, 4): prespace = i if i >= 0 else -i print(' ' * prespace + '*' * (7 - 2 * prespace))
for i in range(-3, 4): print(' ' * abs(i) + '*' * (7 - 2 * abs(i)))
for i in range(-3, 4): if i < 0: prev = abs(i) post = 3 elif i == 0: prev = post = 0 else: prev = 3 post = i print(' ' * prev + '*' * (7 - prev - post)) for i in range(-3,4): if i==0: print('*'*7) print(' '*abs(i)+'*'*(4-abs(i))) if i<0 else print(' '*3+'*'*(3-i))
- 倒序打印输入字符, 并统计出现次数
while True: n = input('>').strip().lstrip('0') if n.isdecimal(): break else: print('{} format wrong'.format(n)) counter = [0] * 10 for b in range(10): counter[b] = n.count(str(b)) for b in range(10): if counter[b]: print(f'{b} counts: {counter[b]}') lst = list(n) lst.reverse() print(''.join(lst))
- 打印Fibonacci小于100项
b, p = 0, 1 print(p) while True: c = b + p if c > 100: break print(c) b = p p = c
求Fibonacci第10项
# Loop 1 b, p = 0, 1 for i in range(9): b, p = p, b + p else: print(p) # Loop 2 b, p = 0, 1 count = 0 while True: b, p = p, b + p count += 1 if count == 9: break print(p) # Recursive 1 def fibonacci(n): if n < 2: return n return fibonacci(n - 1) + fibonacci(n - 2) print(fibonacci(10)) # Tail Resursive def fibonacci(n, prev, next): if n == 1: return next return fibonacci(n - 1, next, prev + next) print(fibonacci(10, 0, 1))
- 求1000内的prime number
count = 0 lst1 = [] lst2 = [] for i in range(2, 1000 + 1): for j in range(2, i): if i % j == 0: break else: count += 1 lst1.append(i) print(count) count = 1 # add 2 # int(i**0.5)+1, 9, 15, 35 for i in range(3, 1000 + 1, 2): for j in range(3, int(i ** 0.5) + 1, 2): if i % j == 0: break else: count += 1 print(count) count = 2 for i in range(3, 1000 + 1, 2): tmp = i ** 0.5 for j in range(3, i, 2): if i % j == 0: break if j > tmp: count += 1 lst2.append(i) break print(count) for i in lst1: if i not in lst2: print(i)
import math n = 100 primes = [] for x in range(2, n + 1): for i in primes: if x % i == 0: break else: primes.append(x) print(len(primes)) primes.clear() for x in range(2, n + 1): flag = True for p in primes: if x % p == 0: flag = False break if p == math.ceil(math.sqrt(x)): print(p, x) if p > math.ceil(math.sqrt(x)): break if flag: primes.append(x) print(len(primes))
- 猴子吃桃
n = 1 for i in range(9): n = (n + 1) * 2 else: print(n) def peach(n): if n == 10: return 1 return peach(n + 1) * 2 + 2 print(peach(1))
n = 1 c = 0 # while True: # c += 1 # n = (n + 1) * 2 # if c == 9: # break while True: if c == 9: # 0-9,c==9,第十次没有执行循环 break c += 1 n = (n + 1) * 2 print(n)
- 杨辉三角
triangle = [] for i in range(6): vex = [] triangle.append(vex) for j in range(i + 1): if j == 0 or j == i: vex.append(1) # print(i, j, triangle, vex) else: # print(i, j, triangle, vex) vex.append(triangle[i - 1][j - 1] + triangle[i - 1][j]) print(triangle)
-
transport matric 转置矩阵
vex = list(range(1, 10)) vie = [] tmp = [] for i in vex: tmp.append(i) if i % 3 == 0: vie.append(tmp) tmp = [] print(vie) for i in range(len(vie)): for j in range(len(vie[i])): print(vie[j][i], end=' ') print()
vex = list(range(1, 10)) vie = [] tmp = [] for i in vex: tmp.append(i) if i % 3 == 0: vie.append(tmp) tmp = [] print(vie) # 对角线 i=j,非对角线i>j或i<j, 只需交换一边 for i in range(len(vie)): for j in range(i): # i>j vie[j][i], vie[i][j] = vie[i][j], vie[j][i] print(vie) for i in range(len(vie)): for j in range(i + 1, len(vie)): # i<j vie[j][i], vie[i][j] = vie[i][j], vie[j][i] print(vie) for i, row in enumerate(vie): for j, elem in enumerate(row): if i < j: vie[j][i], vie[i][j] = vie[i][j], vie[j][i] print(vie)
vie = [[1, 2, 3], [4, 5, 6]] vole = [] for i, row in enumerate(vie): for j, v in enumerate(row): if i == 0: vole.append([v]) else: vole[j].append(v) print(vole) vole = [] for row in vie: for i, v in enumerate(row): if len(vole) < i + 1: vole.append([]) vole[i].append(v) print(vole) vole = [[0 for i in range(len(vie))] for _ in range(len(vie[0]))] for i, row in enumerate(vie): for j, v in enumerate(row): vole[j][i] = vie[i][j] print(vole)
- 随机生成10个数字,统计重复和不重复个数
import random n = [] for _ in range(10): n.append(random.randrange(21)) print(n) same = [] diff = [] states = [0] * len(n) for i in range(len(n)): flag = False if states[i]: continue for j in range(i + 1, len(n)): if states[j]: continue if n[i] == n[j]: flag = True states[j] = 1 if flag: same.append(n[i]) states[i] = 1 else: diff.append(n[i]) print(same, diff)
- set 集合
import random s1 = set() s2 = set() for _ in range(10): s1.add(random.randrange(10, 21)) s2.add(random.randrange(10, 21)) print(s1, s2) print(f'common: {len(s1 | s2)}') print(f'unique: {len(s1 ^ s2)}') print(f'duplicate: {s1 & s2}')
- 简单选择排序
import random vixen = list(range(10)) random.shuffle(vixen) print(vixen) count_iter = count_swap = 0 for i in range(len(vixen)): min_index = i for j in range(i + 1, len(vixen)): count_iter += 1 if vixen[min_index] > vixen[j]: min_index = j if i != min_index: count_swap += 1 vixen[i], vixen[min_index] = vixen[min_index], vixen[i] print(vixen) print(count_iter) print(count_swap)
二元选择排序
import random vixen = list(range(10)) random.shuffle(vixen) print(vixen) count_iter = count_swap = 0 for i in range(len(vixen) // 2): # len(vixen)=odd: len(vixen)//2 自然被排好序 minindex = i maxindex = -i - 1 # 与minindex对称 maxorigin = maxindex for j in range(i + 1, len(vixen) - i): # 负索引也对称 count_iter += 1 if vixen[minindex] > vixen[j]: minindex = j if vixen[maxindex] < vixen[-j - 1]: maxindex = -j - 1 # not j if vixen[minindex] == vixen[maxindex]: # 剩余元素相同 break if i != minindex: vixen[i], vixen[minindex] = vixen[minindex], vixen[i] count_swap += 1 if maxorigin != maxindex and vixen[maxorigin] != vixen[maxindex]: # 2 2 2 2 1 情况 vixen[maxorigin], vixen[maxindex] = vixen[maxindex], vixen[maxorigin] count_swap += 1 print(vixen) print(count_iter) print(count_swap)
b = ['{:>04}.{}'.format(n, ''.join((random.choice(string.ascii_lowercase) for _ in range(5)))) for n in range(5)]
b = ['{:04}.{}'.format(n, ''.join((chr(random.randint(97, 122)) for _ in range(5)))) for n in range(5)]
['{:04}.{}'.format(n, ''.join((random.choice(bytes(range(97, 123)).decode()) for _ in range(10)))) for n in range(1, 101)]
- 生成随机captcha
import random def captcha(size=7): res = '' for i in range(size): lowercase = chr(random.randint(97, 122)) uppercase = chr(random.randrange(65, 91)) number = chr(random.randrange(48, 58)) res += random.choice((lowercase, uppercase, number)) return res print(captcha(8))
- 列表解析式打印九九乘法表
[print('{}*{}={:<3}{}'.format(j, i, i * j, '\n' if i == j else ' '), end=' ') for i in range(1, 10) for j in range(1, i + 1)]
while True: n = input('>>').strip().lstrip('0') if n.isdecimal(): break else: print('{} wrong'.format(n)) d = {} for b in n: if b not in d.keys(): d[b] = 0 d[b] += 1 # for b in n: # d[b] = d.get(b, 0) + 1 # for b in n: # if d.get(b, None): # d[b] += 1 # else: # d.setdefault(b, 1) for b in n: print(f'number: {b}, count: {d[b]}')
import random def vivify(*nums): return max(nums), min(nums) print(*vivify(*(random.randrange(10, 30) for _ in range(50))))
def vocal(n): for i in range(1, 13): for j in range(12, 0, -1): if j <= i: print('{:<{width}}'.format(j, width=1 if j == 1 else 3), end='') else: print(' ' * 3, end='') print() print() for i in range(12, 0, -1): for j in range(12, 0, -1): if j <= i: print('{:<{width}}'.format(j, width=1 if j == 1 else 3), end='') else: print(' ' * 3, end='') print() vocal(13)
def vivify(n): tail = ' '.join((str(i) for i in range(n, 0, -1))) width = len(tail) for i in range(1, n): print('{:>{}}'.format(' '.join((str(i) for i in range(i, 0, -1))), width)) print(tail) print() print(tail) for i in range(n - 1, 0, -1): print('{:>{}}'.format(' '.join((str(i) for i in range(i, 0, -1))), width)) vivify(13)
def vivify(n): head = ' '.join(((str(i) for i in range(n, 0, -1)))) print(head) for i in range(len(head)): # 空格分隔 if head[i] == ' ': print(' ' * i, head[i + 1:], sep=' ') vivify(13)
- 直接插入排序
import random nums = list(range(10)) random.shuffle(nums) print(nums) def insert_sort(vixen): count_assign = 0 vixen = [0] + vixen for i in range(2, len(vixen)): vixen[0] = vixen[i] # sentinel, 待插入值 j = i - 1 while vixen[j] > vixen[0]: count_assign += 1 vixen[j + 1] = vixen[j] j -= 1 vixen[j + 1] = vixen[0] print(count_assign) return vixen[1:] print(insert_sort(nums))
- 将数字倒序生成list
def vixen(n, l=None): if l is None: l = [] if n // 10: l.append(n % 10) return vixen(n // 10, l) l.append(n) return l print(vixen(1234)) def vixen(n, target=None): if target is None: target = [] x, y = divmod(n, 10) target.append(y) if x == 0: return target return vixen(x, target) print(vixen(12345)) def vixen(n, target=[]): if n: target.append(int(n[-1])) vixen(n[:-1]) return target print(vixen(str(1234))) def vixen(n): def vixen_(i): if i == -1: return '' return str(n)[i] + vixen_(i - 1) res = vixen_(len(str(n)) - 1) return [int(x) for x in res] print(vixen(12345))
- 猴子吃桃
def peach(n): if n == 10: return 1 return peach(n + 1) * 2 + 2 print(peach(1)) def peach(n, res=1): if n < 0: return -1 if n == 10: return res res = res * 2 + 2 return peach(n + 1, res) print(peach(1))
- 生成器实现febonacci
def febonacci(): b = 0 p = 1 while True: yield p b, p = p, b + p r = febonacci() for _ in range(5): print(next(r))
- 实现built-in函数sorted功能
import random vale = list(range(10)) random.shuffle(vale) def sort(iterable, reverse=False): ret = [] # def comp() for item in iterable: for i, v in enumerate(ret): # if item > v if reverse else item < v: # ret.insert(i, item) # break if reverse: if item > v: ret.insert(i, item) break else: if item < v: ret.insert(i, item) break else: ret.append(item) return ret print(vale) print(sort(vale, True)) print(sort(vale, 0))
抽离函数
def sort(iterable, reverse=False): ret = [] def comp(v, item, reverse): return item > v if reverse else item < v for item in iterable: for i, v in enumerate(ret): if comp(v, item, reverse): ret.insert(i, item) break else: ret.append(item) return ret
import random vale = list(range(10)) random.shuffle(vale) def comp(a, b): return a < b def sort(iterable, key=lambda a, b: a < b, reverse=False): ret = [] for item in iterable: for i, v in enumerate(ret): flag = key(v, item) if reverse else key(item, v) if flag: ret.insert(i, item) break else: ret.append(item) return ret print(vale) print(sort(vale, key=comp, reverse=True)) print(sort(vale, key=comp, reverse=False)) print(sort(vale))
-
字典flat
bud = {'a': {'b': 11, 'c': 'tt'}, 'd': {'e': 3, 'f': {'g': 55}}} def flat(d: dict, target=None, prefix=''): if target is None: target = {} for k, v in d.items(): # if type(v) == dict: if isinstance(v, (dict,)): flat(v, target, prefix=prefix + k + '.') else: target[prefix + k] = v if prefix == '': return target print(flat(bud))
-
实现base64.b64encode()
import string, base64 def encode(s): alphabet = string.ascii_uppercase + string.ascii_lowercase + string.digits + '+' + '/' alphabet = bytes(alphabet, encoding='utf8') ret = bytearray() zeros = 0 length = len(s) for offset in range(0, length, 3): if offset + 3 <= length: # 可取到源数据的三个有效字节 triple = s[offset:offset + 3] else: # zeros = 3 - (length - offset) # triple = s[offset:] + b'\x00' * zeros triple = s[offset:] zeros = 3 - len(triple) triple = triple + b'\x00' * zeros n = int.from_bytes(triple, 'big') # 对n进行移位 for i in range(18, -1, -6): # 右移四次,18 12 6 0 if i == 18: index = n >> i else: index = n >> i & 0x3F ret.append(alphabet[index]) print(ret) for i in range(zeros): ret[-i - 1] = 0x3D # bytearray每个元素0-255整形, = 码值0x3D print(zeros) return bytes(ret) s = 'abcd' print(encode(s.encode(encoding='utf8'))) print(base64.b64encode(s.encode()))
-
求最长字串
s1 = 'abcdefg' s2 = 'defabcdoabcdeftw' s3 = '=' def find_substr(s1: str, s2: str): if len(s1) > len(s2): s1, s2 = s2, s1 count = 0 length = len(s1) for sublen in range(length, 0, -1): for start in range(0, length - sublen + 1): substr = s1[start:start + sublen] count += 1 if s2.find(substr) > -1: print('count={}'.format(count)) return substr return '' print(find_substr(s1, s2)) print(find_substr(s1, s3))
s1 = 'abcdefg' s2 = 'defabcdoabcdeftw' def find_substr(s1: str, s2: str): if len(s1) > len(s2): s1, s2 = s2, s1 length = len(s1) matrix = [] max = 0 # 最大字串长度 xindex = 0 # 最大字串结束索引(s2) yindex = 0 for i, v1 in enumerate(s1): # 外层循环从小串开始 matrix.append([]) for j, v2 in enumerate(s2): if v1 == v2: if i == 0 or j == 0: # i==0(s1[0]) j==0(s2[0]) matrix[i].append(1) else: matrix[i].append(matrix[i - 1][j - 1] + 1) else: matrix[i].append(0) if matrix[i][j] > max: max = matrix[i][j] xindex = j yindex = i return s1[yindex - max + 1:yindex + 1], s2[xindex - max + 1:xindex + 1] # xindex+1因为后开, xindex-xmax+1,因为直接减字串长度,会多往前走一个 print(find_substr(s2, s1))
-
随机数生成器
import random class RandomGenerator: def __init__(self, n=10, minimum=1, maximum=10): self.n = n self.minimum = minimum self.maximum = maximum self.g = self._generator() def _generator(self): while True: yield [random.randint(self.minimum, self.maximum) for _ in range(self.n)] def generator(self, n=15): self.n = n return next(self.g) r = RandomGenerator() print(r.generator(5)) print(r.generator(10)) print(r.generator())
-
温度转换类
class Temperature: def __init__(self, t, unit='c'): ''' description :param t: :param unit: :return None ''' self.__celsius = None self.__fahrenheit = None self.__kelvin = None if unit == 'k': self.__kelvin = t self.__celsius = self.k2c(t) elif unit == 'f': self.__celsius = self.f2c(t) self.__fahrenheit = t else: self.__celsius = t @property def kelvin(self): if self.__kelvin is None: self.__kelvin = self.c2k(self.__celsius) return self.__kelvin @property def celsius(self): return self.__celsius @property def fahrenheit(self): if self.__fahrenheit is None: self.__fahrenheit = self.c2f(self.__celsius) return self.__fahrenheit @classmethod def c2f(cls, c): return c * 9 / 5 + 32 @classmethod def f2c(cls, f): return (f - 32) * 5 / 9 @classmethod def c2k(cls, c): return c + 273.15 @classmethod def k2c(cls, k): return k - 273.15 @classmethod def k2f(cls, k): return cls.c2f(cls.k2c(k)) @classmethod def f2k(cls, f): return cls.c2k(cls.f2c(f))
- class __call__ Fibonacci
class Fibonacci: def __init__(self): self.vagary = [0, 1] def __len__(self): return len(self.vagary) def __call__(self, index): if index < 0: raise IndexError(f'{index} out of range') if index <= len(self): return self.vagary[index] else: for i in range(len(self) - 1, index): self.vagary.append(self.vagary[i - 1] + self.vagary[i]) return self.vagary[index] def __getitem__(self, index): if index < 0: return None if index <= len(self): return self.vagary[index] else: self(index) return self.vagary[index] def __iter__(self): self.__g = iter(self.vagary) return self def __next__(self): return next(self.__g) def __repr__(self): return str(self.vagary) __str__ = __repr__ f = Fibonacci() print(f(5)) print(f) for v in f: print(v) print(f.vagary) print(f(7)) print(f.vagary) print(f(3)) print(f[55]) print(f.vagary)
- 上下文管理
import sys class Point: def __init__(self): print('__init__') def __enter__(self): print(f'__enter__ {self.__class__}') return self def __exit__(self, exc_type, exc_val, exc_tb): print(f'__exit__ {self.__class__.__name__}') print(f'exc_type {exc_type}') print(f'exc_val {exc_val}') print(f'exc_tb {exc_tb}') # return True # stifle Exception p = Point() print(f'p = {p}') with p as f: raise Exception('Error') sys.exit(202) print(f'f = {f}') print('end')
- 时间计数器
import time, datetime class Chronograph: def __init__(self): pass def __enter__(self): self.start = datetime.datetime.now() return self def __exit__(self, exc_type, exc_val, exc_tb): print((datetime.datetime.now() - self.start).total_seconds()) def add(x, y): time.sleep(1.5) return x + y with Chronograph() as f: add(5, 55)
import time, datetime from functools import wraps def chronograph(f): @wraps(f) def wrapper(*args, **kwargs): start = datetime.datetime.now() ret = f(*args, **kwargs) delta = (datetime.datetime.now() - start).total_seconds() print(f'{f.__name__} elapsed {delta}') return ret return wrapper @chronograph def add(x, y): time.sleep(1.5) return x + y add(5, 55)
- 实现staticmethod classmethod
from functools import wraps, partial class StaticMethod: def __init__(self, f): self.f = f def __get__(self, instance, owner): print(f'{self.__class__.__name__} {self, instance, owner}') return self.f class ClassMethod: def __init__(self, f): self.f = f def __get__(self, instance, owner): print(f'{self.__class__.__name__} {self, instance, owner}') # @wraps(self.f) # def wrapper(*args, **kwargs): # return self.f(owner, *args, **kwargs) # return wrapper return partial(self.f, owner) class B: @StaticMethod def vagary(): print(f'vagary') @ClassMethod def vague(cls, b, /): ''' __doc__ :param b: :return: ''' print(cls.__name__, b) print(B.__dict__) print(B.vagary, type(B.vagary)) B.vagary() B.vague(55) print(B.vague.__doc__)
- 对类进行类型检查
import inspect class CheckMode: def __init__(self, name, mold): self.name = name self.mold = mold def __get__(self, instance, owner): if instance is not None: # Instance Call return instance.__dict__[self.name] # Not JS return self def __set__(self, instance, value): # Only instance call __set__ if isinstance(value, self.mold): instance.__dict__[self.name] = value else: raise TypeError(f'{value} is not {self.mold}') # def type_assert(cls): # parameters = inspect.signature(cls).parameters # print(parameters) # for arg, parameter in parameters.items(): # print(arg, parameter, type(parameter)) # if parameter.annotation != parameter.empty: # setattr(cls, arg, CheckMode(arg, parameter.annotation)) # return cls # @type_assert class TypeAssert: def __init__(self, cls): self.cls = cls self.__assert() def __assert(self): parameters = inspect.signature(self.cls).parameters for arg, parameter in parameters.items(): if parameter.annotation != parameter.empty: setattr(self.cls, arg, CheckMode(arg, parameter.annotation)) def __call__(self, *args, **kwargs): return self.cls(*args, **kwargs) @TypeAssert class Person: def __init__(self, name: str, age: int): # parameters = ((name, str), (age, int)) # if not self.check_mode(parameters): # raise TypeError() self.name = name self.age = age def check_mode(self, parameters): for var, mode in parameters: if not isinstance(var, mode): return False return True print(Person.__dict__) print(type(Person), Person.cls.__dict__) p = Person('r', 5) # p = Person('r', '5')
- 实现内置property
class Property: def __init__(self, fget, fset=None, fdel=None): self.fget = fget self.fset = fset self.fdel = fdel def __get__(self, instance, owner): if not instance: return self return self.fget(instance) def __set__(self, instance, value): if callable(self.fset): self.fset(instance, value) else: AttributeError(f'{self.fset} not callable') def __delete__(self, instance): self.fdel(instance) def setter(self, fset): self.fset = fset return self def deleter(self, fdel): self.fdel = fdel return self class B: def __init__(self, data): self._data = data @Property def data(self): return self._data @data.setter def data(self, value): self._data = value @data.deleter def data(self): del self._data b = B(5) b.data = 55 print(b.data) del b.data print(b.__dict__) print(B.__dict__)
- 转换到int
def cast2int(v): try: return int(v) except: return 0 print(toInt('b'))
- 多线程print函数(线程不安全)
print不换行
import threading, time def b(): for x in range(100): print(f'{threading.current_thread()} running\n', end='') for x in range(5): threading.Thread(target=b, name=f'work-{x}').start()
logging module
import threading, time, logging logging.basicConfig(level=logging.INFO) def b(): for x in range(100): logging.info(f'{threading.current_thread().name} running') for x in range(5): threading.Thread(target=b, name=f'work-{x}').start()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律