├── README.md ├── test1.py ├── test10.py ├── test11.py ├── test12.py ├── test13.py ├── test14.py ├── test15.py ├── test16.py ├── test17.py ├── test18.py ├── test19.py ├── test2.py ├── test20.py ├── test21.py ├── test22.py ├── test23.py ├── test24.py ├── test25.py ├── test26.py ├── test27.py ├── test28.py ├── test29.py ├── test3.py ├── test30.py ├── test31.py ├── test32.py ├── test33.py ├── test35.py ├── test36.py ├── test37.py ├── test38.py ├── test39.py ├── test4.py ├── test40.py ├── test41.py ├── test42.py ├── test43.py ├── test44.py ├── test45.py ├── test46.py ├── test47.py ├── test48.py ├── test49.py ├── test5.py ├── test50.py ├── test51.py ├── test52.py ├── test53.py ├── test54.py ├── test55.py ├── test56.py ├── test6.py ├── test7.py ├── test8.py └── test9.py /README.md: -------------------------------------------------------------------------------- 1 | # python_test 2 | ## 练习廖雪峰的官方网站的python题目及python基础代码 3 | ### 如果觉得对你有用的话,欢迎fork或者给个star哈! 4 | -------------------------------------------------------------------------------- /test1.py: -------------------------------------------------------------------------------- 1 | # 练习python的参数 2 | 3 | # 命名关键字参数,与默认参数有点不同,这个参数没有默认值,而且也属于必填参数,不填时会报错 4 | def fun(name,age,*,city,job): 5 | print(name,age,city,job) 6 | 7 | fun('huang',15,city='biejing',job='progrommer') 8 | 9 | 10 | 11 | # 参数下的练习题 12 | def product(*nums): 13 | if nums is None: 14 | raise TypeError('参数不能为None') 15 | res = 1 16 | for num in nums: 17 | res *= num 18 | 19 | return res 20 | -------------------------------------------------------------------------------- /test10.py: -------------------------------------------------------------------------------- 1 | # 练习函数式编程的sorted函数 2 | 3 | 4 | L = [1, 5, 6, 9, -8, 7, -4, -1, 3, -5] 5 | print(L) 6 | # 排序不改变原来函数,生成一个新的列表 7 | L = sorted(L) 8 | print(L) 9 | # 指定排序方式 10 | L = [1, 5, 6, 9, -8, 7, -4, -1, 3, -5] 11 | L = sorted(L, key=abs) 12 | print(L) 13 | 14 | s = ['dfs','Fds','tda','Eds'] 15 | print(s) 16 | print(sorted(s)) 17 | print(sorted(s, key=str.lower)) 18 | # 反向排序 19 | print(sorted(s, key=str.lower, reverse=True)) 20 | 21 | 22 | # 作业:假设我们用一组tuple表示学生名字和成绩,L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)],按名字进行排序 23 | L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)] 24 | print(sorted(L, key=lambda x: x[0])) 25 | # 按成绩进行排序 26 | print(sorted(L,key=lambda x: x[1])) 27 | -------------------------------------------------------------------------------- /test11.py: -------------------------------------------------------------------------------- 1 | # 练习下函数式编程的返回函数 2 | 3 | 4 | # 在python中,函数可以当返回值返回 5 | def func(*args): 6 | # 求可变参数的和 7 | def fun(): 8 | sum = 0 9 | for n in args: 10 | sum += n 11 | return sum 12 | return fun 13 | 14 | 15 | # 上述的就是闭包,闭包中内层函数可以使用外层函数的变量 16 | sum = func(*[1, 3, 5, 7, 9]) 17 | print(sum) # 可以看出返回了一个函数,内层函数 18 | print(sum()) # 若要输出结果就是加个小括号就可,这种是惰性求和 19 | 20 | 21 | # 但是在使用循环变量时 22 | def f1(): 23 | fs = [] 24 | for x in range(1, 4): 25 | def f2(): 26 | return x*x 27 | fs.append(f2) 28 | return fs 29 | 30 | 31 | # 上面利用循环返回了一个存有三个函数的列表,现在一一复制看结果 32 | n1, n2, n3 = f1() 33 | # 可以看出,结果都是三,并不是想象中的1,4,9 34 | # 这是因为我们在使用闭包时,内层函数的变量指向了循环变量,而函数并不是立即执行,当循环完后,循环变量就变了,这时再执行函数就会产生意想不到的结果 35 | # 所以在使用闭包时记得尽量不要使用循环变量 36 | print(n1()) 37 | print(n2()) 38 | print(n3()) 39 | 40 | 41 | # 若一定要使用循环变量,就是在内层函数在定义一个函数来绑定循环变量让他不再可变 42 | def f1(): 43 | def f2(i): 44 | def f3(): 45 | return i*i 46 | return f3 47 | fs = [] 48 | for x in range(1, 4): 49 | fs.append(f2(x)) 50 | 51 | return fs 52 | 53 | 54 | # 现在就可以了使用循环变量了 55 | n1, n2, n3 = f1() 56 | print(n1()) 57 | print(n2()) 58 | print(n3()) 59 | 60 | 61 | # 闭包还可以这样玩,用闭包来求泛型函数 62 | def line(a, b): 63 | # 内层函数也加了个参数 64 | def aline(x): 65 | return a*x + b 66 | return aline 67 | 68 | 69 | l1 = line(2,3) 70 | l2 = line(5,6) 71 | # 求值时因为内层函数需要传参数,所以这里也需要传参数 72 | print(l1(3)) 73 | print(l2(8)) 74 | 75 | 76 | # 作业:利用闭包返回一个计数器函数,每次调用它返回递增整数 77 | def create_count(): 78 | # 将变量n设为全局变量 79 | global n 80 | n = 0 81 | 82 | def counter(): 83 | # 将变量n设为全局变量 84 | global n 85 | n += 1 86 | return n 87 | return counter 88 | 89 | 90 | counter = create_count() 91 | print(counter(), counter(), counter(), counter(), counter()) 92 | countera = create_count() 93 | print(countera(), countera(), countera(), countera(), countera()) 94 | 95 | -------------------------------------------------------------------------------- /test12.py: -------------------------------------------------------------------------------- 1 | # 练习函数式编程的匿名函数 2 | from functools import reduce 3 | 4 | 5 | # 用reduce来求一个列表的和 6 | l = [x for x in range(11)] 7 | # lambda的就是匿名函数,冒号前的表示参数,冒号后的表达式的结果为返回值 8 | sum = reduce(lambda x, y: x + y, l) 9 | print(sum) 10 | 11 | # 还可以将匿名函数赋值给变量 12 | f = lambda x: x * x 13 | print(f(5)) 14 | print(f(8)) 15 | 16 | 17 | # 作业:改造代码 18 | L = list(filter(lambda x: x % 2 == 1,range(1,20))) 19 | print(L) 20 | -------------------------------------------------------------------------------- /test13.py: -------------------------------------------------------------------------------- 1 | # 练习函数式编程的装饰器 2 | from functools import wraps 3 | import time 4 | 5 | 6 | # now() 7 | # 现在想在函数里面增加打印log信息,这时又不想修改函数内部,此时可用装饰器 8 | def decorator(func): 9 | @wraps(func) # 加这个装饰器是将原函数的__name__等属性复制到这个wrapper函数,防止某些依赖函数签名的代码发生错误 10 | def wrapper(*args, **kw): 11 | print('%s %s()' % ('decorator', func.__name__)) 12 | func() 13 | return wrapper 14 | 15 | 16 | @decorator 17 | def now(): 18 | print('2018-02-22') 19 | 20 | 21 | now() # 加了装饰器之后再调用该函数就是装饰器里的wrapper()函数内容了 22 | # 在装饰器上也加个wraps装饰器后就可以复制原函数的属性了,此时就变成了原函数名字 23 | print(now.__name__) # 此时他的__name__属性也改变了 24 | 25 | 26 | # 有参数的装饰器 27 | def log(text): 28 | def decorator(func): 29 | @wraps(func) # 记得加这个装饰器防止错误 30 | def wrapper(*args, **kw): 31 | print('%s %s()' % (text, func.__name__,)) 32 | func(*args, **kw) 33 | return wrapper 34 | return decorator 35 | 36 | 37 | @log('execute') 38 | def fun(): 39 | print('now:2018-02-22') 40 | 41 | 42 | fun() 43 | print(fun.__name__) 44 | 45 | 46 | # 作业:设计一个decorator,它可作用于任何函数上,并打印该函数的执行时间 47 | def metric(func): 48 | @wraps(func) 49 | def wrapper(*args, **kw): 50 | print(time.time()) 51 | return func(*args, **kw) 52 | return wrapper 53 | 54 | 55 | @metric 56 | def fast(x, y): 57 | time.sleep(0.0012) 58 | return x + y 59 | 60 | @metric 61 | def slow(x, y, z): 62 | time.sleep(0.1234) 63 | return x * y * z 64 | 65 | 66 | print('作业') 67 | print(fast(11, 22)) 68 | print(slow(11, 22, 33)) 69 | -------------------------------------------------------------------------------- /test14.py: -------------------------------------------------------------------------------- 1 | # 练习函数式编程的偏函数 2 | import functools 3 | 4 | 5 | print(int('12')) 6 | print(int('12', 8)) 7 | 8 | # 偏函数,可以简单理解为将函数的某个参数固定住,从而简化调用函数的参数 9 | # 与函数参数的默认参数类似 10 | # 当函数参数比较多的时候可以选择使用偏函数 11 | 12 | # 现在将int函数的禁止在位固定为8进制 13 | # partial方法的第一个参数为函数名,第二个为固定的参数 14 | int8 = functools.partial(int, base=8) 15 | print(int8('12')) 16 | 17 | kw = {'base': 2} 18 | int2 = functools.partial(int, **kw) 19 | print(int2('10')) 20 | 21 | 22 | -------------------------------------------------------------------------------- /test15.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | ' a test module ' 5 | 6 | __author__ = 'sergiojune' 7 | 8 | 9 | # 上面是一个模块的正确写法 10 | # 第一个注释是可以将这个代码直接运行在Unix/Linux/Mac上 11 | # 第二行代码是说这个代码是以utf-8编写的 12 | # 第三代码就是模块的文档注释 13 | # 第四行代码就是作者标明 14 | 15 | import sys 16 | # 添加自己模块的查找位置,这样的方法当运行完就失效,可以想一直有用可以添加环境变量 17 | sys.path.append(r'E:\anaconda\python_project') 18 | # 导入自己的模块 19 | import spider_ip 20 | -------------------------------------------------------------------------------- /test16.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | ' 练习面向对象的类和实例 ' 5 | 6 | __author__ = 'sergiojune' 7 | 8 | # 定义学生实例 9 | 10 | 11 | class Student(object): 12 | def __init__(self, name, score): 13 | ' 初始化实例,当创建实例时被调用这个函数,所以在实例化时需要传入这个函数的参数 ' 14 | self.name = name 15 | self.score = score 16 | 17 | def get_grade(self): 18 | '对数据进行封装' 19 | print('my name is %s' % self.name) 20 | if self.score > 90: 21 | print('your grade is A') 22 | elif self.score > 75: 23 | print('your grade is B') 24 | else: 25 | print('your grade is C') 26 | 27 | 28 | # bart = Student() 29 | # print(bart) 30 | # # 给实例初始化名字属性和成绩 31 | # bart.name = 'bart june' 32 | # bart.score = 98 33 | # print(Student) 34 | # print(bart.name) 35 | # print(bart.score) 36 | # 实例化 37 | tom = Student('Tom', 87) 38 | print(tom.name) 39 | print(tom.score) 40 | bob = Student('Bob', 65) 41 | # 调用实例方法 42 | bob.get_grade() 43 | -------------------------------------------------------------------------------- /test17.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习面向对象的访问限制' 5 | 6 | __author__ = 'sergiojune' 7 | 8 | # 定义实例 9 | class Student(object): 10 | def __init__(self, name, score): 11 | # 前面带了两个下划线表示对变量进行私有化,让外部不可以随意访问和修改 12 | # 但这个只是意识上私有而已,因为在外部我们可以通过 _类名__变量名 来访问,但不建议这样做,因为不同版本名字或许不一样 13 | # 所以私有了,一切靠自觉 14 | self.__name = name 15 | self.__score = score 16 | 17 | def get_grade(self): 18 | print('my name is %s,my grade is %d' % (self.__name,self.__score)) 19 | 20 | # 当外界需要获取时,可以单独写一个方法来获取和设置 21 | # 这样做的好处就是使用户不能随意修改,因为是方法,所以可以实现一些逻辑判断 22 | def get_name(self): 23 | return self.__name 24 | 25 | def get_score(self): 26 | return self.__score 27 | 28 | def set_name(self,name): 29 | if isinstance(name,str): 30 | self.__name = name 31 | else: 32 | raise ValueError('请输入正确名字') 33 | 34 | def set_score(self,score): 35 | if isinstance(score,int): 36 | self.__score = score 37 | else: 38 | raise ValueError('请输入正确的成绩') 39 | 40 | 41 | # 实例化 42 | bart = Student('Bart', 89) 43 | bart.get_grade() 44 | print(bart.get_name()) 45 | bart.set_score(56) 46 | print(bart.get_score()) 47 | # 这样访问私有变量,显然正确,但不推荐这样做 48 | print(bart._Student__name) 49 | # 但是你这样设置变量就错了 50 | bart.__name = 'new name' # 这样做只是给这个实例添加了__name 的属性,并不是修改了私有变量 51 | print(bart.get_name()) # 可以看出这个名字还是不变 52 | 53 | 54 | # 作业:把下面的Student对象的gender字段对外隐藏起来,用get_gender()和set_gender()代替,并检查参数有效性 55 | class StudentA(object): 56 | def __init__(self, name, gender): 57 | self.__name = name 58 | self.__gender = gender 59 | 60 | def get_name(self): 61 | return self.__name 62 | 63 | def get_gender(self): 64 | return self.__gender 65 | 66 | def set_name(self,name): 67 | if isinstance(name, str): 68 | self.__name = name 69 | else: 70 | raise ValueError('请输入字符串的名字') 71 | 72 | def set_gender(self,gender): 73 | if isinstance(gender, str): 74 | self.__gender = gender 75 | else: 76 | raise ValueError('请输入正确性别') 77 | 78 | 79 | # 检验是否正确 80 | bart = StudentA('Bart', 'male') 81 | if bart.get_gender() != 'male': 82 | print('测试失败!') 83 | else: 84 | bart.set_gender('female') 85 | if bart.get_gender() != 'female': 86 | print('测试失败!') 87 | else: 88 | print('测试成功!') -------------------------------------------------------------------------------- /test18.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习面向对象的继承和多态' 5 | 6 | __author__ = 'sergiojune' 7 | 8 | 9 | class Animal(object): 10 | def run(self): 11 | print('animal is running') 12 | 13 | 14 | # 继承Animal类 15 | class Dog(Animal): 16 | # 重载父类的方法 17 | def run(self): 18 | print('Dog is running') 19 | 20 | 21 | class Cat(Animal): 22 | def run(self): 23 | print('cat is running') 24 | 25 | 26 | def run_twich(animal): 27 | animal.run() 28 | animal.run() 29 | 30 | 31 | animal = Animal() 32 | dog = Dog() 33 | cat = Cat() 34 | # 类继承了Animal,所以类中不需要实现任何东西都可以有父类方法 35 | animal.run() 36 | dog.run() 37 | cat.run() 38 | # 这个方法只要是有run方法都可以运行,这就是多态的实现 39 | # 看起来像鸭子,走起路来像鸭子,那这个就是鸭子,这就是鸭子类型,动态语言的鸭子类型 40 | run_twich(animal) 41 | run_twich(dog) 42 | run_twich(cat) 43 | -------------------------------------------------------------------------------- /test19.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习面向对象的获取对象的属性和信息' 5 | 6 | __author__ = 'sergiojune' 7 | 8 | import types 9 | 10 | # 判断基本类型 11 | print(type('str')) 12 | print(type(12)) 13 | print(type(12.36)) 14 | 15 | 16 | def fn(): 17 | print('fn----') 18 | 19 | 20 | # 函数类型 21 | print(type(fn)) 22 | 23 | print(type('d') == str) 24 | print(type(56) == int) 25 | print(type(fn) == types.FunctionType) 26 | 27 | 28 | class Animal(object): 29 | def run(self): 30 | print('run ------') 31 | 32 | 33 | animal = Animal() 34 | print(type(animal)) 35 | # 内置函数类型 36 | print(type(abs)) 37 | 38 | 39 | # 还可以使用isinstance函数来进行判断类型 40 | print(isinstance(123, int)) 41 | print(isinstance('dd', str)) 42 | # 判断对象类型 43 | print(isinstance([1, 2], list)) 44 | print(isinstance({1: 2}, dict)) 45 | print(isinstance(fn, types.FunctionType)) 46 | print(isinstance(abs, types.BuiltinFunctionType)) 47 | print(isinstance(animal, Animal)) 48 | # 第二个参数可以写一个元组。里面的关系表示或 49 | print(isinstance([2, 3, 5], (list, tuple))) 50 | 51 | 52 | # 对对象的属性进行操作 53 | class MyDog(Animal): 54 | def __init__(self): 55 | self.x = 9 56 | 57 | # 这个方法就是调用len函数时被调用的方法 58 | def __len__(self): 59 | return 100 60 | 61 | def power(self): 62 | return self.x * self.x 63 | 64 | 65 | dog = MyDog() 66 | print(len(dog)) 67 | # 获取实例的属性列表 68 | print(dir(dog)) 69 | # 获取实例的属性 70 | print(getattr(dog, 'x')) 71 | # 可以设置默认值,当没有时就会返回默认值 72 | print(getattr(dog, 'high', 404)) 73 | # 设置属性 74 | setattr(dog, 'high', 0.86) 75 | # 获取上述设置的属性 76 | print(getattr(dog, 'high', 404)) 77 | # 还可以判断是否存在该属性 78 | print(hasattr(dog ,'x')) 79 | print(hasattr(dog, 'attr')) 80 | 81 | # 还可以获得实例的方法 82 | print(getattr(dog, 'power')) 83 | p = getattr(dog, 'power') 84 | # 下面这个p相当于 dog.power 85 | print(p()) 86 | -------------------------------------------------------------------------------- /test2.py: -------------------------------------------------------------------------------- 1 | # 练习python的递归函数 2 | 3 | 4 | # 用递归来求阶乘 5 | def func(num): 6 | if num == 1: 7 | return 1 8 | return func(num-1)*num 9 | 10 | 11 | # 求100的阶乘 12 | num = 100 13 | n = func(num) 14 | print('%d的阶乘是' % (num,), n) 15 | 16 | 17 | # 上面的函数如果n的数字过大的话就会出现栈溢出的问题,这是我们需要通过尾递归来优化 18 | def fact(num, product=1): 19 | if num == 1: 20 | return product 21 | return fact(num-1, num*product) 22 | 23 | 24 | # 虽然做了尾递归优化,但是该语言底层没有弄优化,所以还是求不了1000的阶乘 25 | num = 500 26 | n = fact(num) 27 | print('%d的阶乘是' % (num,), n) 28 | 29 | 30 | # 最后的作业,练习汉诺塔:move(n, a, b, c)函数,它接收参数n,表示3个柱子A、B、C中第1个柱子A的盘子数量,然后打印出把所有盘子从A借助B移动到C的方法 31 | def move(n, a, b, c): 32 | if n == 1: 33 | print(a, '-->', c) 34 | else: 35 | # 借助c柱将a的移动到c 36 | move(n-1, a, c, b) 37 | # 借助b柱将a的最后一根移动到c 38 | move(1, a, b, c) 39 | # 最后将b柱的借助a柱移动到c柱 40 | move(n-1, b, a, c) 41 | 42 | 43 | move(3, 'A', 'B', 'C') 44 | 45 | -------------------------------------------------------------------------------- /test20.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习面向对象的实例属性和类属性' 5 | 6 | __author__ = 'sergiojune' 7 | 8 | 9 | class Student(object): 10 | # 这个就是类属性 11 | name = 'student_name' 12 | def __init__(self,age): 13 | # 有self的就是实例属性 14 | self.age = age 15 | 16 | 17 | s1 = Student(15) 18 | s2 = Student(16) 19 | # 都是调用类属性 20 | print(Student.name) 21 | print(s1.name) 22 | print(s2.name) 23 | # 修改类属性 24 | Student.name = '_name' 25 | # 全部都变 26 | print(Student.name) 27 | print(s1.name) 28 | print(s2.name) 29 | # 若绑定同名的实例属性到实例中 30 | s1.name = "name_s1" 31 | # 类属性没有变 32 | print(Student.name) 33 | # 同名属性将类属性屏蔽了 34 | print(s1.name) 35 | # 此实例还有类属性 36 | print(s2.name) 37 | 38 | 39 | # 作业:为了统计学生人数,可以给Student类增加一个类属性,每创建一个实例,该属性自动增加 40 | class Stu(object): 41 | num = 0 42 | 43 | def __init__(self,name): 44 | Stu.num += 1 45 | self.name = name 46 | 47 | 48 | s1 = Stu('Bob') 49 | s2 = Stu('Tom') 50 | print(s2.num) 51 | -------------------------------------------------------------------------------- /test21.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习面向对象高级特性的__slots__属性' 5 | 6 | __author__ = 'sergiojune' 7 | from types import MethodType 8 | 9 | class MyObject(object): 10 | pass 11 | 12 | 13 | o = MyObject() 14 | # 动态绑定属性 15 | o.name = 'object' 16 | print(o.name) 17 | 18 | 19 | # 也可以动态绑定方法 20 | def get_info(self): 21 | print('动态绑定的方法') 22 | 23 | 24 | o.get_info = MethodType(get_info, o) 25 | o.get_info() 26 | # 动态绑定的方法和属性对其他实例无效 27 | oo = MyObject() 28 | # oo.get_info() 29 | # 此时可以动态绑定在类中 30 | MyObject.get_info = get_info 31 | # 这样就可以了 32 | oo.get_info() 33 | 34 | 35 | # 为了防止用户乱绑定属性,python中加了个__slots__属性,来限制动态绑定的属性 36 | class Student(object): 37 | # 值是一个元组。里面表示的是可以动态绑定的属性 38 | __slots__ = ('name', 'age') 39 | 40 | def __init__(self,name): 41 | self.name = name 42 | 43 | 44 | s1 = Student('Bob') 45 | s1.age = 100 46 | print(s1.age) 47 | # 下面这个就会报错:AttributeError: 'Student' object has no attribute 'scoer' 48 | # s1.scoer = 85 49 | # 绑定方法也会报同样的错误 50 | # s1.get_info = MethodType(get_info, s1) 51 | 52 | 53 | # 使用了__slots__属性时,其子类不受限制 54 | class MyStudent(Student): 55 | pass 56 | 57 | 58 | m = MyStudent('bart') 59 | # 这个就不会报错,要想限制也需要单独加那个属性 60 | m.score = 100 61 | 62 | 63 | -------------------------------------------------------------------------------- /test22.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习面向对象高级特性的@property' 5 | 6 | __author__ = 'sergiojune' 7 | 8 | 9 | class Student(object): 10 | def __init__(self, name, score): 11 | self.__name = name 12 | self.__score = score 13 | 14 | def get_name(self): 15 | return self.__name 16 | 17 | def get_score(self): 18 | return self.__score 19 | 20 | def set_name(self, name): 21 | if not isinstance(name, str): 22 | raise ValueError('请输入正确的名字') 23 | self.__name = name 24 | 25 | def set_score(self, score): 26 | if score < 0 or score > 100: 27 | raise ValueError('请输入正确的成绩') 28 | elif not isinstance(score, int): 29 | raise ValueError('请输入正确的成绩') 30 | else: 31 | self.__score = score 32 | 33 | 34 | stu = Student('bob', 86) 35 | print(stu.get_name()) 36 | # 这个就会报错 37 | # stu.set_score(999) 38 | 39 | 40 | # 使用@property装饰器 41 | class People(object): 42 | def __init__(self, name, age): 43 | self.__name = name 44 | self.__age = age 45 | 46 | @property # 添加装饰器,让这个方法变成一个属性 47 | def age(self): 48 | return self.__age 49 | 50 | @property 51 | def name(self): 52 | return self.__name 53 | 54 | @name.setter # 这个前缀名字要和property装饰器的方法名字一致 55 | def name(self, name): 56 | if not isinstance(name, str): 57 | raise ValueError('请输入正确名字') 58 | self.__name = name 59 | 60 | 61 | p = People('bart', 20) 62 | # 加了装饰器之后这样直接调用属性 63 | print(p.name) # 这个就是直接获取name属性 64 | p.name = 'bat' # 直接修改属性 65 | print(p.name) 66 | print(p.age) 67 | # 由于age只是只读,不予许写,所以这个会报错 68 | # p.age = 52 69 | 70 | 71 | # 作业:请利用@property给一个Screen对象加上width和height属性,以及一个只读属性resolution 72 | class Screen(object): 73 | def __init__(self): 74 | self.__width = None 75 | self.__height = None 76 | 77 | @property 78 | def width(self): 79 | return self.__width 80 | 81 | @property 82 | def height(self): 83 | return self.__height 84 | 85 | @width.setter 86 | def width(self,width): 87 | if width < 0 or width > 1000: 88 | raise ValueError('请输入正确的宽') 89 | self.__width = width 90 | 91 | @height.setter 92 | def height(self, height): 93 | if height < 0 or height > 1000: 94 | raise ValueError('请输入正确的高') 95 | self.__height = height 96 | 97 | @property 98 | def resolution(self): 99 | self.__resolution = (self.__height, self.__width) 100 | return self.__resolution 101 | 102 | 103 | screen = Screen() 104 | screen.width = 25 105 | screen.height = 65 106 | print(screen.width) 107 | print(screen.height) 108 | print(screen.resolution) 109 | -------------------------------------------------------------------------------- /test23.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习面向对象高级特性的多继承' 5 | 6 | __author__ = 'sergiojune' 7 | 8 | 9 | class Animal(object): 10 | pass 11 | 12 | 13 | class Bird(Animal): 14 | pass 15 | 16 | 17 | class Mammal(Animal): 18 | pass 19 | 20 | 21 | # 加个扩展功能 22 | class Flyable(object): 23 | def fly(self): 24 | print('fly------------') 25 | 26 | 27 | class Runnable(object): 28 | def run(self): 29 | print('run-----------') 30 | 31 | 32 | # 这样就是多继承,加了和功能 33 | class Dog(Mammal, Runnable): 34 | pass 35 | 36 | 37 | # 多继承从做往右继承,在父类中有相同的方法时就会先实现左边的方法,就近原则 38 | class Parrot(Bird, Flyable): 39 | pass 40 | 41 | -------------------------------------------------------------------------------- /test24.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习面向对象的高级特性的定制类' 5 | 6 | __author__ = 'sergiojune' 7 | 8 | 9 | class Fib(object): 10 | # 在实例化时会调用该方法 11 | def __init__(self): 12 | self.name = 'Fib' 13 | self.a = 0 14 | self.b = 1 15 | 16 | # 在调用len方法时实际调用的是该方法 17 | def __len__(self): 18 | return 100 19 | 20 | # 在打印实例信息时调用该方法 21 | def __str__(self): 22 | return 'object name is %s' % (self.name) 23 | 24 | # 因为一般这两个方法代码一样,所以这样做 25 | __repr__ = __str__ 26 | 27 | # 这个方法让实例可迭代,返回的是一个可迭代对象 28 | def __iter__(self): 29 | return self 30 | 31 | # 这个方法当实例用于for循环时会被调用,与list,tuple类似 32 | def __next__(self): 33 | self.a, self.b = self.b, self.a + self.b 34 | # 到达指定数目就返回一个异常 35 | if self.a > 100000: 36 | raise StopIteration 37 | return self.a 38 | 39 | # 该方法当实例在用下标取元素时被调用,传入切片也是调用这个函数 40 | # 该方法也可以像dict那样用键来获取值,判断参数是否是字符串即可 41 | def __getitem__(self, num): 42 | # 对参数进行判断 43 | if isinstance(num, slice): 44 | start = num.start 45 | end = num.stop 46 | step = num.step 47 | # 开头可能不填 48 | start = start if start else 0 49 | # 步长也一样 50 | step = step if step else 0 51 | L = [] 52 | if step == 0: 53 | for x in range(start, end): 54 | L.append(Fib()[x]) 55 | else: 56 | for x in range(start, end, step): 57 | L.append(Fib()[x]) 58 | return L 59 | else: 60 | n = 0 61 | for x in Fib(): 62 | if n == num: 63 | return x 64 | n += 1 65 | 66 | # 该方法当用下标设置对应值时被调用,也可以像dict一样的赋值 67 | def __setitem__(self, index, value): 68 | # 和上面的差不多,就不实现了 69 | pass 70 | 71 | # __delitem__():方法是当删除某个值时就会被调用 72 | 73 | 74 | fib = Fib() 75 | print(len(fib)) 76 | # 打印实例 77 | print(Fib()) 78 | # 打印有变量指向的实例信息 79 | print(fib) 80 | # 用类实现斐波那契数列 81 | for x in fib: 82 | print(x) 83 | print('-----------') 84 | print(fib[5]) 85 | # 切片 86 | print(fib[1:5]) 87 | # 有步长 88 | print(fib[5:1:-2]) 89 | 90 | 91 | class Student(object): 92 | def __init__(self, name): 93 | self.name = name 94 | 95 | # 这个方法当实例方法不存在的属性时被调用 96 | def __getattr__(self, name): 97 | if name == 'score': 98 | return 99 99 | raise AttributeError('\'Student\' object has no attribute \'%s\'' % name) 100 | 101 | # 这个方法就是当实例当函数被调用时调用这个方法,还可以传参数 102 | def __call__(self): 103 | print('call Student') 104 | 105 | 106 | stu = Student('bart') 107 | print(stu) 108 | # 访问不存在的属性,加了__getattr__方法后就不会报错 109 | print(stu.score) 110 | # print(stu.j) 111 | # 将实例当函数调用 112 | stu() 113 | # 判断对象是否可被调用 114 | print(callable(stu)) 115 | print(callable([1])) 116 | print(callable(fib)) 117 | 118 | 119 | # 实现教程中的Chain().users('michael').repos 得到 GET /users/:user/repos 120 | class Chain(): 121 | def __init__(self, path='GET'): 122 | self.path = path 123 | 124 | def __getattr__(self, path): 125 | if path: 126 | return Chain('%s/%s' % (self.path, path)) 127 | 128 | def __str__(self): 129 | return self.path 130 | 131 | def __call__(self, user): 132 | return Chain('%s/:%s' % (self.path, user)) 133 | 134 | 135 | chain = Chain() 136 | print(Chain().users('michael').repos) 137 | -------------------------------------------------------------------------------- /test25.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习面向对象的高级特性的枚举' 5 | 6 | __author__ = 'sergiojune' 7 | from enum import Enum, unique 8 | 9 | 10 | # 使用枚举 11 | # 12 | Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')) 13 | # 获取每一个成员,value是自动生成的,从 1 开始 14 | for month,member in Month.__members__.items(): 15 | print(month, '=>', member, member.value) 16 | 17 | 18 | # 可以继承枚举来实现枚举类 19 | @unique # 这个装饰器是让枚举的键固定值,并且不能相同 20 | class Weekday(Enum): 21 | # 这样就实现了枚举类 22 | Sun = 0 23 | Mon = 1 24 | Tue = 2 25 | Wed = 3 26 | Thu = 4 27 | Fri = 5 28 | Sat = 6 29 | 30 | 31 | # 访问枚举类的值 32 | print(Weekday.Sun) 33 | print(Weekday(1)) 34 | print(Weekday['Wed']) 35 | num =4 36 | # 这个访问值 37 | print(Weekday(4).value == num) 38 | # 这个访问键 39 | print(Weekday(4) == num) 40 | for day, member in Weekday.__members__.items(): 41 | print(day, '=>', member) 42 | 43 | 44 | # 作业:把Student的gender属性改造为枚举类型,可以避免使用字符串 45 | class Gender(Enum): 46 | Male = 0 47 | Female = 1 48 | 49 | 50 | class Student(object): 51 | def __init__(self, name, gender): 52 | self.name = name 53 | self.gender = gender 54 | 55 | 56 | # 测试: 57 | bart = Student('Bart', Gender.Male) 58 | if bart.gender == Gender.Male: 59 | print('测试通过!') 60 | else: 61 | print('测试失败!') 62 | -------------------------------------------------------------------------------- /test26.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习错误处理' 5 | 6 | __author__ = 'sergiojune' 7 | import logging 8 | from functools import reduce 9 | 10 | 11 | def foo(n): 12 | # 自定义抛出错误 13 | if n == 0: 14 | raise ZeroDivisionError('被除数不能为零') 15 | return 10 / n 16 | 17 | 18 | print(foo(20)) 19 | # 这个就会出错 20 | # print(foo(0)) 21 | 22 | 23 | # 捕捉错误 24 | try: 25 | n = input('请输入一个数字') 26 | n = int(n) 27 | res = 10 / n 28 | print(res) 29 | # 有多种异常情况,所以有多个except语句块 30 | except ZeroDivisionError as e: 31 | print(e) 32 | except ValueError as e: 33 | # 用这个记录错误,开发中会发在日志上查看 34 | logging.exception(e) 35 | 36 | # 当没有发生错误时会执行 37 | else: 38 | print('成功运行') 39 | # 这个语句块是必须执行的 40 | finally: 41 | print('代码执行完毕') 42 | 43 | print('end') 44 | 45 | 46 | # 还可以自己创建异常 47 | # 只需要继承自某一个异常就可以了,不过一般不需要自定义异常 48 | class FooException(BaseException): 49 | pass 50 | 51 | 52 | # 作业:运行下面的代码,根据异常信息进行分析,定位出错误源头,并修复 53 | def str2num(s): 54 | try: 55 | return int(s) 56 | except ValueError as e: 57 | logging.exception(e) 58 | print('捕捉成功') 59 | try: 60 | return float(s) 61 | except ValueError as e: 62 | print(e) 63 | print('输入的内容不是数字') 64 | 65 | 66 | def calc(exp): 67 | try: 68 | ss = exp.split('+') 69 | ns = map(str2num, ss) 70 | return reduce(lambda acc, x: acc + x, ns) 71 | except TypeError as e: 72 | print(e) 73 | 74 | 75 | def main(): 76 | r = calc('100 + 200 + 345') 77 | print('100 + 200 + 345 =', r) 78 | r = calc('99 + 88 + 7.6') 79 | print('99 + 88 + 7.6 =', r) 80 | 81 | 82 | main() 83 | print('end') 84 | -------------------------------------------------------------------------------- /test27.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习调试程序' 5 | 6 | __author__ = 'sergiojune' 7 | import logging 8 | import pdb 9 | # 这个标明打印信息的类别,不标明不会打印具体的错误信息 10 | logging.basicConfig(level=logging.INFO) 11 | 12 | 13 | def foo(n): 14 | # if n == 0: 15 | # # 这个麻烦,可以用断言,这样没有输出 16 | # print('n is zero !') 17 | # else: 18 | # return 10 / n 19 | # 这个当条件为false时,就会执行后面语句,并抛出assertionError 20 | assert n != 0, 'n is zero !' 21 | return 10/n 22 | 23 | 24 | foo(1) 25 | 26 | s = '0' 27 | n = int(s) 28 | # 开发中用这个较多 29 | logging.info('n = %d' % n) 30 | print(10 / n) 31 | 32 | # 还可以用pdb进行调试 33 | s = '0' 34 | n = int(s) 35 | # 这个就是设置断点 36 | pdb.set_trace() 37 | logging.info('n = %d' % n) 38 | print(10 / n) 39 | -------------------------------------------------------------------------------- /test28.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习读取文件' 5 | 6 | __author__ = 'sergiojune' 7 | 8 | 9 | # 默认编码方式是gbk,而编译器是utf-8,所以需要指定编码方式 10 | f = open('./test27.py', 'r', encoding='utf-8') 11 | # 读取文件全部内容,有一个参数为读取文件的大小 12 | # 当文件较小时可以这样读 13 | # txt = f. read() 14 | # print(txt) 15 | 16 | # 还可以这样一行一行读 17 | print(f.readline()) 18 | # 以一行行形式读全部内容 19 | for line in f.readlines(): 20 | print(line) 21 | # 最后记得关闭文件 22 | f.close() 23 | 24 | 25 | # 当文件出现异常时,或许关闭不了文件,就需要捕捉异常 26 | try: 27 | f = open('./test26.py', 'r', encoding='utf-8') 28 | for x in f.readlines(): 29 | print(x) 30 | except IOError as e: 31 | print(e) 32 | finally: 33 | # 最后一定关闭 34 | if f: 35 | f.close() 36 | 37 | 38 | # 如果每次都需要这样捕捉异常,就会很麻烦,python中可以用with语句块来处理 39 | with open('./test27.py', 'r', encoding='utf-8') as f: 40 | # 当离开这个语句块就会自动关闭,就不需要我们来关闭 41 | txt = f.read() 42 | print(txt) 43 | 44 | 45 | # 作业:请将本地一个文本文件读为一个str并打印出来 46 | # 上面的就是了,参考上面的 47 | -------------------------------------------------------------------------------- /test29.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习读取StingIO和BytesIO' 5 | 6 | __author__ = 'sergiojune' 7 | from io import StringIO, BytesIO 8 | 9 | # StingIO和BytesIO 和在内存中读取数据,不是在文件中读取数据 10 | s = StringIO('hello\nhi\ngood!\nheadsome boy') # 创建 11 | # 进行读取,与文件读取差不多 12 | for x in s.readlines(): 13 | print(x) 14 | # 也可以这样创建 15 | s = StringIO() 16 | s.write('hello') 17 | s.write(' ') 18 | s.write('world') 19 | print(s.getvalue()) 20 | 21 | 22 | # 这时BytesIO的练习,bytesIO是写入字节码,而SrtingIO是写入str 23 | b = BytesIO('中文'.encode('utf-8')) 24 | # print(b.getvalue()) 25 | print(b.read()) 26 | -------------------------------------------------------------------------------- /test3.py: -------------------------------------------------------------------------------- 1 | # 练习列表的切片 2 | # 切片是产生一个新的列表,不会修改原来的列表 3 | 4 | 5 | l = ['john','miss','mike','jack','amy'] 6 | # 获取前三位元素,切片一样包头不包尾 7 | print(l[0:3]) 8 | # 获取后三位元素 9 | print(l[2:]) 10 | # 支持负数的哈,往后数第一个为-1 11 | print(l[-3:]) 12 | # 完全复制一个列表 13 | print(l[:]) 14 | # 按步长来取元素,步长为2 15 | print(l[::2]) 16 | 17 | # tuple也可以切片操作 18 | t=(1,2,3,4,5,78,9,10) 19 | print(t[::3]) 20 | 21 | # 而字符串也支持切片操作,因为他也是一个序列 22 | s = 'sergiojune' 23 | print(s[-4:]) 24 | 25 | 26 | # 作业:利用切片操作,实现一个trim()函数,去除字符串首尾的空格 27 | def trim(str): 28 | n1 = 0 29 | n2 = len(str)-1 30 | for num in range(len(str)): 31 | if str[num] == ' ': 32 | continue 33 | else: 34 | n1 = num 35 | break 36 | for num in range(n1,len(str),-1): 37 | if str[num] == ' ': 38 | continue 39 | else: 40 | n2 = num 41 | break 42 | return str[n1:n2+1] 43 | 44 | 45 | # 上述方法较复杂,参考了别人的写法,重新写 46 | def trim2(str): 47 | while True: 48 | if str[0] == ' ': 49 | str = str[1:] 50 | else: 51 | break 52 | while True: 53 | if str[-1] == ' ': 54 | str = str[0:-1] 55 | else: 56 | break 57 | 58 | return str 59 | 60 | 61 | s = ' hello world ' 62 | print(trim2(s)) -------------------------------------------------------------------------------- /test30.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习操作文件和目录' 5 | 6 | __author__ = 'sergiojune' 7 | import os 8 | from datetime import datetime 9 | 10 | # 获取操作系统的类型 11 | print(os.name) 12 | # window操作系统没有这个函数,在mac,linux下就会有 13 | # print(os.uname()) 14 | 15 | # 环境变量 16 | print(os.environ) 17 | # 获取某个环境变量的值 18 | print(os.environ.get('path')) 19 | 20 | # 查看当前目录的绝对路径 21 | print(os.path.abspath('.')) # . 表示当前路径 22 | 23 | # 添加目录 24 | name = os.path.join(os.path.abspath('.'), 'testtest') # 这步是解决不同系统目录名不一样的写法,是以目录形式合并两个参数 25 | print(name) 26 | # 用上面的结果来添加目录 27 | # os.mkdir(name) 28 | # 删除目录 29 | # os.rmdir(name) 30 | 31 | name = os.path.join(os.path.abspath('.'), 'test29.py') 32 | print(name) 33 | # 分割路径,会分出文件名和目录名 34 | l = os.path.split(name) 35 | print(l) 36 | # 也可以直接分出文件名的后缀 37 | t = os.path.splitext(name) 38 | print(t) 39 | # 重命名 40 | # os.rename('test.txt', 'test.md') 41 | # 删除文件 42 | # os.remove('test.md') 43 | # 找出目标路径是目录的名字 44 | d = [x for x in os.listdir(r'E:\anaconda\python_project') if not os.path.isdir(x)] 45 | print(d) 46 | 47 | 48 | # 作业 1 :利用os模块编写一个能实现dir -l输出的程序。 49 | print('%s%30s' % ('type', 'name')) 50 | for x in os.listdir(r'E:\anaconda\python_project'): 51 | # 判断是否是文件 52 | if os.path.isfile(x): 53 | file = os.path.splitext(x)[1] 54 | file = file.split('.')[1] 55 | print('%s%30s' % (file+' file', x)) 56 | else: 57 | print('%s%30s' % ('folder', x)) 58 | 59 | 60 | # 作业2:编写一个程序,能在当前目录以及当前目录的所有子目录下查找文件名包含指定字符串的文件,并打印出相对路径 61 | def find_dir(path, name, dirs=[]): 62 | for x in os.listdir(path): 63 | if os.path.isfile(path+'\\'+x): 64 | # 文件中有指定字符串 65 | if name in x: 66 | dirs.append(path+'\\'+x) 67 | # 文件夹 68 | else: 69 | if name in x: 70 | dirs.append(path+'\\'+x) 71 | # 递归 72 | find_dir(os.path.join(path, x), name) 73 | return dirs 74 | 75 | 76 | d = find_dir(r'E:\anaconda\python_project', 'py') 77 | print(d) 78 | 79 | # 获取文件创建的时间 80 | print(os.path.getmtime(d[0])) 81 | print(datetime.fromtimestamp(os.path.getmtime(d[0])).strftime('%Y-%m-%d %H:%M:%S') ) 82 | # 获取文件大小 83 | print(os.path.getsize(d[0])//1024, 'KB') 84 | 85 | -------------------------------------------------------------------------------- /test31.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习序列化和反序列化' 5 | 6 | __author__ = 'sergiojune' 7 | import pickle 8 | import json 9 | d = {'name': 'bob', 'age': 20, 'score': 80} 10 | # 序列化,这个是序列化成bytes 11 | p = pickle.dumps(d) 12 | print(p) 13 | # 这个序列化后直接存在指定文件 14 | with open('pickle.txt', 'wb') as f: 15 | pickle.dump(d, f) 16 | 17 | # 反序列化 18 | # 这个是将bytes反序列化 19 | p = pickle.loads(p) 20 | print(p) 21 | # 这个是将文件反序列化 22 | with open('pickle.txt', 'rb') as f: 23 | d = pickle.load(f) 24 | print(d) 25 | 26 | 27 | # 若要在个语言之间相互传递对象,这时就需要序列化成JSON或XML等格式 28 | # 这里序列化成JSON,用的是json库 29 | d = {'name': 'bart', 'age': 22, 'score': 76} 30 | j = json.dumps(d) 31 | print(j) 32 | # 序列化后写入文件 33 | with open('json.txt', 'w') as f: 34 | json.dump(d, f) 35 | # 反序列化 36 | f = json.loads(j) 37 | print(f) 38 | # 从文件中反序列化 39 | with open('json.txt', 'r') as f: 40 | w = json.load(f) 41 | print('文件:', w) 42 | 43 | 44 | # 序列化自定义类 45 | class Student(object): 46 | def __init__(self, name, age, score): 47 | self.name = name 48 | self. age = age 49 | self.score = score 50 | 51 | 52 | s = Student('tom', 23, 68) 53 | # 这个是获取对象的字典形式 54 | print(s.__dict__) 55 | # 直接序列化会出错,抛TypeError: Object of type 'Student' is not JSON serializable,说该对象不可序列化 56 | # o = json.dumps(s) 57 | # 对自定义对象序列化需要自己先将对象转换成字典才能序列化 58 | 59 | 60 | # 将student转换成字典 61 | def student2dict(obj): 62 | return {'name': obj.name, 63 | 'age': obj.age, 64 | 'score': obj.score} 65 | 66 | 67 | # 现在序列化 68 | o = json.dumps(s, default=student2dict) 69 | print(o) 70 | # 可以利用类的特性和匿名函数一行代码进行序列化 71 | o1 = json.dumps(s, default=lambda obj: obj.__dict__) 72 | print('简易序列化', o1) 73 | 74 | # 反序列化 75 | 76 | 77 | # 在自定义类中,同样也需要加个函数将序列化后的字典转换成对象的对象 78 | def dict2student(d): 79 | return Student(d['name'], d['age'], d['score']) 80 | 81 | 82 | fan = json.loads(o, object_hook=dict2student) 83 | # 这样就获取到student对象 84 | print(fan) 85 | 86 | 87 | # 作业:对中文进行JSON序列化时,json.dumps()提供了一个ensure_ascii参数,观察该参数对结果的影响 88 | obj = dict(name='小明', age=20) 89 | # 当ensure_ascii为True,会对中文进行编码 90 | s = json.dumps(obj, ensure_ascii=True) 91 | print(s) 92 | # 当ensure_ascii为False,不会对中文进行编码 93 | s = json.dumps(obj, ensure_ascii=False) 94 | print(s) 95 | -------------------------------------------------------------------------------- /test32.py: -------------------------------------------------------------------------------- 1 | #!/ussr/bin/env python 3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习多进程与进程间通信' 5 | 6 | __author__ = 'sergiojune' 7 | from multiprocessing import Process, Pool, Queue 8 | import os 9 | import time 10 | from random import random 11 | 12 | 13 | 14 | # print('parent process(%s) is running' % os.getpid()) 15 | # 定义子进程需要运行的函数 16 | # def run(name): 17 | # print('I am runing,I is process(%s)' % os.getpid()) 18 | # 在使用这个进程时,需要使用if __name__ == '__main__这个语句来开父进程,要不会出错 19 | # if __name__ == '__main__': 20 | # # 创建子进程 21 | # p = Process(target=run, args=('test',)) 22 | # # 开启进程 23 | # p.start() 24 | # # 让子进程运行完再运行下面的父进程 25 | # p.join() 26 | # print('End...........') 27 | 28 | 29 | 30 | # 使用进程池批量开启进程 31 | # def run(name): 32 | # print('task %s is running, process %s' % (name, os.getpid())) 33 | # start = time.time() 34 | # time.sleep(random()*3) 35 | # end = time.time() 36 | # print('%s is run %0.2f seconds process %s' % (name, (end - start), os.getpid())) 37 | # 38 | # 39 | # if __name__ == '__main__': # 开启多进程这个语句是必须的 40 | # print('parent process %s is running' % os.getpid()) 41 | # # 创建进程池 42 | # p = Pool(4) 43 | # for x in range(5): 44 | # p.apply_async(run, args=(x,)) 45 | # # 关闭进程池,不能再添加进程 46 | # p.close() 47 | # # 要实现这个方法之前必须关闭进程池 48 | # p.join() 49 | # print('parent process %s end' % os.getpid()) 50 | 51 | 52 | 53 | # 实现进程间通信 54 | def write(q): 55 | print('process %s is writing' % os.getpid()) 56 | for x in 'ABC': 57 | q.put(x) 58 | print(' %s write %s' % (os.getpid(), x)) 59 | 60 | 61 | def read(q): 62 | print('process %s is read' % os.getpid()) 63 | while True: 64 | value = q.get(True) 65 | print('info is %s' % value) 66 | 67 | 68 | if __name__ == '__main__': 69 | q = Queue() 70 | print('parent is running') 71 | pw = Process(target=write, args=(q,)) 72 | pr = Process(target=read, args=(q,)) 73 | # 开启进程 74 | pw.start() 75 | pr.start() 76 | pw.join() 77 | # 由于read方法不能自行停止,所以需要强制tingz 78 | pr.terminate() 79 | print('end------') 80 | -------------------------------------------------------------------------------- /test33.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习多线程' 5 | 6 | __author__ = 'sergiojune' 7 | import threading 8 | import multiprocessing 9 | 10 | 11 | def run(): 12 | print('thread %s is running' % threading.current_thread().name) 13 | for x in range(5): 14 | print('thread %s ==> %d' % (threading.current_thread().name, x)) 15 | print('thread %s end' % threading.current_thread().name) 16 | 17 | 18 | print('thraed %s is running' % threading.current_thread().name) 19 | t = threading.Thread(target=run, name='loopthread') 20 | # 开启线程 21 | t.start() 22 | t.join() 23 | print('thread %s is end' % threading.current_thread().name) 24 | 25 | 26 | # 多线程的锁 27 | balance = 0 28 | def change(n): 29 | global balance 30 | balance = balance + n 31 | balance = balance - n 32 | print(balance) 33 | 34 | 35 | def run_thread(): 36 | l = threading.Lock() 37 | for x in range(1, 100000): 38 | try: 39 | # 获取锁 40 | l.acquire() 41 | change(x) 42 | finally: 43 | # 释放锁 44 | l.release() 45 | 46 | 47 | t1 = threading.Thread(target=run_thread) 48 | t2 = threading.Thread(target=run_thread()) 49 | t1.start() 50 | t2.start() 51 | t1.join() 52 | t2.join() 53 | print('end') 54 | 55 | 56 | def loop(): 57 | x = 0 58 | while True: 59 | x = x ^ 1 60 | 61 | 62 | for x in range(multiprocessing.cpu_count()): # 根据cpu的数量来开线程 63 | t = threading.Thread(target=loop) 64 | t.start() 65 | 66 | -------------------------------------------------------------------------------- /test35.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习分布式进程 ' 5 | 6 | __author__ = 'sergiojune' 7 | import queue, random 8 | from multiprocessing.managers import BaseManager 9 | # 此文件用来发送和接受结果,test36.py用于处理结果 10 | 11 | # 创建通信工具 12 | # 发送任务 13 | post_task = queue.Queue() 14 | # 接受结果 15 | result_task = queue.Queue() 16 | 17 | 18 | class QueueManager(BaseManager): 19 | pass 20 | 21 | 22 | # 定义的函数解决下面的坑 23 | def posttq(): 24 | return post_task 25 | 26 | 27 | def resulttq(): 28 | return result_task 29 | 30 | 31 | def start(): 32 | # 注册任务 33 | # 这里有个坑,在window系统下callable不能为匿名函数,原因是不能被序列化,所以在这里我们需要定义函数 34 | QueueManager.register('post_task_queue', callable=posttq) # 第一个参数为注册名字 35 | QueueManager.register('result_task_queue', callable=resulttq) 36 | 37 | # 绑定窗口,设置验证码 38 | manager = QueueManager(address=('127.0.0.1', 500), authkey=b'abc') # 第一个参数为地址和端口,第二个参数为验证码,防止别人骚扰 39 | 40 | # 启动管理 41 | manager.start() 42 | # 通过管理器获取通信 43 | post = manager.post_task_queue() 44 | result = manager.result_task_queue() 45 | 46 | # 进行发送数据 47 | print('try post data') 48 | for x in range(10): 49 | n = random.randint(1, 1000000) 50 | print('put %d' % n) 51 | post.put(n) 52 | 53 | # 接受结果 54 | print('try get result') 55 | for x in range(10): 56 | # timeout表示超时获取数的最长时间 57 | value = result.get(timeout=10) 58 | print('get result', value) 59 | 60 | # 关闭管理器 61 | manager.shutdown() 62 | print('master end') 63 | 64 | 65 | if __name__ == '__main__': 66 | start() 67 | -------------------------------------------------------------------------------- /test36.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '处理分布式进程发送的数据' 5 | 6 | __author__ = 'sergiojune' 7 | from multiprocessing.managers import BaseManager 8 | import time, queue 9 | 10 | 11 | class QueueManager(BaseManager): 12 | pass 13 | 14 | 15 | # 注册到网络上 16 | QueueManager.register('post_task_queue') # 由于只是从网络上获取queue,所以不需要写callable方法 17 | QueueManager.register('result_task_queue') 18 | # 连接到网络 19 | address = '127.0.0.1' # 这个是网络地址 20 | manager = QueueManager(address=(address, 500), authkey=b'abc') # 这些必须与发送的一致,要不会连不上 21 | # 连接 22 | manager.connect() 23 | # 获取queue 24 | post = manager.post_task_queue() 25 | result = manager.result_task_queue() 26 | 27 | # 处理数据 28 | print('tyr get value') 29 | for x in range(10): 30 | try: 31 | v = post.get(timeout=10) 32 | print('get value %d' % v) 33 | r = v*v 34 | print('put value %d to result' % r) 35 | time.sleep(1) 36 | result.put(r) 37 | except queue.Empty as e: 38 | print('Queue is empty') 39 | print('work exit') 40 | -------------------------------------------------------------------------------- /test37.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习正则表达式' 5 | 6 | __author__ = 'sergiojune' 7 | import re 8 | 9 | 10 | # 作业:尝试写一个验证Email地址的正则表达式。版本一应该可以验证出类似的Email 11 | a = 'someone@gmail.com' 12 | b = 'bill.gates@microsoft.com' 13 | # 匹配邮箱的正则表达式,返回一个正则对象 14 | re_mail = re.compile('[\.\w]*@[\w]+.[\w]+') 15 | m = re_mail.match(a) 16 | print(m.group()) 17 | g = re_mail.match(b) 18 | print(g.group()) 19 | 20 | 21 | # 版本二: 22 | a = ' tom@voyager.org => Tom Paris' 23 | b = 'bob@example.com => bob' 24 | mail = re.compile('([\w]+|[<>\w\s]+)@[\w]+.[\w]+') 25 | aa = mail.match(a) 26 | bb = mail.match(b) 27 | print(aa.group()) 28 | print(bb.group()) 29 | -------------------------------------------------------------------------------- /test38.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习内建模块致datetime' 5 | 6 | __author__ = 'sergiojune' 7 | from datetime import datetime, timedelta, timezone 8 | import re 9 | 10 | # 获取现在时间 11 | dt = datetime.now() 12 | print(dt) 13 | print(type(dt)) 14 | 15 | # 获取指定某日的时间,即是创建实例 16 | ddt = datetime(2017, 10, 15, 12, 35, 56) 17 | print(ddt) # 类型为datetime.datetime 18 | 19 | # 将datetime转为timestamp 20 | ts = dt.timestamp() 21 | print(ts) 22 | print(type(ts)) # 类型为float 23 | # 将timestamp转为datetime 24 | d = datetime.fromtimestamp(ts) 25 | print(d) 26 | # 将timestamp转为标准的utc时间,比北京时间少了八小时 27 | d = datetime.utcfromtimestamp(ts) 28 | print(d) 29 | 30 | # 将字符串转为时间 31 | s = '2017:12:12 11:11:11' 32 | sd = datetime.strptime(s, '%Y:%m:%d %H:%M:%S') # 第二个参数为字符串的时间格式 33 | print(sd) 34 | print(type(sd)) 35 | 36 | # 将时间转为字符串,参数为转为字符串的格式 37 | ds = sd.strftime('%Y:%m:%d %H:%M:%S') 38 | print(ds) 39 | print(type(ds)) 40 | 41 | 42 | # 将时间进行加减 43 | print('之前:', dt) 44 | dt = dt + timedelta(hours=5,minutes=25) 45 | print(dt) 46 | dt = dt + timedelta(days=5) 47 | print(dt) 48 | 49 | print('-------------------') 50 | # 将本地datetime设一个时区 51 | tz_local = timezone(timedelta(hours=8)) 52 | d = datetime.now() 53 | print(d) 54 | # 强行设置时区,tzinfo就是时区信息 55 | now = d.replace(tzinfo=tz_local) 56 | print(now) 57 | 58 | print('----------------------') 59 | # 时区时间任意转换 60 | # 拿到utc时间,并设置时区 61 | d = datetime.utcnow().replace(tzinfo=timezone.utc) 62 | print(d) 63 | # 转为北京时间的时区 64 | bj_utc = d.astimezone(tz=timezone(timedelta(hours=8))) 65 | print(bj_utc) 66 | # 转为东京时间 67 | dj_utc = d.astimezone(tz=timezone(timedelta(hours=9))) 68 | print(dj_utc) 69 | # 也可以直接利用北京时间转为东京时间 70 | dj_utc = bj_utc.astimezone(tz=timezone(timedelta(hours=9))) 71 | print(dj_utc) 72 | # 所以用astimezone()这个方法可以任意转换时区 73 | 74 | 75 | # 作业:假设你获取了用户输入的日期和时间如2015-1-21 9:01:30,以及一个时区信息如UTC+5:00,均是str,请编写一个函数将其转换为timestamp 76 | def to_timestamp(time, tz): 77 | # 将字符串转为时间 78 | time = datetime.strptime(time, '%Y-%m-%d %H:%M:%S') 79 | # 设置该时间的时区 80 | time = time.replace(tzinfo=timezone(timedelta(hours=tz))) 81 | time = time.timestamp() 82 | return time 83 | 84 | 85 | print('---------------') 86 | time1 = '2015-6-1 08:10:30' 87 | utc1 = 'UTC+7:00' 88 | # 用正则匹配出时间 89 | utc1 = int(re.search('UTC([+-][\d]{1,2}):[\d]{2}', utc1).group(1)) 90 | print(utc1) 91 | time = to_timestamp(time1, utc1) 92 | print(time) 93 | 94 | time2 = '2015-5-31 16:10:30' 95 | utc2 = 'UTC-09:00' 96 | # 用正则匹配出时间 97 | utc2 = int(re.search('UTC([+-][\d]{1,2}):[\d]{2}', utc2).group(1)) 98 | print(utc2) 99 | time2 = to_timestamp(time2, utc2) 100 | print(time2) 101 | -------------------------------------------------------------------------------- /test39.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习内建模块之collections' 5 | 6 | __author__ = 'sergiojune' 7 | from collections import namedtuple, defaultdict, deque, OrderedDict, Counter 8 | 9 | # 弄一个可以根据名字来取数的元组 10 | at = namedtuple('Point', ['x', 'y']) # 第一个参数为描述事物类型, 第二个参数为元组的位置名字 11 | p = at(1, 2) # 新建一个元组 12 | # 根据名字来取元素 13 | print(p.x) # 这就可以看作是一个坐标点 14 | print(p.y) 15 | 16 | # 有默认值的dict 17 | dd = defaultdict(lambda:'not') # 参数为遇到不存在键时的处理的方法 18 | dd['age'] = 20 19 | print(dd['age']) # 存在 20 | print(dd['a']) # 不存在 21 | 22 | 23 | # 使用队列,比list的插入数据和删除数据快,支持从头或者尾删除或插入 24 | d = deque([1, 2, 3, 6]) 25 | print(d) 26 | # 从头插入数据 27 | d.appendleft(5) 28 | print(d) 29 | # 删除头部数据 30 | d.popleft() 31 | print(d) 32 | 33 | # 让字典保持有序 34 | od = OrderedDict([('x', 3), ('y', 6), ('z', 6)]) 35 | print(od) 36 | # 还可以添加,与dict用法一样 37 | ood = OrderedDict() 38 | ood['f'] = 5 39 | ood['s'] = 9 40 | ood['e'] = 7 41 | print(ood) 42 | 43 | 44 | # 用计数器,直接算出某一个字符串里面字符出现的个数 45 | s = 'mynameissergiojune' 46 | c = Counter(s) 47 | print(c) 48 | 49 | 50 | # 利用OrderedDict实现一个先进先出的字典,超过最大容量的时候就删除 51 | class LastUpdateDict(OrderedDict): 52 | def __init__(self, max): 53 | super(LastUpdateDict, self).__init__() 54 | self.max = max 55 | 56 | def __setitem__(self, key, value): 57 | # 看看有没有重复键 58 | contains = 1 if key in self.keys() else 0 59 | # 判断最大长度 60 | if len(self) - contains >= self.max: 61 | last = self.popitem(last=False) # last 为false时就删除第一个添加的键值对,否则删除最后的键值对 62 | print('pop', last) 63 | # 增加元素 64 | if contains: # 键原来存在,直接修改 65 | del self[key] 66 | print('update', key, value) 67 | else: 68 | print('add', key, value) 69 | OrderedDict.__setitem__(self, key, value) 70 | 71 | 72 | lud = LastUpdateDict(3) 73 | lud['a'] = 1 74 | lud['b'] = 2 75 | lud['c'] = 3 76 | print(lud) 77 | lud['d'] = 4 78 | print(lud) 79 | lud['b'] = 5 80 | print(lud) 81 | -------------------------------------------------------------------------------- /test4.py: -------------------------------------------------------------------------------- 1 | # 练习高级特性的迭代 2 | 3 | 4 | l = list(range(1,21)) 5 | # 这个就是迭代 6 | for num in l: 7 | print(num) 8 | # 对元组的迭代 9 | t = (1,3,5,7,9) 10 | for num in t: 11 | print(num) 12 | # 还可以对字符串进行迭代 13 | s = 'jskldf' 14 | for c in s: 15 | print(c) 16 | 17 | 18 | # 判断一变量是否可迭代,用collections的Iterable 19 | from collections import Iterable 20 | print(isinstance(l,Iterable)) 21 | print(isinstance(t,Iterable)) 22 | print(isinstance(s,Iterable)) 23 | # 可以看出结果都是True,证明可迭代 24 | 25 | 26 | # 还可以按下表来迭代 27 | for value,num in enumerate(t): 28 | print(value, num) 29 | 30 | 31 | # 作业:请使用迭代查找一个list中最小和最大值,并返回一个tuple: 32 | def getNum(L): 33 | if isinstance(L,list): 34 | max = min = L[0] 35 | for num in L: 36 | if num > max: 37 | max = num 38 | if num < min: 39 | min = num 40 | return (min, max) 41 | else: 42 | print('请输入一个列表') 43 | 44 | 45 | l = [9,5,456,8,54,4,45] 46 | print(getNum(l)) -------------------------------------------------------------------------------- /test40.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习内建模块之base64' 5 | 6 | __author__ = 'sergiojune' 7 | import base64 8 | 9 | # 进行base64编码,转为字符串 10 | b = b'binary\x00strg=' 11 | bs = base64.b64encode(b) 12 | print(bs) 13 | # 解码 14 | b = base64.b64decode(bs) 15 | print(b) 16 | 17 | 18 | # 对于网页的安全编码 19 | s = b'i\xb7\x1d\xfb\xef\xff' 20 | bs = base64.b64encode(s) 21 | print(bs) 22 | bs = base64.urlsafe_b64encode(s) 23 | print(bs) 24 | 25 | 26 | # 作业:请写一个能处理去掉=的base64解码函数 27 | def safe_base64_decode(s): 28 | while len(s) % 4 !=0: 29 | s += b'=' 30 | bs = base64.b64decode(s) 31 | return bs 32 | 33 | 34 | # 测试: 35 | assert b'abcd' == safe_base64_decode(b'YWJjZA=='), safe_base64_decode('YWJjZA==') 36 | assert b'abcd' == safe_base64_decode(b'YWJjZA'), safe_base64_decode('YWJjZA') 37 | print('ok') -------------------------------------------------------------------------------- /test41.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- conding: utf-8 -*- 3 | 4 | '练习内建模块之struct' 5 | 6 | __author__ = 'sergiojune' 7 | import struct,base64 8 | 9 | # 这个模块是将bytes与其他二进制数据互相转换 10 | # 将任意数据类型转为bytes 11 | i = 10249999 12 | b = struct.pack('>I', i) # 第一个参数为处理指令 13 | print(b) 14 | 15 | s = 123.456 16 | b = struct.pack('f', s) 17 | print(b) 18 | 19 | 20 | # 将bytes转为其他任意类型 21 | s = struct.unpack('f', b) 22 | print(s) 23 | 24 | s = b'\x42\x4d\x38\x8c\x0a\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00\x80\x02\x00\x00\x68\x01\x00\x00\x01\x00\x18\x00' 25 | un = struct.unpack('' % self.name, end='') 38 | 39 | def put_end(self): 40 | print('' % self.name) 41 | 42 | 43 | @contextlib.contextmanager 44 | def create(name): 45 | h = Html(name) 46 | h.put_start() 47 | yield h 48 | h.put_end() 49 | 50 | 51 | with create('h1') as h: 52 | print('我是标题', end='') 53 | 54 | 55 | # 如果一个对象没有实现上下文方法,我们还可以用colsing这个方法 56 | with contextlib.closing(requests.get('https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001478651770626de401ff1c0d94f379774cabd842222ff000')) as f: 57 | print(f.text) 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /test46.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- conding: utf-8 -*- 3 | 4 | '练习内建模块之HTMLParser' 5 | 6 | __author__ = 'sergiojune' 7 | from html.parser import HTMLParser 8 | import requests 9 | 10 | 11 | class MyHTMLParser(HTMLParser): 12 | 13 | def handle_starttag(self, tag, attrs): # 这个是处理开始标签 14 | print('<%s>' % tag, list(attrs)) 15 | 16 | def handle_endtag(self, tag): # 这个是处理结束标签 17 | print('' % tag) 18 | 19 | def handle_data(self, data): # 这个是处理标签里的内容 20 | print(data) 21 | 22 | def handle_comment(self, data): # 这个是处理注释 23 | print('') 24 | 25 | def handle_entityref(self, name): # 这个是处理特殊字符,比如  26 | print('&%s;' % name) 27 | 28 | def handle_charref(self, name): # 这个是处理特殊字符,比如Ӓ 29 | print('&#%s;' % name) 30 | 31 | 32 | parser = MyHTMLParser() 33 | parser.feed(''' 34 | 35 | 36 | 37 |

Some html HTML tutorial...
END

38 | ''') 39 | 40 | 41 | # 作业:找一个网页,例如https://www.python.org/events/python-events/,用浏览器查看源码并复制,然后尝试解析一下HTML,输出Python官网发布的会议时间、名称和地点。 42 | class DealHTML(HTMLParser): 43 | def __init__(self): 44 | super(DealHTML, self).__init__() 45 | self.thing = 0 46 | self.time = 0 47 | self.address = 0 48 | 49 | def handle_starttag(self, tag, attrs): 50 | if len(attrs) == 1: 51 | if 'python-events' in list(attrs)[0][1]: # 获取工作事件 52 | print('' % list(attrs)[0][1], end='') 53 | self.thing = 1 54 | if 'datetime' in list(attrs)[0][0]: # 获取工作时间 55 | print('<%s>' % list(attrs)[0][0], end='') 56 | self.time = 1 57 | if 'location' in list(attrs)[0][1]: # 获取工作地点 58 | print('<%s>' % list(attrs)[0][1], end='') 59 | self.address = 1 60 | 61 | def handle_data(self, data): 62 | if self.thing: 63 | print(data, end='') 64 | if self.time: 65 | print(data, end='') 66 | if self.address: 67 | print(data, end='') 68 | 69 | def handle_endtag(self, tag): 70 | if self.thing: 71 | print('' % tag) 72 | self.thing = 0 73 | if self.time: 74 | print('' % tag) 75 | self.time = 0 76 | if self.address: 77 | print('' % tag) 78 | print('') 79 | self.address = 0 80 | 81 | 82 | response = requests.get('https://www.python.org/events/python-events/').text 83 | dh = DealHTML() 84 | dh.feed(response) 85 | -------------------------------------------------------------------------------- /test47.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- conding: utf-8 -*- 3 | 4 | '练习第三方模块之pillow' 5 | 6 | __author__ = 'sergiojune' 7 | from PIL import Image, ImageFilter, ImageDraw, ImageFont 8 | import random 9 | # 对图像进行缩小 10 | im = Image.open('test.jpg') 11 | w, h = im.size # 获取图片的宽高 12 | print('origin image width is %d, height is %d' % (w, h)) 13 | # 进行缩小一倍 14 | im.thumbnail((w//2, h//2)) # 参数是一个元组,对应的是宽高 15 | im.save('suoxiao.png', 'png') 16 | print('now width is %d, height is %d' % (im.size[0], im.size[1])) 17 | 18 | # 还可以对图像进行模糊化 19 | im2 = im.filter(ImageFilter.BLUR) 20 | im2.save('muhu.png', 'png') 21 | 22 | 23 | # 利用这个模块产生验证码 24 | def rndchar(): # 产生随机字符 25 | return chr(random.randint(65, 90)) 26 | 27 | 28 | def rndcolor(): # 随机颜色 29 | return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255)) 30 | 31 | 32 | def rndcolor2(): 33 | return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127)) 34 | 35 | 36 | width = 240 37 | height = 40 38 | # 创建图像对象 39 | im = Image.new('RGB', (width, height), (255, 255, 255)) 40 | # 创建字体 41 | font = ImageFont.truetype(r'E:\python_project\Lib\site-packages\matplotlib\mpl-data\fonts\ttf\cmsy10.ttf', 36) 42 | # 创建画笔 43 | draw = ImageDraw.Draw(im) 44 | # 填充图片 45 | for x in range(width): 46 | for y in range(height): 47 | draw.point((x, y), fill=rndcolor2()) 48 | # 写文字 49 | for x in range(4): 50 | draw.text((60*x+10, 10), rndchar(), font=font, fill=rndcolor()) 51 | 52 | # mohu 53 | im.filter(ImageFilter.BLUR) 54 | # 保存图片 55 | im.save('yan.png', 'png') 56 | -------------------------------------------------------------------------------- /test48.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- conding: utf-8 -*- 3 | 4 | '练习第三方模块之chardet' 5 | 6 | __author__ = 'sergiojune' 7 | import chardet # 这个库是用来猜测字节码的编码方式的 8 | 9 | s = b'hello world' 10 | c = chardet.detect(s) 11 | print(c) 12 | # 结果:{'encoding': 'ascii', 'confidence': 1.0, 'language': ''},可以看出是ascii编码,第二个为概率,1.0表示百分百 13 | 14 | s = '中国中文我爱你' 15 | c = chardet.detect(s.encode('gbk')) 16 | print(c) 17 | 18 | c = chardet.detect(s.encode('utf-8')) 19 | print(c) 20 | 21 | # 看看日语的 22 | s = '最新の主要ニュース' 23 | c = chardet.detect(s.encode('euc-jp')) 24 | print(c) 25 | 26 | # encode()为编码,将字符串变为字节码,decode()为解码,将字节码转为字符串 27 | -------------------------------------------------------------------------------- /test49.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '用于练习网络编程TCP' 5 | 6 | __author__ = 'sergiojune' 7 | import socket, threading, time 8 | 9 | # 创建socket 10 | # s = socket.socket(socket.AF_INET , socket.SOCK_STREAM) # 第一个参数为指定ipv4模式, 第二个参数指定为tup模式的面向流 11 | # # 建立连接 12 | # s.connect(('www.sina.com.cn', 80)) 13 | # # 发送请求 14 | # s.send(b'GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n') # 发送get请求,http协议 15 | # # 处理返回来的数据 16 | # buffer = [] 17 | # while True: 18 | # # 指定最大接受1024个字节 19 | # d = s.recv(1024) 20 | # if d: 21 | # buffer.append(d) 22 | # else: 23 | # break 24 | # data = b''.join(buffer) 25 | # # 关闭连接 26 | # s.close() 27 | # 取出请求头和内容 28 | # header, body =data.split(b'\r\n') 29 | # print(header) 30 | # print(body) 31 | 32 | 33 | # 建立服务器端 34 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 35 | # 绑定端口和地址,当有信息从这个端口发送过来时就捕捉 36 | s.bind(('127.0.0.1', 9999)) # 这个为本机ip,这个服务器只能接受本地的 37 | # 监听窗口 38 | s.listen(5) # 传入参数为最大的等待连接数 39 | print('await for connect') 40 | def tcplink(sock, add): 41 | print('here is a connector from %s:%s' % add) 42 | # 向客户端发送数据 43 | sock.send(b'Welcome') 44 | # 处理客户端发送来的数据 45 | while True: 46 | d = sock.recv(1024) 47 | time.sleep(1) 48 | if not d or d == b'exit': 49 | break 50 | sock.send(('hello %s !' % d.decode('utf-8')).encode('utf-8')) 51 | # 关闭连接 52 | sock.close() 53 | print('connect is closed') 54 | 55 | # 用永久循环来等待客户端连接 56 | while True: 57 | # 这个函数会返回一个客户端连接 58 | sock, add = s.accept() 59 | # 创建线程来处理客户端的数据 60 | t = threading.Thread(target=tcplink, args=(sock, add)) 61 | # 开启线程 62 | t.start() 63 | -------------------------------------------------------------------------------- /test5.py: -------------------------------------------------------------------------------- 1 | # 练习列表生成式,这个很好用,越用越爽 2 | 3 | 4 | l = [x for x in range(10)] 5 | print(l) 6 | # 还可以加条件来筛选元素,这里筛选偶数 7 | l = [x for x in range(10) if x % 2 == 0] 8 | print(l) 9 | # 对两个列表生成一个也可以,生成全排列 10 | l = [x + y for x in 'XYZ' for y in 'abc'] 11 | print(l) 12 | # 也可以生成字典 13 | d = {x:y for x in 'xyz' for y in 'ABC'} 14 | print(d) 15 | 16 | 17 | # 作业:将列表的字符串的大写改成小写,不是字符串的就去掉 18 | L1 = ['Hello', 'World', 18, 'Apple', None] 19 | print(L1) 20 | L2 = [s.lower() for s in L1 if isinstance(s,str)] 21 | print(L2) 22 | 23 | -------------------------------------------------------------------------------- /test50.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '配合test49文件的服务器,这文件当作客户端' 5 | 6 | __author__ = 'sergiojune' 7 | import socket 8 | 9 | # 建立socket 10 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 11 | # 连接地址 12 | s.connect(('127.0.0.1', 9999)) 13 | # 接受返回的数据 14 | print(s.recv(1024).decode('utf-8')) 15 | # 发送数据 16 | for x in [b'bob', b'amy', b'june']: 17 | print('send %s' % x) 18 | s.send(x) 19 | print(s.recv(1024).decode('utf-8')) 20 | # 发送退出数据 21 | s.send(b'exit') 22 | s.close() 23 | print('connect is closed from kehuuduan') 24 | -------------------------------------------------------------------------------- /test51.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | '练习UDP网络协议' 5 | 6 | __author__ = 'sergiojune' 7 | import socket 8 | 9 | # 此文件用于当服务器 10 | # 创建socket 11 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 第二个参数为指定udp协议 12 | # 绑定端口,不需要监听 13 | s.bind(('127.0.0.1', 9999)) 14 | print('await connect') 15 | while True: 16 | data, addr = s.recvfrom(1024) # 这个直接返回客户端的ip和请求信息 17 | print('connect form %s:%s' % addr) 18 | # 发送数据回客户端 19 | s.sendto(b'hello %s' % data, addr) # 第二个参数为发送到的ip 20 | -------------------------------------------------------------------------------- /test52.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | 'udp配合test51文件的服务器,这文件当作客户端' 5 | 6 | __author__ = 'sergiojune' 7 | import socket 8 | 9 | # 创建socket 10 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 11 | # UDP协议不需要建立连接 12 | for x in [b'bret', b'tom', b'sergiojune']: 13 | s.sendto(x, ('127.0.0.1', 9999)) 14 | print(s.recv(1024).decode('utf-8')) 15 | s.close() 16 | -------------------------------------------------------------------------------- /test53.py: -------------------------------------------------------------------------------- 1 | #!/usr.bin.env python 3 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' 5 | 练习python的协程0 6 | next(方法和next()方法在一定意义上是相同用法的,只不过next不能传递特定的值而next可以传递特定的值 7 | next() 和send(None) 方法是等价的,都是用于启动生成器返回值 8 | ''' 9 | 10 | __author__ = 'sergiojune' 11 | 12 | 13 | # 消费者 14 | def consumer(): 15 | r = '' 16 | while True: 17 | n = yield r # 接受调用者发送的数据 18 | if not n: 19 | return 20 | print('consumer consume is %s' % n) 21 | r = '200 OK' 22 | 23 | 24 | def producer(c): # 这个函数先被执行 25 | c.send(None) # 这个语句必须写,而且参数固定,作用是启动上面的生成器 26 | x = 0 27 | while x < 5: 28 | x = x+1 29 | print('producer is produce %d' % x) 30 | r = c.send(x) # 发送数据,生成器接受数据,赋值给n变量 31 | print('consumer is return %s' % r) 32 | # 关闭 33 | c.close() 34 | 35 | 36 | c = consumer() 37 | producer(c) 38 | -------------------------------------------------------------------------------- /test54.py: -------------------------------------------------------------------------------- 1 | #!/usr.bin.env python 3 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' 5 | 练习python的asyncio 6 | yield form 语句返回的值是后面表达式迭代后遇到StopIteration后再return(这个语句) 的值,无这个语句是返回None 7 | ''' 8 | 9 | __author__ = 'sergiojune' 10 | import asyncio,threading 11 | 12 | 13 | @asyncio.coroutine # 这个装饰器是把生成器标记成为coroutine 14 | def hello(): 15 | r = '' 16 | print('hello world(%s)' % threading.current_thread()) 17 | n = yield from asyncio.sleep(1) # 这个方法也是个coroutine,执行到这里后会等待该方法返回数给这个coroutine 18 | print('hello again(%s)' % threading.current_thread()) 19 | 20 | 21 | # 这是练习一个协程的 22 | # # 获取事件循环,就是eventloop 23 | # loop = asyncio.get_event_loop() 24 | # # 执行coroutine,参数是需要运行的协程 25 | # loop.run_until_complete(hello()) 26 | # # 关闭 27 | # loop.close() 28 | 29 | 30 | # 这个执行两个hello 31 | # l = asyncio.get_event_loop() 32 | # # 把协程放到eventloop里面 33 | # # 这两个方法是并发执行的 34 | # l.run_until_complete(asyncio.wait([hello(), hello()])) # wait()是将参数里的协程转为一个包括他们在内的单独协程 35 | # l.close() 36 | 37 | 38 | # 练习用异步连接新浪搜狐和网易云 39 | def wget(host): 40 | print('ready ro connect %s' % host) 41 | connect = asyncio.open_connection(host, 80) 42 | reader, writer = yield from connect # 这个io操作比较耗时,所以会执行下个协程 43 | header = 'GET/HTTP/1.1\r\nHost:%s\r\n\r\n' % host 44 | writer.write(header.encode('utf-8')) 45 | yield from writer.drain() # 用于刷新缓存区的内容,确保将内容提交上去 46 | while True: 47 | line = yield from reader.readline() # 这个io操作有时不耗时,会直接运行整个循环 48 | if line == b'\r\n': 49 | break 50 | print('%s header>%s' % (host, line.decode('utf-8').strip())) 51 | writer.close() 52 | 53 | 54 | loop = asyncio.get_event_loop() 55 | loop.run_until_complete(asyncio.wait([wget(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']])) 56 | loop.close() 57 | -------------------------------------------------------------------------------- /test55.py: -------------------------------------------------------------------------------- 1 | #!/usr.bin.env python 3 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' 5 | 练习python的async/await 6 | async:相当于asyncio.coroutine,可以用这个替换这个更加方便 7 | await:相当于yield form,把这个改成await即可替代 8 | 以上都是在python3.5版本以上才有的 9 | ''' 10 | 11 | __author__ = 'sergiojune' 12 | import asyncio 13 | 14 | 15 | async def hello(): # 这样就是相当于一个coroutine了 16 | print('hello world') 17 | await asyncio.sleep(1) 18 | print('hello again') 19 | 20 | 21 | # loop = asyncio.get_event_loop() 22 | # loop.run_until_complete(hello()) 23 | # loop.close() 24 | 25 | 26 | # 两个协程 27 | # loop = asyncio.get_event_loop() 28 | # loop.run_until_complete(asyncio.wait([hello(), hello()])) 29 | # loop.close() 30 | 31 | 32 | # 再用这个方法连接搜狐新浪和网易 33 | async def wegt(host): 34 | print('wegt %s ' % host) 35 | # 连接 36 | connect = asyncio.open_connection(host, 80) 37 | reader, writer = await connect 38 | header = 'GET/HTTP/1.0\r\nHost:%s\r\n\r\n' % host 39 | writer.write(header.encode('utf-8')) 40 | await writer.drain() # 相当于刷新缓存 41 | while True: 42 | line = await reader.readline() 43 | if line == b'\r\n': 44 | print() 45 | break 46 | print('%s header > %s' % (host, line.decode('utf-8').strip())) 47 | connect.close() 48 | 49 | 50 | loop = asyncio.get_event_loop() 51 | loop.run_until_complete(asyncio.wait([wegt(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']])) 52 | loop.close() 53 | -------------------------------------------------------------------------------- /test56.py: -------------------------------------------------------------------------------- 1 | #!/usr.bin.env python 3 2 | # -*- coding: utf-8 -*- 3 | 4 | ''' 5 | 练习python的aiohttp 6 | 练习服务器上的异步操作 7 | ''' 8 | 9 | __author__ = 'sergiojune' 10 | import asyncio 11 | from aiohttp import web 12 | 13 | 14 | async def index(request): # 首页返回一个h1标签 15 | await asyncio.sleep(0.5) 16 | return web.Response(body=b'

index

', content_type='text/html') 17 | 18 | 19 | async def hello(request): # 根据url参数返回信息 20 | await asyncio.sleep(0.5) 21 | return web.Response(body=b'

hello %s

' % request.match_info['name'], content_type='text/html') 22 | 23 | 24 | # 初始化服务器,也是一个coroutine 25 | async def init(loop): # 接受协程池 26 | app = web.Application(loop=loop) 27 | # 添加反应路径 28 | app.router.add_route('GET', '/', index) 29 | app.router.add_route('GET', '/hello/{name}', hello) 30 | s = loop.create_server(app.make_handler(), '', 80) # 用loop.create_server创建tcp协议 31 | print('sever is start in 127.0.0.1:80') 32 | return s 33 | 34 | 35 | loop = asyncio.get_event_loop() 36 | loop.run_until_complete(init(loop)) 37 | loop.run_forever() # 服务器永远运行 38 | 39 | -------------------------------------------------------------------------------- /test6.py: -------------------------------------------------------------------------------- 1 | # 练习生成式,生成式就是将列表生成式的中括号改成小括号即可 2 | 3 | 4 | g = (x for x in range(1,20)) 5 | print(g) # 这是个generator对象 6 | print(next(g)) # 不断使用next来进行获取下一个数,当获取到最后一个数时会抛出StopIteration错误 7 | # 可见这种方法对于列表相当大时,就可以节约内存,同时他也可以用for循环来获取元素 8 | for x in g: 9 | print(x) 10 | 11 | 12 | # 使用yield来定义一个生成器的函数 13 | def odd(): 14 | print('yield 1') 15 | # yield就是一个关键字,用来生成生成器 16 | # 每执行一个next函数时,就会运行到一个yield处,把该值返回 17 | yield 1 18 | print('yield 2') 19 | yield 2 20 | print('yield 3') 21 | yield 3 22 | 23 | 24 | o = odd() 25 | # 他是生成器,所以可以通过next来获取数 26 | print(next(o)) 27 | print(next(o)) 28 | print(next(o)) 29 | # next(o) 30 | 31 | 32 | # 使用yield来编写斐波那契数列 33 | def fib(n): 34 | a, b = 0, 1 35 | while n > 0: 36 | # 第一和第二个数都是1 37 | yield b 38 | a, b = b, a+b 39 | n -=1 40 | return 'done' 41 | 42 | 43 | num = fib(6) 44 | # 因为是生成器,所以可以通过for循环来获取元素 45 | for x in num: 46 | print(x) 47 | 48 | 49 | # 作业:有一个杨辉三角,把每一行看做一个list,试写一个generator,不断输出下一行的list: 50 | def triangles(n): 51 | l = [1] 52 | # 记录第几行,同时知道有多少个元素 53 | num = 1 54 | while num <= n: 55 | # 使用切片是避免两个变量指向同一个列表,从而影响了下面操作 56 | L = l[:] 57 | yield L 58 | num += 1 59 | if len(l) > 1: 60 | for d in range(1, num-1): 61 | l[d] = L[d] + L[d-1] 62 | l[0] = 1 63 | l.append(1) 64 | 65 | 66 | t = triangles(10) 67 | for x in t: 68 | print(x) -------------------------------------------------------------------------------- /test7.py: -------------------------------------------------------------------------------- 1 | # 练习高级特性的迭代器 2 | from collections import Iterable, Iterator 3 | 4 | l = [1, 3, 5] 5 | t = (1, 6, 5) 6 | s = 'dsjk' 7 | # 判断是否可迭代 8 | print(isinstance(l, Iterable)) 9 | print(isinstance(t, Iterable)) 10 | print(isinstance(s, Iterable)) 11 | # 判断是否是迭代器,可以看出,这三个都不是迭代器 12 | print(isinstance(l, Iterator)) 13 | print(isinstance(t, Iterator)) 14 | print(isinstance(s, Iterator)) 15 | # 判断生成器是否是迭代器,是的 16 | print(isinstance((x for x in range(3)), Iterator)) 17 | # 同时也是可迭代的 18 | print(isinstance((x for x in range(3)), Iterable)) 19 | 20 | 21 | # 我们可以将list,tuple,和string转成迭代器,这时就是迭代器了 22 | print(isinstance(iter(l), Iterator)) 23 | print(isinstance(iter(t), Iterator)) 24 | print(isinstance(iter(s), Iterator)) 25 | 26 | 27 | # 其实for循环就是通过next来不断获取下一个元素的,直到抛出异常StopIteration 28 | -------------------------------------------------------------------------------- /test8.py: -------------------------------------------------------------------------------- 1 | # 练习函数式编程的map和reduce 2 | from functools import reduce 3 | 4 | 5 | l = [x for x in range(-10, 10, 2)] 6 | print(l) 7 | l = list(map(abs, l)) 8 | print(l) 9 | 10 | 11 | # reduce是将列表做累计运算 12 | # lambda是匿名函数 13 | num = reduce(lambda x, y: x + y, l) 14 | print(num) 15 | 16 | 17 | # 将一个字符串转换成整型 18 | def str2int(s): 19 | def char2int(ch): 20 | c = {str(x): x for x in range(10)} 21 | return c[ch] 22 | 23 | def fun(n1, n2): 24 | return n1*10 + n2 25 | 26 | return reduce(fun, map(char2int, s)) 27 | 28 | 29 | num = str2int('12345') 30 | print(type(num), num) 31 | 32 | 33 | # 这是使用匿名函数的简便版 34 | def str2int2(s): 35 | ch = {str(x): x for x in range(10)} 36 | return reduce(lambda x, y: x*10+y, map(lambda x: ch[x], s)) 37 | 38 | 39 | num = str2int2('12345') 40 | print(type(num), num) 41 | 42 | 43 | # 作业:利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字 44 | def normalize(name): 45 | # capitalize()函数是将字符串的首字母大写 46 | return list(map(lambda x: x.capitalize(), name)) 47 | 48 | 49 | L = ['adam', 'LISA', 'barT'] 50 | print(normalize(L)) 51 | 52 | 53 | # 作业2:Python提供的sum()函数可以接受一个list并求和,请编写一个prod()函数,可以接受一个list并利用reduce()求积 54 | def prod(x, y): 55 | return x*y 56 | 57 | 58 | num = reduce(prod, [3, 5, 7, 9]) 59 | print(num) 60 | 61 | 62 | # 作业3:利用map和reduce编写一个str2float函数,把字符串'123.456'转换成浮点数123.456 63 | def str2float(s): 64 | ch = {str(x): x for x in range(10)} 65 | # 先将字符串分割 66 | L = s.split('.') 67 | # 整数部分 68 | n1 = reduce(lambda x, y: x*10 + y, map(lambda x: ch[x], L[0])) 69 | # 小数部分 70 | n2 = reduce(lambda x, y: x * 10 + y, map(lambda x: ch[x], L[1])) 71 | n2 *= 0.1**len(L[1]) 72 | return n1+n2 73 | 74 | 75 | num = str2float('123.456') 76 | print(num) 77 | -------------------------------------------------------------------------------- /test9.py: -------------------------------------------------------------------------------- 1 | # 练习函数式编程的filter过滤器 2 | from functools import reduce 3 | 4 | 5 | L = [x for x in range(100)] 6 | # 过滤取3的倍数 7 | L = filter(lambda x: x % 3 == 0, L) # 这个返回也是一个迭代器,可以通过next来获取下一个元素 8 | print(next(L)) 9 | # 转成list 10 | print(list(L)) 11 | 12 | 13 | # 获取初始序列,因为偶数都不是素数,所以就只有奇数 14 | def get_list(): 15 | n = 1 16 | while True: 17 | n = n+2 18 | yield n 19 | 20 | 21 | # 获取素数 22 | def get_primes(): 23 | num = 2 24 | yield num 25 | # 初始化序列 26 | it = get_list() 27 | while True: 28 | num = next(it) 29 | yield num 30 | # 排除第一个数的倍数 31 | filter(lambda x: x % num != 0, it) 32 | 33 | 34 | for num in get_primes(): 35 | if num < 1000: 36 | print(num) 37 | else: 38 | break 39 | 40 | 41 | # 作业:回数是指从左向右读和从右向左读都是一样的数,例如12321,909。请利用filter()筛选出回数 42 | def is_palindrome(n): 43 | l = list(str(n)) 44 | l.reverse() 45 | num = reduce(lambda x, y: int(x) * 10 + int(y), l) 46 | return num == n 47 | 48 | 49 | output = filter(is_palindrome, range(1, 1000)) 50 | print('1~1000:', list(output)) 51 | --------------------------------------------------------------------------------