├── .idea
├── dictionaries
│ └── L1n.xml
└── vcs.xml
├── C_问答题汇总.md
├── Python 语言特性
├── 1 Python的函数参数传递.md
├── 2 @staticmethod和@classmethod.md
├── 3 类变量和实例变量.md
├── 4 Python中单下划线和双下划线.md
├── 5 args and kwargs.md
├── 6 面向切面编程AOP和装饰器.md
├── 7 单例模式.md
├── 8 Python 函数式编程.md
├── 9 Python 里的拷贝.md
└── readme.md
├── Python 面试编程题
├── 1 台阶问题 斐波那契
│ ├── fibonacci.py
│ ├── unittest_fibonacci.py
│ └── 斐波那契.md
├── 10 快排
│ ├── qsort.py
│ ├── unittest_sort.py
│ └── 快排.md
├── 11 找零问题
│ ├── coin_change.py
│ └── 找零问题.md
├── 12 二叉树相关
│ ├── binary_tree.py
│ └── 二叉树相关.md
├── 13 单链表逆置
│ ├── single_list_reverse.py
│ └── 单链表逆置.md
├── 2 变态台阶问题
│ ├── similar_frog_jump.py
│ └── 变态台阶问题.md
├── 3 矩形覆盖
│ ├── rectangle.py
│ └── 矩阵覆盖.md
├── 4 杨氏矩阵查找
│ ├── rectangle_search.py
│ ├── unittest_rectangle_search.py
│ └── 杨氏矩阵查找.md
├── 5 去除列表中的重复元素
│ ├── delete_repeat.py
│ └── 去除列表中的重复元素.md
├── 6 链表成对调换
│ ├── swap_pairs_list_node.py
│ └── 链表成对调换.md
├── 7 创建字典的方法
│ ├── create_dict.py
│ └── 创建字典的方法.md
├── 8 合并两个有序列表
│ ├── merge_sort.py
│ ├── unittest_merge_sort.py
│ └── 合并两个有序列表.md
├── 9 二分查找
│ ├── binary_search.py
│ ├── unittest_binary_search.py
│ └── 二分查找.md
└── readme.md
├── README.md
├── SUMMARY.md
├── python_script
├── check_summary.py
├── readme.md
├── search_keyword.py
└── test_check_summary.py
├── stackoverflow-about-Python
├── Python中关键字yield有什么作用.md
├── Python中如何在一个函数中加入多个装饰器.md
├── Python中的元类(metaclass)是什么.md
├── join的问题.md
├── name=main的作用.md
├── readme.md
├── str与repr的区别.md
├── super与init方法.md
├── 为什么代码在一个函数里运行的更快.md
├── 为什么用pip比用easy_install的好.md
├── 单下划线和双下划线的含义.md
├── 变化的默认参数.md
├── 在Android上运行Python.md
├── 在Windows下安装pip.md
├── 在函数里使用全局变量.md
├── 如何判断一个文件是否存在.md
├── 如何知道一个对象有一个特定的属性.md
├── 如何调用外部命令.md
├── 如何通过函数名的字符串来调用函数.md
├── 字典合并问题.md
├── 循环中获取索引.md
├── 快速合并列表中的列表.md
├── 怎么在终端里输出颜色.md
├── 怎么用引用来改变一个变量.md
├── 把列表分割成同样大小的块.md
├── 枚举类型的使用.md
├── 根据字典值进行排序.md
├── 检查列表为空的最好办法.md
├── 检查文件夹是否存在的操作.md
├── 类里的静态变量.md
└── 装饰器classmethod和staticmethod的区别.md
├── 剑指 Offer 编程题
├── readme.md
├── 二维数组中的查找
│ ├── python_solve.py
│ ├── readme.md
│ └── unittest_solve.py
├── 从尾到头打印链表
│ ├── python_solve.py
│ └── readme.md
├── 旋转数组的最小数字
│ └── readme.md
├── 替换空格
│ └── readme.md
├── 用两个栈实现队列
│ ├── readme.md
│ └── two_stack_implement_queue.py
└── 重建二叉树
│ ├── readme.md
│ └── rebuild_binary_tree_pre_in_order.py
├── 安全测试开发相关面试
├── readme.md
├── 业务安全类面试参考.md
├── 安全测试类面试参考.md
├── 测试开发类面试参考.md
├── 测试开发类面试参考2.md
├── 测试开发类面试参考3.md
├── 测试类HR面参考.md
└── 测试类综合面试参考.md
├── 深信服_sangfor_相关
├── readme.md
├── sangfor_acm_oj
│ ├── 2016_12_03
│ │ ├── A.py
│ │ ├── C.py
│ │ ├── C_ACM
│ │ │ ├── out(2).zip
│ │ │ ├── right_C_answer.zip
│ │ │ ├── sxf.cpp
│ │ │ ├── sxf1.cpp
│ │ │ ├── sxf22.cpp
│ │ │ └── test——A.txt
│ │ ├── out.zip
│ │ ├── template.py
│ │ ├── test_A.py
│ │ ├── test_A.txt
│ │ ├── test_C.zip
│ │ └── test_C_answer.zip
│ ├── before_2016_12_03
│ │ ├── __init__.py
│ │ ├── acm_1001.py
│ │ ├── acm_1003.py
│ │ ├── acm_1004.py
│ │ ├── acm_1005.py
│ │ ├── acm_1076.py
│ │ ├── acm_1077.py
│ │ ├── acm_1078.py
│ │ ├── acm_1079.py
│ │ ├── acm_1080.py
│ │ ├── acm_1081.py
│ │ ├── acm_1082.py
│ │ ├── acm_1083.py
│ │ ├── acm_1084.py
│ │ ├── acm_1085.py
│ │ ├── acm_1086.py
│ │ ├── acm_1087.py
│ │ ├── acm_1088.py
│ │ ├── acm_1089.py
│ │ ├── acm_1090.py
│ │ ├── acm_1091.py
│ │ ├── acm_1092.py
│ │ ├── acm_1093.py
│ │ ├── acm_1094.py
│ │ ├── test_1003.py
│ │ ├── test_1004.py
│ │ └── test_1005.py
│ └── readme.md
├── 智安全杯
│ ├── 2018比赛.md
│ ├── 2019初赛.md
│ ├── 2019复赛.md
│ └── readme.md
└── 测试类面试参考.md
├── 编程题汇总.md
├── 网易 2017 校招笔试编程题
├── binary_weight.py
├── readme.md
├── test_binary_weight.py
├── 二进制权重.md
├── 平方串.md
└── 数位和.md
├── 腾讯 2017 暑期实习生编程题
├── README.md
├── get_longest_palindromic_substring.py
├── 字符移位
│ ├── readme.md
│ └── solve.py
├── 有趣的数字.md
├── 有趣的数字
│ ├── readme.md
│ ├── solve.py
│ └── unittest_solve.py
├── 构造回文.md
├── 构造回文
│ ├── get_longest_palindromic_substring.py
│ ├── readme.md
│ └── solve.py
├── 算法基础-字符移位.md
└── 腾讯 2017 暑期实习生编程题.md
├── 计算机知识
├── readme.md
├── readme1.md
├── readme2.md
└── readme3.md
└── 软件测试题
└── 题目汇总.md
/.idea/dictionaries/L1n.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | stackoverflow
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Python 语言特性/1 Python的函数参数传递.md:
--------------------------------------------------------------------------------
1 | ```Python
2 | #!/bin/env python3
3 | # -*- coding: utf-8 -*-
4 | # version: Python3.X
5 | """ 参考网上资料, 关于 Python 的函数参数传递问题
6 |
7 | 总结:
8 | 在 Python 中, strings, tuples, numbers 是不可更改的对象, 而 list, dict 等则是可以修改的对象
9 | """
10 |
11 | __author__ = '__L1n__w@tch'
12 |
13 |
14 | def modify_fun_fail(value):
15 | """
16 | 当一个引用传递给函数的时候, 函数自动复制一份引用, 这个函数里的引用和外边的引用没有关系
17 | 所以这里函数把引用指向了一个不可变对象, 当函数返回的时候, 外面的引用不会被改变
18 | :param value: int()
19 | :return: None
20 | """
21 | value += 50
22 | print("调用函数 {}, 修改值为 {}".format("modify_fun_fail", value))
23 |
24 |
25 | def modify_fun_success(a_list):
26 | """
27 | 函数内的引用指向的是可变对象, 对它的操作就和定位了指针地址一样, 在内存里进行修改
28 | :param a_list: list()
29 | :return: None
30 | """
31 | a_list.append(1)
32 | print("调用函数 {}, 修改值为 {}".format("modify_fun_success", a_list))
33 |
34 |
35 | if __name__ == "__main__":
36 | number = 30
37 | print("接下来调用函数 {}, 当前 number 值为 {}".format("modify_fun_fail", number))
38 | modify_fun_fail(number)
39 | print("调用完成, number 值为 {}".format(number), end="\n\n")
40 |
41 | number_list = list()
42 | print("接下来调用函数 {}, 当前 number_list 值为 {}".format("modify_fun_success", number_list))
43 | modify_fun_success(number_list)
44 | print("调用完成, number_list 值为 {}".format(number_list))
45 | ```
--------------------------------------------------------------------------------
/Python 语言特性/2 @staticmethod和@classmethod.md:
--------------------------------------------------------------------------------
1 | ```Python
2 | #!/bin/env python3
3 | # -*- coding: utf-8 -*-
4 | # version: Python3.X
5 | """ Python 有 4 个方法, 静态方法(staticmethod), 类方法(classmethod), 实例方法, 普通方法
6 | """
7 |
8 | __author__ = '__L1n__w@tch'
9 |
10 |
11 | def normal_function():
12 | print("I am just a 普通方法")
13 |
14 |
15 | class FunctionTest:
16 | def method(self, value):
17 | """
18 | self 是对实例的绑定, 需要把实例自己传给函数, 调用的时候是这样的 ft.method(value), 其实是 method(ft, value)
19 | :param value: int()
20 | :return: None
21 | """
22 | print("I am just a 实例方法, {}; {}".format(self, value))
23 |
24 | @classmethod
25 | def class_method(cls, value):
26 | """
27 | # cls是对类的绑定
28 | :param value: int()
29 | :return: None
30 | """
31 | print("I am just a 类方法, {}; {}".format(cls, value))
32 |
33 | @staticmethod
34 | def static_method(value):
35 | print("I am just a 静态方法, 打印值 {}".format(value))
36 |
37 |
38 | if __name__ == "__main__":
39 | ft = FunctionTest()
40 |
41 | normal_function()
42 |
43 | ft.method(3.4)
44 | ft.static_method(3.4)
45 | ft.class_method(3.4)
46 |
47 | FunctionTest.static_method(3.4)
48 | FunctionTest.class_method(3.4)
49 | ```
--------------------------------------------------------------------------------
/Python 语言特性/3 类变量和实例变量.md:
--------------------------------------------------------------------------------
1 | ```Python
2 | #!/bin/env python3
3 | # -*- coding: utf-8 -*-
4 | # version: Python3.X
5 | """ 关于类变量和实例变量的讨论
6 | """
7 |
8 | __author__ = '__L1n__w@tch'
9 |
10 |
11 | class VarTest:
12 | str_var = "I am 类变量"
13 | list_var = ["I am 类变量"]
14 |
15 |
16 | if __name__ == "__main__":
17 | vt1 = VarTest()
18 | vt2 = VarTest()
19 |
20 | vt1.str_var = "I am 实例变量"
21 | print("vt1.str_var: {}".format(vt1.str_var))
22 | print("vt2.str_var: {}".format(vt2.str_var))
23 | print("VarTest.str_var: {}".format(VarTest.str_var), end="\n\n")
24 |
25 | # 在实例的作用域里把类变量的引用改变了, 就变成了一个实例变量, self.list_var 不再引用 VarTest 的类变量 list_var 了
26 | vt1.list_var.append("vt1 到此一游")
27 | print("vt1.list_var: {}".format(vt1.list_var))
28 | print("vt2.list_var: {}".format(vt2.list_var))
29 | print("VarTest.list_var: {}".format(VarTest.list_var))
30 | ```
--------------------------------------------------------------------------------
/Python 语言特性/4 Python中单下划线和双下划线.md:
--------------------------------------------------------------------------------
1 | ```Python
2 | #!/bin/env python3
3 | # -*- coding: utf-8 -*-
4 | # version: Python3.X
5 | """ 讨论关于单下划线和双下划线命名的问题
6 |
7 | 总结:
8 | __foo__:一种约定,Python内部的名字,用来区别其他用户自定义的命名,以防冲突.
9 | _foo:一种约定,用来指定变量私有.程序员用来指定私有变量的一种方式.
10 | __foo:这个有真正的意义:解析器用_className__foo来代替这个名字,以区别和其他类相同的命名.
11 | """
12 |
13 | __author__ = '__L1n__w@tch'
14 |
15 |
16 | class UnderlineTest:
17 | def __init__(self):
18 | self.__super_private = "超级私有"
19 | self._semi_private = "假私有"
20 |
21 |
22 | if __name__ == "__main__":
23 | ut = UnderlineTest()
24 | try:
25 | print(ut.__super_private)
26 | except AttributeError as e:
27 | print("[!] 找不到超级私有")
28 | print(e)
29 |
30 | print("寻找假私有{}: {}", "ut._semi_private", ut._semi_private)
31 | print("打印 __dict__: {}".format(ut.__dict__))
32 | ```
--------------------------------------------------------------------------------
/Python 语言特性/5 args and kwargs.md:
--------------------------------------------------------------------------------
1 | ```Python
2 | #!/bin/env python3
3 | # -*- coding: utf-8 -*-
4 | # version: Python3.X
5 | """ 讨论关于 args 和 kwargs 的相关知识点
6 |
7 | 总结:
8 | 当你不确定你的函数里将要传递多少参数时你可以用 *args
9 | **kwargs 允许你使用没有事先定义的参数名
10 | 可以混着用, 命名参数首先获得参数值然后所有的其他参数都传递给 *args 和 **kwargs
11 |
12 | """
13 |
14 | __author__ = '__L1n__w@tch'
15 |
16 |
17 | def test_args(*args):
18 | # 当你不确定你的函数里将要传递多少参数时你可以用 *args
19 | for count, value in enumerate(args):
20 | print("{}: {}".format(count, value))
21 |
22 |
23 | def test_kwargs(**kwargs):
24 | # **kwargs 允许你使用没有事先定义的参数名
25 | for key, value in kwargs.items():
26 | print("Key:Value, {}:{}".format(key, value))
27 |
28 |
29 | # 当调用函数时你也可以用 * 和 ** 语法
30 | def star_operation(name, value, count):
31 | print("Name: {}, Value: {}, Count: {}".format(name, value, count))
32 |
33 |
34 | if __name__ == "__main__":
35 | test_args("a", "1", "c", "b", "3", "2")
36 | test_kwargs(test1=1, test2=2, test3=3)
37 |
38 | # 它可以传递列表(或者元组)的每一项并把它们解包. 注意必须与它们在函数里的参数相吻合
39 | a_list = ["名字", "值", "计数器"]
40 | star_operation(*a_list)
41 | ```
--------------------------------------------------------------------------------
/Python 语言特性/6 面向切面编程AOP和装饰器.md:
--------------------------------------------------------------------------------
1 | ```Python
2 | #!/bin/env python3
3 | # -*- coding: utf-8 -*-
4 | # version: Python3.X
5 | """ 练习一下自己怎么写一个装饰器
6 |
7 | 完整资料参考: https://taizilongxu.gitbooks.io/stackoverflow-about-python/content/3/README.html
8 | """
9 |
10 | __author__ = '__L1n__w@tch'
11 |
12 |
13 | def no_argument_decorator(function):
14 | # 注意这是在脚本被解释期间(还没进入 main 代码就在跑的了)
15 | print("I am a 无参数修饰器")
16 |
17 | def wrapper():
18 | print("{} 装饰开始 {}".format("*" * 30, "*" * 30))
19 | function()
20 | print("{} 装饰结束 {}".format("*" * 30, "*" * 30))
21 |
22 | return wrapper
23 |
24 |
25 | def decorator_maker_with_arguments(decorator_arg1, decorator_arg2):
26 | print("创建装饰器, 同时接收参数: {}, {}".format(decorator_arg1, decorator_arg2))
27 |
28 | def my_decorator(func):
29 | print("装饰器, 得到参数: {}, {}".format(decorator_arg1, decorator_arg2))
30 |
31 | # 不要忘了装饰器参数和函数参数!
32 | def wrapped(*args, **kwargs):
33 | print("装饰函数得到的参数: {}, {}, {}, {}".format(decorator_arg1, decorator_arg2,
34 | args, kwargs))
35 | return func(*args, **kwargs)
36 |
37 | return wrapped
38 |
39 | return my_decorator
40 |
41 |
42 | @decorator_maker_with_arguments("a", "b")
43 | # @no_argument_decorator
44 | def no_argument_function():
45 | print("I am a 普通的无参数函数")
46 |
47 |
48 | @decorator_maker_with_arguments("a", "b")
49 | # @no_argument_decorator
50 | def argument_function(*args):
51 | print("I am a 带多个参数的函数")
52 |
53 |
54 | @decorator_maker_with_arguments("a", "b")
55 | # @no_argument_decorator
56 | def args_kwargs_function(*args, **kwargs):
57 | print("I am a 带 args & kwargs 参数的函数")
58 |
59 |
60 | if __name__ == "__main__":
61 | no_argument_function()
62 | argument_function("c", "d")
63 | args_kwargs_function("c", "d")
64 | ```
--------------------------------------------------------------------------------
/Python 语言特性/7 单例模式.md:
--------------------------------------------------------------------------------
1 | # 文件 1
2 | singleton_for_import.py
3 | ```Python
4 | #!/bin/env python3
5 | # -*- coding: utf-8 -*-
6 | # version: Python3.X
7 | """ 作为被 import 的文件, 实现单例
8 | """
9 |
10 | __author__ = '__L1n__w@tch'
11 |
12 |
13 | class MySingleton:
14 | def foo(self):
15 | pass
16 |
17 |
18 | my_singleton = MySingleton()
19 |
20 | if __name__ == "__main__":
21 | pass
22 |
23 | ```
24 |
25 | # 文件 2
26 | singleton.py
27 | ```Python
28 | #!/bin/env python3
29 | # -*- coding: utf-8 -*-
30 | # version: Python3.X
31 | """ 单例模式的 4 种实现方法
32 |
33 | 1. 使用__new__方法
34 | 2. 共享属性(创建实例时把所有实例的 __dict__ 指向同一个字典,这样它们具有相同的属性和方法)
35 | 3. 装饰器版本
36 | 4. import方法
37 | """
38 | from singleton_for_import import my_singleton
39 |
40 | __author__ = '__L1n__w@tch'
41 |
42 |
43 | # 使用 __new__ 方法
44 | class Singleton:
45 | def __new__(cls, *args, **kwargs):
46 | if not hasattr(cls, "_instance"):
47 | orig = super(Singleton, cls)
48 | cls._instance = orig.__new__(cls, *args, **kwargs)
49 | return cls._instance
50 |
51 |
52 | class TestSingleton1(Singleton):
53 | var = 1
54 |
55 |
56 | """
57 | 共享属性的方法, 不知道为何出错了
58 | class Singleton2:
59 | _state = {}
60 |
61 | def __new__(cls, *args, **kwargs):
62 | ob = super(Singleton2, cls).__new__(cls, *args, **kwargs)
63 | ob.__dict__ = cls._state
64 | return ob
65 |
66 |
67 | class TestSingleton2(Singleton2):
68 | var = 2
69 | """
70 |
71 |
72 | def singleton(cls, *args, **kwargs):
73 | instances = dict()
74 |
75 | def get_instance():
76 | if cls not in instances:
77 | instances[cls] = cls(*args, **kwargs)
78 | return instances[cls]
79 |
80 | return get_instance
81 |
82 |
83 | @singleton
84 | class TestSingleton3:
85 | var = 3
86 |
87 |
88 | if __name__ == "__main__":
89 | ts1 = TestSingleton1()
90 | ts2 = TestSingleton1()
91 | assert ts1 == ts2 # 仅有一个实例
92 |
93 | # ts3 = TestSingleton2()
94 | # ts4 = TestSingleton2()
95 | # assert ts3 == ts4
96 |
97 | ts5 = TestSingleton3()
98 | ts6 = TestSingleton3()
99 | assert ts5 == ts6
100 |
101 | my_singleton.foo() # import 到的本身就是一个实例
102 | ```
--------------------------------------------------------------------------------
/Python 语言特性/8 Python 函数式编程.md:
--------------------------------------------------------------------------------
1 | # func_code
2 | ```Python
3 | #!/bin/env python3
4 | # -*- coding: utf-8 -*-
5 | # version: Python3.X
6 | """ 函数式编程相关知识
7 |
8 | 完整版参考资料:
9 | http://coolshell.cn/articles/10822.html
10 |
11 | Python 中函数式编程支持:
12 | filter 函数的功能相当于过滤器, 调用一个布尔函数 bool_func 来迭代遍历每个 seq 中的元素;
13 | 返回一个使 bool_seq 返回值为 true 的元素的序列
14 |
15 | map 函数是对一个序列的每个项依次执行函数
16 |
17 | reduce 函数是对一个序列的每个项迭代调用函数
18 | """
19 | import functools
20 |
21 | __author__ = '__L1n__w@tch'
22 |
23 |
24 | def test_filter():
25 | """
26 | 测试 filter 函数的功能
27 | :return:
28 | """
29 | wait_to_filter = [i for i in range(10)]
30 | after_filter = filter(lambda x: x > 5, wait_to_filter)
31 | print("测试 filter: {}".format(list(after_filter)))
32 |
33 |
34 | def test_map():
35 | """
36 | 测试 map 函数的功能
37 | :return:
38 | """
39 | wait_to_map = [i for i in range(10)]
40 | after_map = map(lambda x: x * 2, wait_to_map)
41 | print("测试 map: {}".format(list(after_map)))
42 |
43 |
44 | def test_reduce():
45 | """
46 | 测试 reduce 函数的功能, 看 doc 说 3.4 版本的 reduce 好像有所不同
47 | :return:
48 | """
49 | wait_to_reduce = [i for i in range(1, 4)]
50 | after_reduce = functools.reduce(lambda x, y: x * y, wait_to_reduce)
51 | print("测试 reduce: {}".format(after_reduce))
52 |
53 |
54 | if __name__ == "__main__":
55 | test_filter() # 过滤得到大于 5 的值
56 | test_map() # 对一个序列每个项都乘以 2
57 | test_reduce() # 求 3 的阶乘
58 |
59 | ```
--------------------------------------------------------------------------------
/Python 语言特性/9 Python 里的拷贝.md:
--------------------------------------------------------------------------------
1 | # about_copy.py
2 | ```Python
3 | #!/bin/env python3
4 | # -*- coding: utf-8 -*-
5 | # version: Python3.X
6 | """ 关于 Python 的拷贝, 有引用/浅复制/深复制的区别, (引用和 copy(), deepcopy() 的区别)
7 | """
8 |
9 | import copy
10 |
11 | __author__ = '__L1n__w@tch'
12 |
13 | if __name__ == "__main__":
14 | List = [1, 2, 3, 4, ["a", "b"]]
15 |
16 | one_list = List # 赋值, 传对象的引用
17 | second_list = copy.copy(List) # 对象拷贝, 浅拷贝
18 | third_list = copy.deepcopy(List) # 对象拷贝,深拷贝
19 |
20 | List.append(5) # 修改对象 List
21 | List[4].append("c")
22 |
23 | print("List: {}".format(List))
24 | print("one_list: {}".format(one_list))
25 | print("second_list: {}".format(second_list))
26 | print("third_list: {}".format(third_list))
27 | ```
--------------------------------------------------------------------------------
/Python 语言特性/readme.md:
--------------------------------------------------------------------------------
1 | # Python 语言特性
2 | 这一个节里主要是练习 Python 语言特性的相关代码。
3 | ## 参考资料
4 | [interview_Python](https://github.com/taizilongxu/interview_Python#Python%E8%AF%AD%E8%A8%80%E7%89%B9%E6%80%A7)
5 | ## 清单
6 | 1. Python的函数参数传递
7 | 2. @staticmethod和@classmethod
8 | 3. 类变量和实例变量
9 | 4. Python中单下划线和双下划线
10 | 5. \*args and \*\*kwargs
11 | 6. 面向切面编程AOP和装饰器
12 | 7. 单例模式
13 | 8. Python 函数式编程
14 | 9. Python 里的拷贝
15 |
16 | ## 零散知识点
17 |
18 | ### 元类(metaclass)
19 |
20 | 这个非常的不常用, 但是像 ORM 这种复杂的结构还是会需要的, [详情](http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-Python)
21 |
22 | ### 自省
23 |
24 | 自省就是面向对象的语言所写的程序在运行时, 所能知道对象的类型.
25 |
26 | 简单一句就是运行时能够获得对象的类型.
27 |
28 | 比如 ``type(), dir(), getattr(), hasattr(), isinstance()``.
29 |
30 | ### 字典推导式
31 |
32 | 可能你见过列表推导时 \#, 却没有见过字典推导式, 在 2.7 中才加入的:
33 | ``d = {key: value for (key, value) in iterable}``
34 |
35 | ### 字符串格式化: % 和 .format
36 |
37 | ``.format`` 在许多方面看起来更便利.
38 |
39 | 对于 % 最烦人的是它无法同时传递一个变量和元组. 你可能会想下面的代码不会有什么问题:
40 |
41 | ``"hi there %s" % name``
42 | 但是, 如果 name 恰好是 (1,2,3), 它将会抛出一个 TypeError 异常.
43 |
44 | 为了保证它总是正确的, 你必须这样做:
45 |
46 | ``"hi there %s" % (name,) # 提供一个单元素的数组而不是一个参数``
47 | 但是有点丑.
48 |
49 | ``.format`` 就没有这些问题.你给的第二个问题也是这样, ``.format``好看多了.
50 |
51 | 你为什么不用它?
52 |
53 | * 不知道它(在读这个之前)
54 |
55 |
56 | * 为了和 Python2.5 兼容(譬如 [logging 库建议使用 %](http://stackoverflow.com/questions/5082452/Python-string-formatting-vs-format))
57 |
58 | ### 迭代器和生成器
59 |
60 | [参考](https://taizilongxu.gitbooks.io/stackoverflow-about-Python/content/1/README.html)
61 |
62 | ### 鸭子类型
63 |
64 | “当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
65 | 我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。
66 | 比如在 Python 中,有很多 file-like 的东西,比如 StringIO, GzipFile, socket。它们有很多相同的方法,我们把它们当作文件使用。
67 | 又比如 ``list.extend()`` 方法中, 我们并不关心它的参数是不是 list, 只要它是可迭代的, 所以它的参数可以是 list/tuple/dict/字符串/生成器等.
68 | 鸭子类型在动态语言中经常使用,非常灵活,使得 Python 不像 java那样专门去弄一大堆的设计模式。
69 |
70 | ### Python 中重载
71 |
72 | 函数重载主要是为了解决两个问题:
73 |
74 | * 可变参数类型
75 |
76 |
77 | * 可变参数个数
78 |
79 | 另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应当使用重载,而应当使用一个名字不同的函数。
80 | 好吧,那么对于情况 1 ,函数功能相同,但是参数类型不同,Python 如何处理?答案是根本不需要处理,因为 Python 可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在 Python 中很可能是相同的代码,没有必要做成两个不同函数。
81 | 那么对于情况 2 ,函数功能相同,但参数个数不同,Python 如何处理?大家知道,答案就是缺省参数。对那些缺少的参数设定为缺省参数即可解决问题。因为你假设函数功能相同,那么那些缺少的参数终归是需要用的。
82 | 好了,鉴于情况 1 跟 情况 2 都有了解决方案,Python 自然就不需要函数重载了。
83 |
84 | ### 新式类和旧式类
85 |
86 | [这篇文章](http://www.cnblogs.com/btchenguang/archive/2012/09/17/2689146.html)很好的介绍了新式类的特性
87 | 新式类很早在 2.2 就出现了,所以旧式类完全是兼容的问题, Python3 里的类全部都是新式类. 这里有一个 MRO 问题可以了解下(新式类是广度优先,旧式类是深度优先),里讲的也很多.
88 |
89 | ### \_\_new\_\_ 和 \_\_init\_\_ 的区别
90 |
91 | * \_\_new\_\_ 是一个静态方法, 而\_\_init\_\_ 是一个实例方法.
92 |
93 |
94 | * \_\_new\_\_ 方法会返回一个创建的实例, 而\_\_init\_\_ 什么都不返回.
95 |
96 |
97 | * 只有在 \_\_new\_\_ 返回一个 cls 的实例时后面的 \_\_init\_\_ 才能被调用.
98 |
99 |
100 | * 当创建一个新实例时调用 \_\_new\_\_, 初始化一个实例时用 \_\_init\_\_.
101 |
102 | PS: \_\_metaclass\_\_ 是创建类时起作用. 所以我们可以分别使用 \_\_metaclass\_\_, \_\_new\_\_ 和 \_\_init\_\_ 来分别在类创建,实例创建和实例初始化的时候做一些小手脚.
103 |
104 | ### Python 中的作用域
105 |
106 | Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。
107 | 当 Python 遇到一个变量的话他会按照这样的顺序进行搜索:
108 | ``本地作用域(Local)→ 当前作用域被嵌入的本地作用域(Enclosing locals)→ 全局/模块作用域(Global)→ 内置作用域(Built-in)` `
109 |
110 | ### GIL 线程全局锁
111 |
112 | 线程全局锁(Global Interpreter Lock), 即 Python 为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.
113 | 见 Python 最难的问题
114 | 解决办法就是多进程和下面的协程(协程也只是单 CPU,但是能减小切换代价提升性能).
115 |
116 | ### 协程
117 |
118 | 简单点说协程是进程和线程的升级版, 进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间, 而协程就是用户自己控制切换的时机, 不再需要陷入系统的内核态.
119 | Python 里最常见的 yield 就是协程的思想!
120 |
121 | ### 闭包
122 |
123 | 闭包(closure)是函数式编程的重要的语法结构。闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。
124 | 当一个内嵌函数引用其外部作作用域的变量,我们就会得到一个闭包. 总结一下,创建一个闭包必须满足以下几点:
125 | * 必须有一个内嵌函数
126 |
127 | * 内嵌函数必须引用外部函数中的变量
128 |
129 | * 外部函数的返回值必须是内嵌函数
130 |
131 | 感觉闭包还是有难度的,几句话是说不明白的,还是查查相关资料.
132 |
133 | 重点是函数运行后并不会被撤销, 就像 16 题的 instance 字典一样, 当函数运行完后, instance 并不被销毁,而是继续留在内存空间里.
134 |
135 | 这个功能类似类里的类变量, 只不过迁移到了函数上.
136 |
137 | 闭包就像个空心球一样, 你知道外面和里面, 但你不知道中间是什么样.
138 |
139 | ### lambda 函数
140 | 其实就是一个匿名函数,为什么叫 lambda?因为和后面的函数式编程有关.
141 |
142 | ### Python 垃圾回收机制
143 | Python GC 主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率。
144 | * 引用计数
145 | * PyObject 是每个对象必有的内容,其中 ob_refcnt 就是做为引用计数。当一个对象有新的引用时,它的 ob_refcnt 就会增加,当引用它的对象被删除,它的 ob_refcnt 就会减少.引用计数为 0 时,该对象生命就结束了。
146 | * 优点:
147 | * 简单
148 | * 实时性
149 | * 缺点:
150 | * 维护引用计数消耗资源
151 | * 循环引用
152 | * 标记-清除机制
153 | * 基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。
154 | * 分代技术
155 | * 分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。
156 | * Python 默认定义了三代对象集合,索引数越大,对象存活时间越长。
157 | * 举例: 当某些内存块 M 经过了 3 次垃圾收集的清洗之后还存活时,我们就将内存块 M 划到一个集合 A 中去,而新分配的内存都划分到集合 B 中去。当垃圾收集开始工作时,大多数情况都只对集合 B 进行垃圾回收,而对集合 A 进行垃圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。在这个过程中,集合 B 中的某些内存块由于存活时间长而会被转移到集合 A 中,当然,集合 A 中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟。
158 |
159 | ### Python 的 List
160 |
161 | [推荐](http://www.jianshu.com/p/J4U6rR)
162 |
163 | ### Python 的 is
164 |
165 | is 是对比地址,== 是对比值
166 |
167 | ### read, readline 和 readlines
168 |
169 | * read 读取整个文件
170 | * readline 读取下一行,使用生成器方法
171 | * readlines 读取整个文件到一个迭代器以供我们遍历
172 |
173 | ### Python 2 和 3 的区别
174 |
175 | [Python 2.7.x 与 Python 3.x 的主要差异](http://chenqx.github.io/2014/11/10/Key-differences-between-Python-2-7-x-and-Python-3-x/)
--------------------------------------------------------------------------------
/Python 面试编程题/1 台阶问题 斐波那契/fibonacci.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 又见斐波那契数列
5 |
6 | 这回是练习了经典的面试题:
7 | 一只青蛙一次可以跳上 1 级台阶, 也可以跳上 2 级. 求该青蛙跳上一个 n 级的台阶总共有多少种跳法?
8 |
9 | 斐波那契除了 GitHub 面试题给的那三种外, 还有我之前实现过的一种, 都整理在这个文件了
10 | """
11 | import timeit
12 | from functools import wraps
13 |
14 | __author__ = '__L1n__w@tch'
15 |
16 |
17 | def recursion(n):
18 | """
19 | 普通的递归求斐波那契
20 | :param n:
21 | :return:
22 | """
23 | if n <= 2:
24 | return n
25 | else:
26 | return recursion(n - 1) + recursion(n - 2)
27 |
28 |
29 | def memory(function):
30 | """
31 | 作为修饰器存在的
32 | :param function:
33 | :return:
34 | """
35 | cache = {}
36 |
37 | @wraps(function) # 加这句主要是为了保留被修饰的函数的名字
38 | def wrap(args):
39 | if args not in cache:
40 | cache[args] = function(args)
41 | return cache[args]
42 |
43 | return wrap
44 |
45 |
46 | @memory
47 | def memory_recursion(n):
48 | """
49 | 函数本身依旧是普通的递归求斐波那契, 但是装有修饰器
50 | :param n:
51 | :return:
52 | """
53 | if n <= 2:
54 | return n
55 | else:
56 | return memory_recursion(n - 1) + memory_recursion(n - 2)
57 |
58 |
59 | def circle(n):
60 | """
61 | 循环求斐波那契
62 | :param n:
63 | :return:
64 | """
65 | a, b = 0, 1
66 | for i in range(n):
67 | a, b = b, a + b
68 | return b
69 |
70 |
71 | class Fibonacci:
72 | """
73 | 自己之前写的一个斐波那契数列
74 | """
75 |
76 | def __init__(self, f0, f1):
77 | self.f0 = f0
78 | self.f1 = f1
79 |
80 | def _fib(self, a, b):
81 | a = self.f0
82 | b = self.f1
83 | yield a
84 | yield b
85 | while True:
86 | a, b = b, a + b
87 | yield b
88 |
89 | def fib_generator(self):
90 | """
91 | 生成器
92 | :return:
93 | """
94 | return self._fib(self.f0, self.f1)
95 |
96 |
97 | if __name__ == "__main__":
98 | print("方法一: 匿名函数(其实就是递归), 注意这种写法被 PEP8 报警了...")
99 | # fibonacci_1 = lambda n: n if n <= 2 else fibonacci_1(n - 1) + fibonacci_1(n - 2)
100 | fibonacci_1 = recursion
101 | time_cost = timeit.timeit("recursion(33)", setup="from fibonacci import recursion", number=1)
102 | print("fibonacci_1(33) 耗时: {}".format(time_cost))
103 |
104 | print("方法二: 依旧递归求解, 不过加了个记忆用的修饰器, 速率翻倍了都")
105 | fibonacci_2 = memory_recursion
106 | time_cost = timeit.timeit("memory_recursion(33)", setup="from fibonacci import memory_recursion")
107 | print("fibonacci_2(33) 耗时: {}".format(time_cost))
108 |
109 | print("方法三: 循环求解")
110 | fibonacci_3 = circle
111 | time_cost = timeit.timeit("circle(33)", setup="from fibonacci import circle", number=1)
112 | print("fibonacci_3(33) 耗时: {}".format(time_cost))
113 |
114 | print("方法四: 同样循环求解, 不过是通过生成器实现的")
115 | fibonacci_4 = Fibonacci(1, 2).fib_generator()
116 |
--------------------------------------------------------------------------------
/Python 面试编程题/1 台阶问题 斐波那契/unittest_fibonacci.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 需要练习一下单元测试的相关知识
5 |
6 | 本文件是对同文件夹下的 fibonacci 几种写法进行测试
7 | """
8 | import unittest
9 | from fibonacci import recursion, memory_recursion, circle
10 |
11 |
12 | __author__ = '__L1n__w@tch'
13 |
14 |
15 | class FibonacciTest(unittest.TestCase):
16 | def setUp(self):
17 | self.wait_to_test = [recursion, memory_recursion, circle] # 待测试的函数
18 |
19 | def normal_test(self):
20 | """
21 | 简单的功能性测试罢了
22 | :return:
23 | """
24 | for function in self.wait_to_test:
25 | self.failUnless(function(1) == 1)
26 | self.failUnless(function(2) == 2)
27 | self.failUnless(function(3) == 3)
28 | self.failUnless(function(4) == 5)
29 | self.failUnless(function(5) == 8)
30 | self.failUnless(function(6) == 13)
31 | self.failUnless(function(7) == 21)
32 | self.failUnless(function(13) == 377)
33 | self.failUnless(function(15) == 987)
34 | self.failUnless(function(20) == 10946)
35 | self.failUnless(function(25) == 121393)
36 | self.failUnless(function(29) == 832040)
37 | self.failUnless(function(33) == 5702887)
38 | if function.__name__ == "recursion":
39 | print("递归 50 次时间太长, 不测试了")
40 | continue
41 | self.failUnless(function(50) == 20365011074)
42 | print("函数: {}, 测试完毕".format(function.__name__))
43 |
44 |
45 | if __name__ == "__main__":
46 | unittest.main()
47 |
--------------------------------------------------------------------------------
/Python 面试编程题/1 台阶问题 斐波那契/斐波那契.md:
--------------------------------------------------------------------------------
1 | # 题目说明
2 | 经典的面试题:
3 |
4 | 一只青蛙一次可以跳上 1 级台阶, 也可以跳上 2 级. 求该青蛙跳上一个 n 级的台阶总共有多少种跳法?
5 |
6 | 斐波那契除了 GitHub 面试题给的那三种外, 还有我之前实现过的一种, 都整理在这个文件了, 包括:
7 | * 递归求斐波那契(函数形式)
8 | * 循环求斐波那契(函数形式)
9 | * 带记忆的递归求斐波那契(函数形式 + 装饰器)
10 | * 循环求斐波那契(类形式)
11 |
12 | # fibonacci.py
13 | ```Python
14 | #!/bin/env python3
15 | # -*- coding: utf-8 -*-
16 | # version: Python3.X
17 |
18 | import timeit
19 | from functools import wraps
20 |
21 | __author__ = '__L1n__w@tch'
22 |
23 |
24 | def recursion(n):
25 | """
26 | 普通的递归求斐波那契
27 | :param n:
28 | :return:
29 | """
30 | if n <= 2:
31 | return n
32 | else:
33 | return recursion(n - 1) + recursion(n - 2)
34 |
35 |
36 | def memory(function):
37 | """
38 | 作为修饰器存在的
39 | :param function:
40 | :return:
41 | """
42 | cache = {}
43 |
44 | @wraps(function) # 加这句主要是为了保留被修饰的函数的名字
45 | def wrap(args):
46 | if args not in cache:
47 | cache[args] = function(args)
48 | return cache[args]
49 |
50 | return wrap
51 |
52 |
53 | @memory
54 | def memory_recursion(n):
55 | """
56 | 函数本身依旧是普通的递归求斐波那契, 但是装有修饰器
57 | :param n:
58 | :return:
59 | """
60 | if n <= 2:
61 | return n
62 | else:
63 | return memory_recursion(n - 1) + memory_recursion(n - 2)
64 |
65 |
66 | def circle(n):
67 | """
68 | 循环求斐波那契
69 | :param n:
70 | :return:
71 | """
72 | a, b = 0, 1
73 | for i in range(n):
74 | a, b = b, a + b
75 | return b
76 |
77 |
78 | class Fibonacci:
79 | """
80 | 自己之前写的一个斐波那契数列
81 | """
82 |
83 | def __init__(self, f0, f1):
84 | self.f0 = f0
85 | self.f1 = f1
86 |
87 | def _fib(self, a, b):
88 | a = self.f0
89 | b = self.f1
90 | yield a
91 | yield b
92 | while True:
93 | a, b = b, a + b
94 | yield b
95 |
96 | def fib_generator(self):
97 | """
98 | 生成器
99 | :return:
100 | """
101 | return self._fib(self.f0, self.f1)
102 |
103 |
104 | if __name__ == "__main__":
105 | print("方法一: 匿名函数(其实就是递归), 注意这种写法被 PEP8 报警了...")
106 | # fibonacci_1 = lambda n: n if n <= 2 else fibonacci_1(n - 1) + fibonacci_1(n - 2)
107 | fibonacci_1 = recursion
108 | time_cost = timeit.timeit("recursion(33)", setup="from fibonacci import recursion", number=1)
109 | print("fibonacci_1(33) 耗时: {}".format(time_cost))
110 |
111 | print("方法二: 依旧递归求解, 不过加了个记忆用的修饰器, 速率翻倍了都")
112 | fibonacci_2 = memory_recursion
113 | time_cost = timeit.timeit("memory_recursion(33)", setup="from fibonacci import memory_recursion")
114 | print("fibonacci_2(33) 耗时: {}".format(time_cost))
115 |
116 | print("方法三: 循环求解")
117 | fibonacci_3 = circle
118 | time_cost = timeit.timeit("circle(33)", setup="from fibonacci import circle", number=1)
119 | print("fibonacci_3(33) 耗时: {}".format(time_cost))
120 |
121 | print("方法四: 同样循环求解, 不过是通过生成器实现的")
122 | fibonacci_4 = Fibonacci(1, 2).fib_generator()
123 | ```
124 |
125 | # 单元测试
126 | 本文件是对同文件夹下的 fibonacci 几种写法进行测试
127 | ```Python
128 | #!/bin/env python3
129 | # -*- coding: utf-8 -*-
130 | # version: Python3.X
131 |
132 | import unittest
133 | from fibonacci import recursion, memory_recursion, circle
134 |
135 |
136 | __author__ = '__L1n__w@tch'
137 |
138 |
139 | class FibonacciTest(unittest.TestCase):
140 | def setUp(self):
141 | self.wait_to_test = [recursion, memory_recursion, circle] # 待测试的函数
142 |
143 | def normal_test(self):
144 | """
145 | 简单的功能性测试罢了
146 | :return:
147 | """
148 | for function in self.wait_to_test:
149 | self.failUnless(function(1) == 1)
150 | self.failUnless(function(2) == 2)
151 | self.failUnless(function(3) == 3)
152 | self.failUnless(function(4) == 5)
153 | self.failUnless(function(5) == 8)
154 | self.failUnless(function(6) == 13)
155 | self.failUnless(function(7) == 21)
156 | self.failUnless(function(13) == 377)
157 | self.failUnless(function(15) == 987)
158 | self.failUnless(function(20) == 10946)
159 | self.failUnless(function(25) == 121393)
160 | self.failUnless(function(29) == 832040)
161 | self.failUnless(function(33) == 5702887)
162 | if function.__name__ == "recursion":
163 | print("递归 50 次时间太长, 不测试了")
164 | continue
165 | self.failUnless(function(50) == 20365011074)
166 | print("函数: {}, 测试完毕".format(function.__name__))
167 |
168 |
169 | if __name__ == "__main__":
170 | unittest.main()
171 | ```
--------------------------------------------------------------------------------
/Python 面试编程题/10 快排/qsort.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 快排的 Python 实现
5 | """
6 |
7 | __author__ = '__L1n__w@tch'
8 |
9 |
10 | def qsort(a_list):
11 | if len(a_list) == 0:
12 | return a_list
13 | else:
14 | pivot = a_list[0]
15 | small = qsort([x for x in a_list[1:] if x < pivot])
16 | big = qsort([x for x in a_list[1:] if x >= pivot])
17 | return small + [pivot] + big
18 |
19 |
20 | if __name__ == "__main__":
21 | List = [1, 3, 5, 1, 2]
22 | print(qsort(List))
23 |
--------------------------------------------------------------------------------
/Python 面试编程题/10 快排/unittest_sort.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 单元测试快排
5 | """
6 | import random
7 | import unittest
8 | from qsort import qsort
9 |
10 |
11 | __author__ = '__L1n__w@tch'
12 |
13 |
14 | class TestQSort(unittest.TestCase):
15 | def test_qsort(self):
16 | for i in range(30):
17 | list_wait_to_sort = [random.randint(-1000, 1000) for i in range(100)]
18 | self.failUnless(sorted(list_wait_to_sort) == qsort(list_wait_to_sort))
19 |
--------------------------------------------------------------------------------
/Python 面试编程题/10 快排/快排.md:
--------------------------------------------------------------------------------
1 | # 题目
2 | 快排实现
3 |
4 | # qsort.py
5 | ```Python
6 | #!/bin/env python3
7 | # -*- coding: utf-8 -*-
8 | # version: Python3.X
9 |
10 |
11 | __author__ = '__L1n__w@tch'
12 |
13 |
14 | def qsort(a_list):
15 | if len(a_list) == 0:
16 | return a_list
17 | else:
18 | pivot = a_list[0]
19 | small = qsort([x for x in a_list[1:] if x < pivot])
20 | big = qsort([x for x in a_list[1:] if x >= pivot])
21 | return small + [pivot] + big
22 |
23 |
24 | if __name__ == "__main__":
25 | List = [1, 3, 5, 1, 2]
26 | print(qsort(List))
27 | ```
28 |
29 | # 单元测试
30 | ```Python
31 | #!/bin/env python3
32 | # -*- coding: utf-8 -*-
33 | # version: Python3.X
34 | """ 单元测试快排
35 | """
36 | import random
37 | import unittest
38 | from qsort import qsort
39 |
40 |
41 | __author__ = '__L1n__w@tch'
42 |
43 |
44 | class TestQSort(unittest.TestCase):
45 | def test_qsort(self):
46 | for i in range(30):
47 | list_wait_to_sort = [random.randint(-1000, 1000) for i in range(100)]
48 | self.failUnless(sorted(list_wait_to_sort) == qsort(list_wait_to_sort))
49 | ```
--------------------------------------------------------------------------------
/Python 面试编程题/11 找零问题/coin_change.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 找零问题, 为啥看答案有点像背包问题...
5 | """
6 |
7 | __author__ = '__L1n__w@tch'
8 |
9 |
10 | def coin_change(values, money):
11 | """
12 | 背包问题解法?
13 | :param values: [25, 21, 10, 5, 1]
14 | :param money: 63
15 | :return: {1:1, 2:2, 3:3, 4:4, 5:1, ..., 63:3}
16 | """
17 | coin_count = {i: 0 for i in range(money_wait_to_change + 1)}
18 |
19 | for cents in range(1, money + 1):
20 | min_coins = cents # 从第一个开始到money的所有情况初始
21 | for value in values:
22 | if value <= cents:
23 | temp = coin_count[cents - value] + 1 # 这不是经典的背包?
24 | if temp < min_coins:
25 | min_coins = temp
26 | coin_count[cents] = min_coins
27 | print('面值为:{0} 的最小硬币数目为:{1} '.format(cents, coin_count[cents]))
28 |
29 |
30 | if __name__ == '__main__':
31 | pocket_monkey = [25, 21, 10, 5, 1]
32 | money_wait_to_change = 63
33 | coin_change(pocket_monkey, money_wait_to_change)
34 |
--------------------------------------------------------------------------------
/Python 面试编程题/11 找零问题/找零问题.md:
--------------------------------------------------------------------------------
1 | # 题目
2 | 找零问题, 给个金额让你找出对应的最小硬币数目
3 |
4 | # coin_change.py
5 | ```Python
6 | #!/bin/env python3
7 | # -*- coding: utf-8 -*-
8 | # version: Python3.X
9 |
10 |
11 | __author__ = '__L1n__w@tch'
12 |
13 |
14 | def coin_change(values, money):
15 | """
16 | 背包问题解法?
17 | :param values: [25, 21, 10, 5, 1]
18 | :param money: 63
19 | :return: {1:1, 2:2, 3:3, 4:4, 5:1, ..., 63:3}
20 | """
21 | coin_count = {i: 0 for i in range(money_wait_to_change + 1)}
22 |
23 | for cents in range(1, money + 1):
24 | min_coins = cents # 从第一个开始到money的所有情况初始
25 | for value in values:
26 | if value <= cents:
27 | temp = coin_count[cents - value] + 1 # 这不是经典的背包?
28 | if temp < min_coins:
29 | min_coins = temp
30 | coin_count[cents] = min_coins
31 | print('面值为:{0} 的最小硬币数目为:{1} '.format(cents, coin_count[cents]))
32 |
33 |
34 | if __name__ == '__main__':
35 | pocket_monkey = [25, 21, 10, 5, 1]
36 | money_wait_to_change = 63
37 | coin_change(pocket_monkey, money_wait_to_change)
38 | ```
39 |
--------------------------------------------------------------------------------
/Python 面试编程题/13 单链表逆置/single_list_reverse.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 对单链表实现逆置操作, 即 1 -> 2 -> 3 变为 3 -> 2 -> 1
5 | """
6 |
7 | __author__ = '__L1n__w@tch'
8 |
9 |
10 | class ListNode:
11 | def __init__(self, data=None, next_node=None):
12 | self.data = data
13 | self.next_node = next_node
14 |
15 |
16 | def print_single_list(head_node):
17 | """
18 | 打印单链表
19 | :param head_node: ListNode()
20 | :return: None
21 | """
22 | if head_node:
23 | print(head_node.data, end=" -> ")
24 | next_node = head_node.next_node
25 | while next_node:
26 | print(next_node.data, end=" -> ")
27 | next_node = next_node.next_node
28 | print("None")
29 |
30 |
31 | def reverse_single_list(head_node):
32 | """
33 | GitHub 上的思路是用 3 个指针, 自己的思路是用栈来解决, 看起来 GitHub 思路简单些
34 | :param head_node: ListNode()
35 | :return: None
36 | """
37 | pre = head_node
38 | current = head_node.next_node
39 | pre.next_node = None
40 |
41 | while current:
42 | temp = current.next_node
43 | current.next_node = pre
44 | pre = current
45 | current = temp
46 | return pre
47 |
48 |
49 | if __name__ == "__main__":
50 | single_list = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5, ListNode(6, ListNode(7, ListNode(8))))))))
51 | print_single_list(single_list)
52 |
53 | reversed_single_list = reverse_single_list(single_list)
54 | print_single_list(reversed_single_list)
55 |
--------------------------------------------------------------------------------
/Python 面试编程题/13 单链表逆置/单链表逆置.md:
--------------------------------------------------------------------------------
1 | # 题目
2 | 对单链表实现逆置操作, 即 `1 -> 2 -> 3` 变为 `3 -> 2 -> 1`
3 |
4 | # single_list_reverse.py
5 | ```python
6 | #!/bin/env python3
7 | # -*- coding: utf-8 -*-
8 | # version: Python3.X
9 |
10 |
11 | __author__ = '__L1n__w@tch'
12 |
13 |
14 | class ListNode:
15 | def __init__(self, data=None, next_node=None):
16 | self.data = data
17 | self.next_node = next_node
18 |
19 |
20 | def print_single_list(head_node):
21 | """
22 | 打印单链表
23 | :param head_node: ListNode()
24 | :return: None
25 | """
26 | if head_node:
27 | print(head_node.data, end=" -> ")
28 | next_node = head_node.next_node
29 | while next_node:
30 | print(next_node.data, end=" -> ")
31 | next_node = next_node.next_node
32 | print("None")
33 |
34 |
35 | def reverse_single_list(head_node):
36 | """
37 | GitHub 上的思路是用 3 个指针, 自己的思路是用栈来解决, 看起来 GitHub 思路简单些
38 | :param head_node: ListNode()
39 | :return: None
40 | """
41 | pre = head_node
42 | current = head_node.next_node
43 | pre.next_node = None
44 |
45 | while current:
46 | temp = current.next_node
47 | current.next_node = pre
48 | pre = current
49 | current = temp
50 | return pre
51 |
52 |
53 | if __name__ == "__main__":
54 | single_list = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5, ListNode(6, ListNode(7, ListNode(8))))))))
55 | print_single_list(single_list)
56 |
57 | reversed_single_list = reverse_single_list(single_list)
58 | print_single_list(reversed_single_list)
59 | ```
--------------------------------------------------------------------------------
/Python 面试编程题/2 变态台阶问题/similar_frog_jump.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 变态台阶问题, 一只青蛙一次可以跳上 1 级台阶, 也可以跳上 2 级, 它也可以跳上 n 级. 求该青蛙跳上一个 n 级的台阶总共有多少种跳法
5 |
6 | 根据数学归纳法可证得答案为 2 ^ n - 1 (可参考剑指 Offer 面试题 9)
7 | """
8 |
9 | __author__ = '__L1n__w@tch'
10 |
11 |
12 | def recursion(steps):
13 | if steps < 2:
14 | return steps
15 | else:
16 | return 2 * recursion(steps - 1)
17 |
18 |
19 | if __name__ == "__main__":
20 | n = 233
21 | print("{} 级台阶: {}".format(n, recursion(n)))
22 |
23 | compute_jump = lambda steps: steps if steps < 2 else 2 * compute_jump(steps - 1)
24 | print("{} 级台阶: {}".format(n, compute_jump(n)))
25 |
--------------------------------------------------------------------------------
/Python 面试编程题/2 变态台阶问题/变态台阶问题.md:
--------------------------------------------------------------------------------
1 | # 题目说明
2 | 变态台阶问题, 一只青蛙一次可以跳上 1 级台阶, 也可以跳上 2 级, 它也可以跳上 n 级. 求该青蛙跳上一个 n 级的台阶总共有多少种跳法?
3 |
4 | 根据数学归纳法可证得答案为 `2 ^ (n - 1)` (可参考剑指 Offer 面试题 9)
5 |
6 | # similar_frog_jump.py
7 | ```Python
8 | #!/bin/env python3
9 | # -*- coding: utf-8 -*-
10 | # version: Python3.X
11 |
12 | __author__ = '__L1n__w@tch'
13 |
14 |
15 | def recursion(steps):
16 | if steps < 2:
17 | return steps
18 | else:
19 | return 2 * recursion(steps - 1)
20 |
21 |
22 | if __name__ == "__main__":
23 | n = 233
24 | print("{} 级台阶: {}".format(n, recursion(n)))
25 |
26 | compute_jump = lambda steps: steps if steps < 2 else 2 * compute_jump(steps - 1)
27 | print("{} 级台阶: {}".format(n, compute_jump(n)))
28 | ```
--------------------------------------------------------------------------------
/Python 面试编程题/3 矩形覆盖/rectangle.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 矩形覆盖
5 |
6 | 同样可以参考剑指 Offer (面试题 9)
7 |
8 | 解题思路摘要:
9 | 可以用 2 * 1 的小矩形横着或者竖着去覆盖更大的矩形。请问用 8 个 2 * 1 的小矩形无重叠地覆盖一个 2 * 8 的大矩形,总共有多少种方法?
10 |
11 | 我们先把 2 * 8 的覆盖方法记为 f(8)。用第一个 1 * 2 小矩形去覆盖大矩形的最左边时有两个选择,竖着放或者横着放。
12 | 当竖着放的时候,右边还剩下2 * 7 的区域,这种情况下的覆盖方法记为 f(7)。
13 |
14 | 接下来考虑横着放的情况。当 1 * 2 的小矩形横着放在左上角的时候,右下角必须和横着放一个 1 * 2 的小矩形,而在右边还剩下 2 * 6 的区域,
15 | 这种情形下的覆盖方法记为 f(6),因此 f(8) = f(7) + f(6)。此时可以看出,这仍然是斐波那契数列。
16 | """
17 |
18 | __author__ = '__L1n__w@tch'
19 |
20 |
21 | def circle_fibonacci(steps, fn_1, fn_2):
22 | """
23 | 循环求解斐波那契数列, f(n) = f(n - 1) + f(n - 2)
24 | :param steps: 阶数
25 | :param fn_1: f(n - 1)
26 | :param fn_2: f(n - 2)
27 | :return: f(n)
28 | """
29 | for i in range(steps):
30 | fn_1, fn_2 = fn_2, fn_1 + fn_2
31 | return fn_2
32 |
33 |
34 | if __name__ == "__main__":
35 | n = 3
36 |
37 | print("{} 级台阶: {}".format(n, circle_fibonacci(n, 0, 1)))
38 |
--------------------------------------------------------------------------------
/Python 面试编程题/3 矩形覆盖/矩阵覆盖.md:
--------------------------------------------------------------------------------
1 | # 题目说明
2 |
3 | 矩形覆盖
4 |
5 | 可以用 2 \* 1 的小矩形横着或者竖着去覆盖更大的矩形。请问用 8 个 2 \* 1 的小矩形无重叠地覆盖一个 2 \* 8 的大矩形,总共有多少种方法?
6 |
7 | 同样可以参考剑指 Offer \(面试题 9\)
8 |
9 | 解题思路摘要:
10 |
11 | ```
12 | 我们先把 2 * 8 的覆盖方法记为 f(8)。用第一个 1 * 2 小矩形去覆盖大矩形的最左边时有两个选择,竖着放或者横着放。
13 |
14 | 当竖着放的时候,右边还剩下2 * 7 的区域,这种情况下的覆盖方法记为 f(7)。
15 |
16 | 接下来考虑横着放的情况。当 1 * 2 的小矩形横着放在左上角的时候,右下角必须和横着放一个 1 * 2 的小矩形,而在右边还剩下 2 * 6 的区域。
17 |
18 | 这种情形下的覆盖方法记为 f(6),因此 f(8) = f(7) + f(6)。此时可以看出,这仍然是斐波那契数列。
19 | ```
20 |
21 | # rectangle.py
22 |
23 | ```python
24 | #!/bin/env python3
25 | # -*- coding: utf-8 -*-
26 | # version: Python3.X
27 |
28 | __author__ = '__L1n__w@tch'
29 |
30 |
31 | def circle_fibonacci(steps, fn_1, fn_2):
32 | """
33 | 循环求解斐波那契数列, f(n) = f(n - 1) + f(n - 2)
34 | :param steps: 阶数
35 | :param fn_1: f(n - 1)
36 | :param fn_2: f(n - 2)
37 | :return: f(n)
38 | """
39 | for i in range(steps):
40 | fn_1, fn_2 = fn_2, fn_1 + fn_2
41 | return fn_2
42 |
43 |
44 | if __name__ == "__main__":
45 | n = 3
46 |
47 | print("{} 级台阶: {}".format(n, circle_fibonacci(n, 0, 1)))
48 | ```
49 |
50 |
--------------------------------------------------------------------------------
/Python 面试编程题/4 杨氏矩阵查找/rectangle_search.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ GitHub 上只给了题目没给源代码, 是嫌太简单了吗...
5 |
6 | 题目描述:
7 | 在一个 m 行 n 列二维数组中, 每一行都按照从左到右递增的顺序排序, 每一列都按照从上到下递增的顺序排序.
8 | 请完成一个函数, 输入这样的一个二维数组和一个整数, 判断数组中是否含有该整数
9 |
10 | 解答思路:
11 | 参考: 剑指 Offer (面试题 3)
12 | 总结查找的过程,发现规律如下:
13 | 首先选取数组中右上角的数字。如果该数字等于要查找的数字,查找过程结束;
14 | 如果该数字大于要查找的数字,剔除这个数字所在的列;
15 | 如果该数字小于要查找的数字,剔除这个数字所在的行。
16 | 也就是说如果要查找的数字不在数组的右上角,则每一次都在数组的查找范围中剔除一行或者一列,这样每一步都可以缩小查找的范围,
17 | 直到找到要查找的数字,或者查找范围为空。
18 | """
19 | import timeit
20 | import random
21 |
22 | __author__ = '__L1n__w@tch'
23 |
24 |
25 | def python_style_solve(a_list, number_to_find):
26 | """
27 | 用 Python 的风格解决, 思路是把二维数组转换为一维数组, 然后执行查找
28 | :param a_list: 要查找的二维数组
29 | :param number_to_find: 待查找的数字
30 | :return: True or False
31 | """
32 | sum_list = list()
33 | for each in a_list:
34 | sum_list.extend(each)
35 | if number_to_find in sum_list:
36 | return True
37 | # print("Found!")
38 |
39 |
40 | def c_style_solve(a_list, rows, columns, number_to_find):
41 | """
42 | 用 C 的风格解决, 思路参考剑指 Offer
43 | :param a_list: 要查找的二维数组
44 | :param rows: 行
45 | :param columns: 列
46 | :param number_to_find: 待查找的数字
47 | :return: True or False
48 | """
49 | found = False
50 |
51 | if a_list is not None and rows > 0 and columns > 0:
52 | row, column = 0, columns - 1
53 | while row < rows and column >= 0:
54 | if a_list[row][column] == number_to_find:
55 | found = True
56 | break
57 | elif a_list[row][column] > number_to_find:
58 | column -= 1
59 | else:
60 | row += 1
61 | return found
62 |
63 |
64 | if __name__ == "__main__":
65 | python_time = list()
66 | c_time = list()
67 |
68 | for i in range(30):
69 | number = random.choice([i for i in range(9)])
70 | print("第 {} 次, 查找数字: {}".format(i + 1, number))
71 |
72 | test_list = [[i for i in range(3)], [i for i in range(3, 6)], [i for i in range(6, 9)]]
73 | time_cost = timeit.timeit("python_style_solve(test_list, {})".format(number),
74 | setup="from __main__ import python_style_solve, test_list")
75 | print("Python 风格执行时间: {} s".format(time_cost))
76 | python_time.append(time_cost)
77 |
78 | time_cost = timeit.timeit("c_style_solve(test_list, len(test_list), len(test_list[0]), {})".format(number),
79 | setup="from __main__ import c_style_solve, test_list")
80 | print("C 风格执行时间: {} s".format(time_cost))
81 | c_time.append(time_cost)
82 |
83 | print("Python 平均时间: {}, C 平均时间: {}".format(sum(python_time) / len(python_time), sum(c_time) / len(c_time)))
84 |
--------------------------------------------------------------------------------
/Python 面试编程题/4 杨氏矩阵查找/unittest_rectangle_search.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 对杨氏矩阵查找的几种解法进行单元测试
5 | """
6 | import unittest
7 | from rectangle_search import python_style_solve, c_style_solve
8 |
9 | __author__ = '__L1n__w@tch'
10 |
11 |
12 | class TestAnswer(unittest.TestCase):
13 | def setUp(self):
14 | self.repeat_list = [[1, 2, 8, 9], [2, 4, 9, 12], [4, 7, 10, 13], [6, 8, 11, 15]]
15 | self.no_repeat_list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20]]
16 |
17 | def test_normal(self):
18 | # 测试数字在其中的情况
19 | wait_to_search = [1, 9, 2, 12, 4, 13, 6, 15, 11, 8, 10, 7, 9, 4, 8, 2]
20 | print("二维数组: ".format(self.repeat_list))
21 | for each_number in wait_to_search:
22 | print("测试查找数字: {}".format(each_number))
23 | self.failUnless(python_style_solve(self.repeat_list, each_number))
24 | self.failUnless(
25 | c_style_solve(self.repeat_list, len(self.repeat_list), len(self.repeat_list[0]), each_number))
26 |
27 | # 测试数字不在其中的情况
28 | # self.failIf()
29 |
30 |
31 | if __name__ == "__main__":
32 | pass
33 |
--------------------------------------------------------------------------------
/Python 面试编程题/4 杨氏矩阵查找/杨氏矩阵查找.md:
--------------------------------------------------------------------------------
1 | # 题目
2 | 在一个 m 行 n 列二维数组中, 每一行都按照从左到右递增的顺序排序, 每一列都按照从上到下递增的顺序排序.请完成一个函数, 输入这样的一个二维数组和一个整数, 判断数组中是否含有该整数
3 |
4 | # 思路
5 | * 参考: 剑指 Offer (面试题 3)
6 | * 总结查找的过程,发现规律如下:
7 | * 首先选取数组中右上角的数字。如果该数字等于要查找的数字,查找过程结束;
8 | * 如果该数字大于要查找的数字,剔除这个数字所在的列;
9 | * 如果该数字小于要查找的数字,剔除这个数字所在的行。
10 | * 也就是说如果要查找的数字不在数组的右上角,则每一次都在数组的查找范围中剔除一行或者一列,这样每一步都可以缩小查找的范围,
11 | * 直到找到要查找的数字,或者查找范围为空。
12 |
13 | # rectangle_search.py
14 | ```Python
15 | #!/bin/env python3
16 | # -*- coding: utf-8 -*-
17 | # version: Python3.X
18 |
19 | import timeit
20 | import random
21 |
22 | __author__ = '__L1n__w@tch'
23 |
24 |
25 | def python_style_solve(a_list, number_to_find):
26 | """
27 | 用 Python 的风格解决, 思路是把二维数组转换为一维数组, 然后执行查找
28 | :param a_list: 要查找的二维数组
29 | :param number_to_find: 待查找的数字
30 | :return: True or False
31 | """
32 | sum_list = list()
33 | for each in a_list:
34 | sum_list.extend(each)
35 | if number_to_find in sum_list:
36 | return True
37 | # print("Found!")
38 |
39 |
40 | def c_style_solve(a_list, rows, columns, number_to_find):
41 | """
42 | 用 C 的风格解决, 思路参考剑指 Offer
43 | :param a_list: 要查找的二维数组
44 | :param rows: 行
45 | :param columns: 列
46 | :param number_to_find: 待查找的数字
47 | :return: True or False
48 | """
49 | found = False
50 |
51 | if a_list is not None and rows > 0 and columns > 0:
52 | row, column = 0, columns - 1
53 | while row < rows and column >= 0:
54 | if a_list[row][column] == number_to_find:
55 | found = True
56 | break
57 | elif a_list[row][column] > number_to_find:
58 | column -= 1
59 | else:
60 | row += 1
61 | return found
62 |
63 |
64 | if __name__ == "__main__":
65 | python_time = list()
66 | c_time = list()
67 |
68 | for i in range(30):
69 | number = random.choice([i for i in range(9)])
70 | print("第 {} 次, 查找数字: {}".format(i + 1, number))
71 |
72 | test_list = [[i for i in range(3)], [i for i in range(3, 6)], [i for i in range(6, 9)]]
73 | time_cost = timeit.timeit("python_style_solve(test_list, {})".format(number),
74 | setup="from __main__ import python_style_solve, test_list")
75 | print("Python 风格执行时间: {} s".format(time_cost))
76 | python_time.append(time_cost)
77 |
78 | time_cost = timeit.timeit("c_style_solve(test_list, len(test_list), len(test_list[0]), {})".format(number),
79 | setup="from __main__ import c_style_solve, test_list")
80 | print("C 风格执行时间: {} s".format(time_cost))
81 | c_time.append(time_cost)
82 |
83 | print("Python 平均时间: {}, C 平均时间: {}".format(sum(python_time) / len(python_time), sum(c_time) / len(c_time)))
84 | ```
85 |
86 | # 单元测试
87 | ```Python
88 | #!/bin/env python3
89 | # -*- coding: utf-8 -*-
90 | # version: Python3.X
91 | """ 对杨氏矩阵查找的几种解法进行单元测试
92 | """
93 | import unittest
94 | from rectangle_search import python_style_solve, c_style_solve
95 |
96 | __author__ = '__L1n__w@tch'
97 |
98 |
99 | class TestAnswer(unittest.TestCase):
100 | def setUp(self):
101 | self.repeat_list = [[1, 2, 8, 9], [2, 4, 9, 12], [4, 7, 10, 13], [6, 8, 11, 15]]
102 | self.no_repeat_list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20]]
103 |
104 | def test_normal(self):
105 | # 测试数字在其中的情况
106 | wait_to_search = [1, 9, 2, 12, 4, 13, 6, 15, 11, 8, 10, 7, 9, 4, 8, 2]
107 | print("二维数组: ".format(self.repeat_list))
108 | for each_number in wait_to_search:
109 | print("测试查找数字: {}".format(each_number))
110 | self.failUnless(python_style_solve(self.repeat_list, each_number))
111 | self.failUnless(
112 | c_style_solve(self.repeat_list, len(self.repeat_list), len(self.repeat_list[0]), each_number))
113 |
114 | # 测试数字不在其中的情况
115 | # self.failIf()
116 |
117 |
118 | if __name__ == "__main__":
119 | pass
120 | ```
--------------------------------------------------------------------------------
/Python 面试编程题/5 去除列表中的重复元素/delete_repeat.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 去除列表中重复元素的几种方法
5 | """
6 |
7 | __author__ = '__L1n__w@tch'
8 |
9 |
10 | def use_set(a_list):
11 | """
12 | 用集合去除重复元素
13 | :param a_list: [1,2,1,2]
14 | :return: [1,2]
15 | """
16 | return list(set(a_list))
17 |
18 |
19 | def use_dictionary(a_list):
20 | """
21 | 用字典去除重复元素
22 | :param a_list: [1,2,1,2]
23 | :return: [1,2]
24 | """
25 | a_dict = dict().fromkeys(a_list).keys()
26 | return list(a_dict)
27 |
28 |
29 | def use_dict_keep_order(a_list):
30 | """
31 | 用字典并保持顺序
32 | :param a_list: [1,2,1,2]
33 | :return: [1,2]
34 | """
35 | another_list = list(set(a_list))
36 | another_list.sort(key=a_list.index)
37 | return another_list
38 |
39 |
40 | def use_list_derive(a_list):
41 | """
42 | 列表推导式
43 | :param a_list: [1,2,1,2]
44 | :return: [1,2]
45 | """
46 | another_list = list()
47 | [another_list.append(i) for i in a_list if i not in another_list]
48 | return another_list
49 |
50 |
51 | if __name__ == "__main__":
52 | List = [1, 2, 1, 2, 3, 3, 3, 4, 1, 0, 9, 9, 3, 1111221231]
53 |
54 | print(use_set(List))
55 | print(use_dictionary(List))
56 | print(use_dict_keep_order(List))
57 | print(use_list_derive(List))
58 |
59 | if use_set(List) == use_dictionary(List) == use_dict_keep_order(List) == use_list_derive(List):
60 | print("OK")
61 |
--------------------------------------------------------------------------------
/Python 面试编程题/5 去除列表中的重复元素/去除列表中的重复元素.md:
--------------------------------------------------------------------------------
1 | # 题目
2 | 去除重复元素的几种方法, 包括
3 | * 用集合去除重复元素
4 | * 用字典去除重复元素
5 | * 用字典去除并保持顺序
6 | * 列表推导式
7 |
8 | # 解答
9 | ```Python
10 | #!/bin/env python3
11 | # -*- coding: utf-8 -*-
12 | # version: Python3.X
13 |
14 |
15 | __author__ = '__L1n__w@tch'
16 |
17 |
18 | def use_set(a_list):
19 | """
20 | 用集合去除重复元素
21 | :param a_list: [1,2,1,2]
22 | :return: [1,2]
23 | """
24 | return list(set(a_list))
25 |
26 |
27 | def use_dictionary(a_list):
28 | """
29 | 用字典去除重复元素
30 | :param a_list: [1,2,1,2]
31 | :return: [1,2]
32 | """
33 | a_dict = dict().fromkeys(a_list).keys()
34 | return list(a_dict)
35 |
36 |
37 | def use_dict_keep_order(a_list):
38 | """
39 | 用字典并保持顺序
40 | :param a_list: [1,2,1,2]
41 | :return: [1,2]
42 | """
43 | another_list = list(set(a_list))
44 | another_list.sort(key=a_list.index)
45 | return another_list
46 |
47 |
48 | def use_list_derive(a_list):
49 | """
50 | 列表推导式
51 | :param a_list: [1,2,1,2]
52 | :return: [1,2]
53 | """
54 | another_list = list()
55 | [another_list.append(i) for i in a_list if i not in another_list]
56 | return another_list
57 |
58 |
59 | if __name__ == "__main__":
60 | List = [1, 2, 1, 2, 3, 3, 3, 4, 1, 0, 9, 9, 3, 1111221231]
61 |
62 | print(use_set(List))
63 | print(use_dictionary(List))
64 | print(use_dict_keep_order(List))
65 | print(use_list_derive(List))
66 |
67 | if use_set(List) == use_dictionary(List) == use_dict_keep_order(List) == use_list_derive(List):
68 | print("OK")
69 | ```
--------------------------------------------------------------------------------
/Python 面试编程题/6 链表成对调换/swap_pairs_list_node.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 链表成对调换
5 |
6 | 1->2->3->4 转换成 2->1->4->3
7 |
8 | 参考 GitHub 给的思路, 其实挺好理解的
9 | """
10 |
11 | __author__ = '__L1n__w@tch'
12 |
13 |
14 | def swap_pairs(head_node):
15 | """
16 | 链表成对调换
17 | :param head_node:
18 | :return:
19 | """
20 | if head_node is not None and head_node.next is not None:
21 | next_node = head_node.next
22 | head_node.next = swap_pairs(next_node.next)
23 | next_node.next = head_node
24 | return next_node
25 | return head_node
26 |
27 |
28 | def print_list_node(head_node):
29 | """
30 | 顺序打印链表
31 | :param head_node: 头结点
32 | :return: None
33 | """
34 | for node in list_node:
35 | print("No.{} List Node, Next: {}".format(node.value, node.next.value if node.next is not None else None))
36 | print()
37 |
38 |
39 | class ListNode:
40 | def __init__(self, value, next_node=None):
41 | self.value = value
42 | self.next = next_node
43 |
44 |
45 | if __name__ == "__main__":
46 | list_node = list()
47 | for i in range(4, 0, -1):
48 | list_node.append(ListNode(i, list_node[-1] if len(list_node) > 0 else None))
49 | list_node = list(reversed(list_node))
50 |
51 | print_list_node(list_node[0])
52 |
53 | swap_pairs(list_node[0])
54 | print_list_node(list_node[0])
55 |
--------------------------------------------------------------------------------
/Python 面试编程题/6 链表成对调换/链表成对调换.md:
--------------------------------------------------------------------------------
1 | # 题目
2 | 链表成对调换
3 |
4 | `1->2->3->4` 转换成 `2->1->4->3`
5 |
6 | 通过递归实现
7 |
8 | # swap_pairs_list_node.py
9 | ```Python
10 | #!/bin/env python3
11 | # -*- coding: utf-8 -*-
12 | # version: Python3.X
13 |
14 |
15 | __author__ = '__L1n__w@tch'
16 |
17 |
18 | def swap_pairs(head_node):
19 | """
20 | 链表成对调换
21 | :param head_node:
22 | :return:
23 | """
24 | if head_node is not None and head_node.next is not None:
25 | next_node = head_node.next
26 | head_node.next = swap_pairs(next_node.next)
27 | next_node.next = head_node
28 | return next_node
29 | return head_node
30 |
31 |
32 | def print_list_node(head_node):
33 | """
34 | 顺序打印链表
35 | :param head_node: 头结点
36 | :return: None
37 | """
38 | for node in list_node:
39 | print("No.{} List Node, Next: {}".format(node.value, node.next.value if node.next is not None else None))
40 | print()
41 |
42 |
43 | class ListNode:
44 | def __init__(self, value, next_node=None):
45 | self.value = value
46 | self.next = next_node
47 |
48 |
49 | if __name__ == "__main__":
50 | list_node = list()
51 | for i in range(4, 0, -1):
52 | list_node.append(ListNode(i, list_node[-1] if len(list_node) > 0 else None))
53 | list_node = list(reversed(list_node))
54 |
55 | print_list_node(list_node[0])
56 |
57 | swap_pairs(list_node[0])
58 | print_list_node(list_node[0])
59 | ```
60 |
--------------------------------------------------------------------------------
/Python 面试编程题/7 创建字典的方法/create_dict.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 考怎么创建字典的?
5 | """
6 |
7 | __author__ = '__L1n__w@tch'
8 |
9 | if __name__ == "__main__":
10 | dictionary = {"key1": 1, "key2": 2}
11 |
12 | items = [("key1", 1), ("key2", 2)]
13 | dictionary_2 = dict(items)
14 |
15 | dictionary_3 = dict().fromkeys(("key1", "key2"), -1)
16 | dictionary_4 = dict().fromkeys(("key1", "key2"))
17 |
18 | print(dictionary, dictionary_2, dictionary_3, dictionary_4)
19 |
--------------------------------------------------------------------------------
/Python 面试编程题/7 创建字典的方法/创建字典的方法.md:
--------------------------------------------------------------------------------
1 | # 题目
2 | 考怎么创建字典的?包括:
3 | * 花括号创建
4 | * dict 内置类
5 | * dict().fromkeys 方法
6 |
7 | # create_dict.py
8 | ```Python
9 | #!/bin/env python3
10 | # -*- coding: utf-8 -*-
11 | # version: Python3.X
12 |
13 |
14 | __author__ = '__L1n__w@tch'
15 |
16 | if __name__ == "__main__":
17 | dictionary = {"key1": 1, "key2": 2}
18 |
19 | items = [("key1", 1), ("key2", 2)]
20 | dictionary_2 = dict(items)
21 |
22 | dictionary_3 = dict().fromkeys(("key1", "key2"), -1)
23 | dictionary_4 = dict().fromkeys(("key1", "key2"))
24 |
25 | print(dictionary, dictionary_2, dictionary_3, dictionary_4)
26 | ```
--------------------------------------------------------------------------------
/Python 面试编程题/8 合并两个有序列表/merge_sort.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 好像是考归并排序的两种实现方式, 一种递归一种循环
5 |
6 | 两种实现方式都是参考 GitHub 上的
7 | """
8 | __author__ = '__L1n__w@tch'
9 |
10 |
11 | def recursion_merge_sort(list1, list2, a_list):
12 | def __recursion(list_wait_to_sort_1, list_wait_to_sort_2, list_after_sort):
13 | if len(list_wait_to_sort_1) == 0 or len(list_wait_to_sort_2) == 0:
14 | list_after_sort.extend(list_wait_to_sort_1)
15 | list_after_sort.extend(list_wait_to_sort_2)
16 | return list_after_sort
17 | elif list_wait_to_sort_1[0] < list_wait_to_sort_2[0]:
18 | list_after_sort.append(list_wait_to_sort_1[0])
19 | del list_wait_to_sort_1[0] # 为啥不用 list1.pop(0)...
20 | elif list_wait_to_sort_1[0] >= list_wait_to_sort_2[0]:
21 | list_after_sort.append(list_wait_to_sort_2[0])
22 | del list_wait_to_sort_2[0]
23 | return __recursion(list_wait_to_sort_1, list_wait_to_sort_2, list_after_sort)
24 |
25 | return __recursion(list1, list2, list())
26 |
27 |
28 | def loop_merge_sort(list1, list2):
29 | after_sort = list()
30 | while len(list1) > 0 and len(list2) > 0:
31 | if list1[0] < list2[0]:
32 | after_sort.append(list1[0])
33 | del list1[0]
34 | else:
35 | after_sort.append(list2[0])
36 | del list2[0]
37 | after_sort.extend(list1)
38 | after_sort.extend(list2)
39 | return after_sort
40 |
41 |
42 | if __name__ == "__main__":
43 | List1 = sorted([3, 4, 1, 2])
44 | List2 = sorted([2, 1, 1, 1])
45 |
46 | test_list = recursion_merge_sort(List1[::1], List2[::1], list())
47 | print(test_list)
48 |
49 | test_list = loop_merge_sort(List1, List2)
50 | print(test_list)
51 |
--------------------------------------------------------------------------------
/Python 面试编程题/8 合并两个有序列表/unittest_merge_sort.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 测试归并排序是否正确
5 | """
6 | import random
7 | import unittest
8 | from merge_sort import recursion_merge_sort, loop_merge_sort
9 |
10 |
11 | __author__ = '__L1n__w@tch'
12 |
13 |
14 | class TestMergeSort(unittest.TestCase):
15 | def test(self):
16 | for i in range(5):
17 | wait_to_sort = sorted([random.randint(-1000, 1000) for i in range(100)])
18 | wait_to_sort_2 = sorted([random.randint(-1000, 1000) for i in range(100)])
19 |
20 | after_sort = sorted(wait_to_sort + wait_to_sort_2)
21 |
22 | self.failUnless(after_sort == recursion_merge_sort(wait_to_sort[::1], wait_to_sort_2[::1], list()))
23 | self.failUnless(after_sort == loop_merge_sort(wait_to_sort[::1], wait_to_sort_2[::1]))
24 |
25 |
26 | if __name__ == "__main__":
27 | pass
28 |
--------------------------------------------------------------------------------
/Python 面试编程题/8 合并两个有序列表/合并两个有序列表.md:
--------------------------------------------------------------------------------
1 | # 题目
2 | 考归并排序的两种实现方式, 一种递归一种循环
3 |
4 | # merge_sort.py
5 | ```Python
6 | #!/bin/env python3
7 | # -*- coding: utf-8 -*-
8 | # version: Python3.X
9 |
10 | __author__ = '__L1n__w@tch'
11 |
12 |
13 | def recursion_merge_sort(list1, list2, a_list):
14 | def __recursion(list_wait_to_sort_1, list_wait_to_sort_2, list_after_sort):
15 | if len(list_wait_to_sort_1) == 0 or len(list_wait_to_sort_2) == 0:
16 | list_after_sort.extend(list_wait_to_sort_1)
17 | list_after_sort.extend(list_wait_to_sort_2)
18 | return list_after_sort
19 | elif list_wait_to_sort_1[0] < list_wait_to_sort_2[0]:
20 | list_after_sort.append(list_wait_to_sort_1[0])
21 | del list_wait_to_sort_1[0] # 为啥不用 list1.pop(0)...
22 | elif list_wait_to_sort_1[0] >= list_wait_to_sort_2[0]:
23 | list_after_sort.append(list_wait_to_sort_2[0])
24 | del list_wait_to_sort_2[0]
25 | return __recursion(list_wait_to_sort_1, list_wait_to_sort_2, list_after_sort)
26 |
27 | return __recursion(list1, list2, list())
28 |
29 |
30 | def loop_merge_sort(list1, list2):
31 | after_sort = list()
32 | while len(list1) > 0 and len(list2) > 0:
33 | if list1[0] < list2[0]:
34 | after_sort.append(list1[0])
35 | del list1[0]
36 | else:
37 | after_sort.append(list2[0])
38 | del list2[0]
39 | after_sort.extend(list1)
40 | after_sort.extend(list2)
41 | return after_sort
42 |
43 |
44 | if __name__ == "__main__":
45 | List1 = sorted([3, 4, 1, 2])
46 | List2 = sorted([2, 1, 1, 1])
47 |
48 | test_list = recursion_merge_sort(List1[::1], List2[::1], list())
49 | print(test_list)
50 |
51 | test_list = loop_merge_sort(List1, List2)
52 | print(test_list)
53 | ```
54 |
55 | # 单元测试
56 | ```Python
57 | #!/bin/env python3
58 | # -*- coding: utf-8 -*-
59 | # version: Python3.X
60 | """ 测试归并排序是否正确
61 | """
62 | import random
63 | import unittest
64 | from merge_sort import recursion_merge_sort, loop_merge_sort
65 |
66 |
67 | __author__ = '__L1n__w@tch'
68 |
69 |
70 | class TestMergeSort(unittest.TestCase):
71 | def test(self):
72 | for i in range(5):
73 | wait_to_sort = sorted([random.randint(-1000, 1000) for i in range(100)])
74 | wait_to_sort_2 = sorted([random.randint(-1000, 1000) for i in range(100)])
75 |
76 | after_sort = sorted(wait_to_sort + wait_to_sort_2)
77 |
78 | self.failUnless(after_sort == recursion_merge_sort(wait_to_sort[::1], wait_to_sort_2[::1], list()))
79 | self.failUnless(after_sort == loop_merge_sort(wait_to_sort[::1], wait_to_sort_2[::1]))
80 |
81 |
82 | if __name__ == "__main__":
83 | pass
84 | ```
--------------------------------------------------------------------------------
/Python 面试编程题/9 二分查找/binary_search.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 考二分查找法的
5 | """
6 |
7 | __author__ = '__L1n__w@tch'
8 |
9 |
10 | def binary_search(a_list, number_to_find):
11 | """
12 | 二分查找法
13 | :param a_list: 待查找列表
14 | :param number_to_find: 待查找数字
15 | :return: int() or False
16 | """
17 | start, end = 0, len(a_list) - 1
18 | while start < end:
19 | middle = (start + end) // 2
20 | if a_list[middle] > number_to_find:
21 | end = middle
22 | elif a_list[middle] < number_to_find:
23 | start = middle + 1
24 | else:
25 | return middle
26 | return start if a_list[start] == number_to_find else False
27 |
28 |
29 | if __name__ == "__main__":
30 | List = [i for i in range(10)]
31 | print(binary_search(List, 2))
32 |
--------------------------------------------------------------------------------
/Python 面试编程题/9 二分查找/unittest_binary_search.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 单元测试二分查找
5 | """
6 | import random
7 | import unittest
8 | from binary_search import binary_search
9 |
10 |
11 | __author__ = '__L1n__w@tch'
12 |
13 |
14 | class TestBinarySearch(unittest.TestCase):
15 | def test(self):
16 | list_wait_to_search = sorted([random.randint(-1000, 1000) for i in range(100)])
17 | number_wait_to_search = list_wait_to_search[random.randint(0, 100)]
18 |
19 | self.failUnless(number_wait_to_search ==
20 | list_wait_to_search[binary_search(list_wait_to_search, number_wait_to_search)])
21 |
--------------------------------------------------------------------------------
/Python 面试编程题/9 二分查找/二分查找.md:
--------------------------------------------------------------------------------
1 | # 题目
2 | 考二分查找法的
3 |
4 | # binary_search.py
5 | ```Python
6 | #!/bin/env python3
7 | # -*- coding: utf-8 -*-
8 | # version: Python3.X
9 |
10 |
11 | __author__ = '__L1n__w@tch'
12 |
13 |
14 | def binary_search(a_list, number_to_find):
15 | """
16 | 二分查找法
17 | :param a_list: 待查找列表
18 | :param number_to_find: 待查找数字
19 | :return: int() or False
20 | """
21 | start, end = 0, len(a_list) - 1
22 | while start < end:
23 | middle = (start + end) // 2
24 | if a_list[middle] > number_to_find:
25 | end = middle
26 | elif a_list[middle] < number_to_find:
27 | start = middle + 1
28 | else:
29 | return middle
30 | return start if a_list[start] == number_to_find else False
31 |
32 |
33 | if __name__ == "__main__":
34 | List = [i for i in range(10)]
35 | print(binary_search(List, 2))
36 | ```
37 |
38 | # 单元测试
39 | ```Python
40 | #!/bin/env python3
41 | # -*- coding: utf-8 -*-
42 | # version: Python3.X
43 | """ 单元测试二分查找
44 | """
45 | import random
46 | import unittest
47 | from binary_search import binary_search
48 |
49 |
50 | __author__ = '__L1n__w@tch'
51 |
52 |
53 | class TestBinarySearch(unittest.TestCase):
54 | def test(self):
55 | list_wait_to_search = sorted([random.randint(-1000, 1000) for i in range(100)])
56 | number_wait_to_search = list_wait_to_search[random.randint(0, 100)]
57 |
58 | self.failUnless(number_wait_to_search ==
59 | list_wait_to_search[binary_search(list_wait_to_search, number_wait_to_search)])
60 | ```
--------------------------------------------------------------------------------
/Python 面试编程题/readme.md:
--------------------------------------------------------------------------------
1 | # Python 面试编程题
2 | 这一节主要就是编程题部分。
3 | ## 参考资料
4 | [interview_python](https://github.com/taizilongxu/interview_python#1-%E5%8F%B0%E9%98%B6%E9%97%AE%E9%A2%98%E6%96%90%E6%B3%A2%E7%BA%B3%E6%8C%88)
5 | ## 清单
6 | 1. 台阶问题/斐波那契
7 | 2. 变态台阶问题
8 | 3. 矩形覆盖
9 | 4. 杨氏矩阵查找
10 | 5. 去除列表中的重复元素
11 | 6. 链表成对调换
12 | 7. 创建字典的方法
13 | 8. 合并两个有序列表
14 | 9. 二分查找
15 | 10. 快排
16 | 11. 找零问题
17 | 12. 二叉树相关
18 | 13. 单链表逆置
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Python && C/C++ 面试
2 |
3 | 整理自己准备 Python && C/C++ 面试时的相关资料
4 |
5 | [GitBook 链接](https://l1nwatch.gitbooks.io/interview_exercise/content/)
6 |
7 | 【PS: 突然发现 Python Cookbook 很适合拿来当考题, 以后我要是面试别人就用这个出题, ✧(≖ ◡ ≖✿)嘿嘿】[Python CookBook](http://python3-cookbook.readthedocs.io/zh_CN/latest/index.html)
8 |
9 | # 资料来源
10 |
11 | * [牛客网](http://www.nowcoder.com/7651698)
12 | * [GitHub Python 面试题](https://github.com/taizilongxu/interview_python)
13 | * [GitHub stackoverflow-about-Python](https://taizilongxu.gitbooks.io/stackoverflow-about-python/content/)
14 | * [Python CookBook](http://python3-cookbook.readthedocs.io/zh_CN/latest/index.html)
15 | * sangfor
--------------------------------------------------------------------------------
/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | * [说明](README.md)
4 | * [C/C++ 问答题汇总](C_问答题汇总.md)
5 | * [编程题汇总](编程题汇总.md)
6 | * [腾讯 2017 暑期实习生编程题](腾讯 2017 暑期实习生编程题/腾讯 2017 暑期实习生编程题.md)
7 | * [构造回文](腾讯 2017 暑期实习生编程题/构造回文.md)
8 | * [算法基础-字符移位](腾讯 2017 暑期实习生编程题/算法基础-字符移位.md)
9 | * [有趣的数字](腾讯 2017 暑期实习生编程题/有趣的数字.md)
10 | * [剑指 Offer 编程题练习](剑指 Offer 编程题/readme.md)
11 | * [二维数组中的查找](剑指 Offer 编程题/二维数组中的查找/readme.md)
12 | * [从尾到头打印链表](剑指 Offer 编程题/从尾到头打印链表/readme.md)
13 | * [旋转数组的最小数字](剑指 Offer 编程题/旋转数组的最小数字/readme.md)
14 | * [替换空格](剑指 Offer 编程题/替换空格/readme.md)
15 | * [用两个栈实现队列](剑指 Offer 编程题/用两个栈实现队列/readme.md)
16 | * [重建二叉树](剑指 Offer 编程题/重建二叉树/readme.md)
17 | * [网易 2017 校招笔试编程题](网易 2017 校招笔试编程题/readme.md)
18 | * [二进制权重](网易 2017 校招笔试编程题/二进制权重.md)
19 | * [平方串](网易 2017 校招笔试编程题/平方串.md)
20 | * [数位和](网易 2017 校招笔试编程题/数位和.md)
21 | * [安全测试开发相关面试](安全测试开发相关面试/readme.md)
22 | * [安全测试类面试参考](安全测试开发相关面试/安全测试类面试参考/readme.md)
23 | * [业务安全类面试参考](安全测试开发相关面试/业务安全类面试参考/readme.md)
24 | * [测试开发类面试参考](安全测试开发相关面试/测试开发类面试参考/readme.md)
25 | * [深信服_sangfor_相关](深信服_sangfor_相关/readme.md)
26 | * [深信服acm相关](深信服_sangfor_相关/sangfor_acm_oj/readme.md)
27 | * [测试类面试参考](深信服_sangfor_相关/测试类面试参考.md)
28 | * [智安全杯](深信服_sangfor_相关/智安全杯/readme.md)
29 | * [智安全杯-2018比赛](深信服_sangfor_相关/智安全杯/2018比赛.md)
30 | * [智安全杯-2019初赛](深信服_sangfor_相关/智安全杯/2019初赛.md)
31 | * [智安全杯-2019复赛](深信服_sangfor_相关/智安全杯/2019复赛.md)
32 | * [软件测试题汇总](软件测试题/题目汇总.md)
33 | * [计算机知识题汇总](计算机知识/readme.md)
34 | * [前 75 题](计算机知识/readme1.md)
35 | * [75 题以后](计算机知识/readme2.md)
36 | * [Python 语言特性](Python 语言特性/readme.md)
37 | * [1 Python的函数参数传递](Python 语言特性/1 Python的函数参数传递.md)
38 | * [2 @staticmethod和@classmethod](Python 语言特性/2 @staticmethod和@classmethod.md)
39 | * [3 类变量和实例变量](Python 语言特性/3 类变量和实例变量.md)
40 | * [4 Python中单下划线和双下划线](Python 语言特性/4 Python中单下划线和双下划线.md)
41 | * [5 *args and **kwargs](Python 语言特性/5 args and kwargs.md)
42 | * [6 面向切面编程AOP和装饰器](Python 语言特性/6 面向切面编程AOP和装饰器.md)
43 | * [7 单例模式](Python 语言特性/7 单例模式.md)
44 | * [8 Python 函数式编程](Python 语言特性/8 Python 函数式编程.md)
45 | * [9 Python 里的拷贝](Python 语言特性/9 Python 里的拷贝.md)
46 | * [stackoverflow-about-Python](stackoverflow-about-Python/readme.md)
47 | * [Python中关键字yield有什么作用?](stackoverflow-about-Python/Python中关键字yield有什么作用.md)
48 | * [Python中的元类(metaclass)是什么?](stackoverflow-about-Python/Python中的元类(metaclass)是什么.md)
49 | * [Python中如何在一个函数中加入多个装饰器?](stackoverflow-about-Python/Python中如何在一个函数中加入多个装饰器.md)
50 | * [如何判断一个文件是否存在?](stackoverflow-about-Python/如何判断一个文件是否存在.md)
51 | * [如何调用外部命令?](stackoverflow-about-Python/如何调用外部命令.md)
52 | * [枚举类型的使用?](stackoverflow-about-Python/枚举类型的使用.md)
53 | * [在Windows下安装pip?](stackoverflow-about-Python/在Windows下安装pip.md)
54 | * [字典合并问题](stackoverflow-about-Python/字典合并问题.md)
55 | * [在Android上运行Python](stackoverflow-about-Python/在Android上运行Python.md)
56 | * [根据字典值进行排序](stackoverflow-about-Python/根据字典值进行排序.md)
57 | * [在函数里使用全局变量](stackoverflow-about-Python/在函数里使用全局变量.md)
58 | * [变化的默认参数](stackoverflow-about-Python/变化的默认参数.md)
59 | * [装饰器classmethod和staticmethod的区别](stackoverflow-about-Python/装饰器classmethod和staticmethod的区别.md)
60 | * [检查列表为空的最好办法](stackoverflow-about-Python/检查列表为空的最好办法.md)
61 | * [怎么用引用来改变一个变量](stackoverflow-about-Python/怎么用引用来改变一个变量.md)
62 | * [检查文件夹是否存在的操作](stackoverflow-about-Python/检查文件夹是否存在的操作.md)
63 | * [name=main的作用](stackoverflow-about-Python/name=main的作用.md)
64 | * [super与init方法](stackoverflow-about-Python/super与init方法.md)
65 | * [str与repr的区别](stackoverflow-about-Python/str与repr的区别.md)
66 | * [循环中获取索引](stackoverflow-about-Python/循环中获取索引.md)
67 | * [类里的静态变量](stackoverflow-about-Python/类里的静态变量.md)
68 | * [怎么在终端里输出颜色?](stackoverflow-about-Python/怎么在终端里输出颜色.md)
69 | * [为什么用pip比用easy_install的好?](stackoverflow-about-Python/为什么用pip比用easy_install的好.md)
70 | * [join的问题](stackoverflow-about-Python/join的问题.md)
71 | * [把列表分割成同样大小的块](stackoverflow-about-Python/把列表分割成同样大小的块.md)
72 | * [为什么代码在一个函数里运行的更快](stackoverflow-about-Python/为什么代码在一个函数里运行的更快.md)
73 | * [如何快速合并列表中的列表?](stackoverflow-about-Python/快速合并列表中的列表.md)
74 | * [如何知道一个对象有一个特定的属性?](stackoverflow-about-Python/如何知道一个对象有一个特定的属性.md)
75 | * [如何通过函数名的字符串来调用这个函数?](stackoverflow-about-Python/如何通过函数名的字符串来调用函数.md)
76 | * [单下划线和双下划线的含义?](stackoverflow-about-Python/单下划线和双下划线的含义.md)
77 | * [Python 面试编程题](Python 面试编程题/readme.md)
78 | * [1 台阶问题 斐波那契](Python 面试编程题/1 台阶问题 斐波那契/斐波那契.md)
79 | * [2 变态台阶问题](Python 面试编程题/2 变态台阶问题/变态台阶问题.md)
80 | * [3 矩形覆盖](Python 面试编程题/3 矩形覆盖/矩阵覆盖.md)
81 | * [4 杨氏矩阵查找](Python 面试编程题/4 杨氏矩阵查找/杨氏矩阵查找.md)
82 | * [5 去除列表中的重复元素](Python 面试编程题/5 去除列表中的重复元素/去除列表中的重复元素.md)
83 | * [6 链表成对调换](Python 面试编程题/6 链表成对调换/链表成对调换.md)
84 | * [7 创建字典的方法](Python 面试编程题/7 创建字典的方法/创建字典的方法.md)
85 | * [8 合并两个有序列表](Python 面试编程题/8 合并两个有序列表/合并两个有序列表.md)
86 | * [9 二分查找](Python 面试编程题/9 二分查找/二分查找.md)
87 | * [10 快排](Python 面试编程题/10 快排/快排.md)
88 | * [11 找零问题](Python 面试编程题/11 找零问题/找零问题.md)
89 | * [12 二叉树相关](Python 面试编程题/12 二叉树相关/二叉树相关.md)
90 | * [13 单链表逆置](Python 面试编程题/13 单链表逆置/单链表逆置.md)
--------------------------------------------------------------------------------
/python_script/check_summary.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """
5 | 2017.03.10 使用博客搜索本仓库下某个文件夹的笔记才发现, 存在 summary.md 与路径对应不上的问题, 于是编写脚本来检查
6 | """
7 | import os
8 | import re
9 |
10 | __author__ = '__L1n__w@tch'
11 |
12 |
13 | class Checker:
14 | def run(self, summary_md_file_path, root_path):
15 | """
16 | 进行所有检查
17 | :param summary_md_file_path: str(), 比如 "SUMMARY.md", 表示 SUMMARY.md 的路径
18 | :param root_path: str(), 比如 "/Users/.../interview_collect", 表示所有 md 文件的根路径
19 | :return: None
20 | """
21 | # 打开 summary.md, 加载所有目录对应的路径
22 | path_list = self.get_all_path_in_summary_md_file(summary_md_file_path)
23 |
24 | # 遍历每个路径, 看对应的文件是否存在
25 | for each_path in path_list:
26 | if not os.path.exists(os.path.join(root_path, each_path)):
27 | print("[-] Error: 路径 {} 不存在".format(each_path))
28 |
29 | @staticmethod
30 | def get_all_path_in_summary_md_file(md_file_path):
31 | """
32 | 通过读取 summary.md 提取出所有要进行判定的路径
33 | :param md_file_path: str(), 比如 "SUMMARY.md", 指定 SUMMARY.md 的路径
34 | :return: list(), 比如 ["README.md", "腾讯 2017 暑期实习生编程题/腾讯 2017 暑期实习生编程题.md", ...]
35 | """
36 | result_list = list()
37 | title_re = re.compile("\[.*\]\((.*)\)")
38 |
39 | with open(md_file_path, "r",encoding="utf8") as f:
40 | for each_line in f:
41 | re_result = title_re.findall(each_line)
42 | if re_result:
43 | result_list.append(re_result[0])
44 |
45 | return result_list
46 |
47 |
48 | if __name__ == "__main__":
49 | base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
50 | summary_path = os.path.join(base_dir, "SUMMARY.md")
51 |
52 | check = Checker()
53 | check.run(summary_path, base_dir)
54 |
--------------------------------------------------------------------------------
/python_script/readme.md:
--------------------------------------------------------------------------------
1 | ## 文件夹说明
2 |
3 | 这个文件夹存放一些 Python 脚本, 用于辅助本仓库的维护等工作
4 |
5 | ### 清单
6 |
7 | * `search_keyword`: 实现对本仓库内容进行搜索的脚本
8 |
9 | * `check_summary`: 检查 `summary.md` 中的路径信息是否跟文件夹中的路径信息相对应
--------------------------------------------------------------------------------
/python_script/search_keyword.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """ 实现对指定文件夹下所有文件进行内容搜索, 关键词及搜索的文件类型由用户指定
5 |
6 | 2016.07.23 由于自己现在记的笔记形式是 GitHub + GitBook, 但是这两货的笔记搜索功能是在有限, 故需要将此程序进一步扩展
7 | 2016.06.21 由于微机原理也要进行 ARM 平台小车的开发, 遇到了跟 ZigBee 一样的困境, 需要快速掌握工程文件, 所以还是将这个程序通用化吧
8 | 2016.04 起初编写这个程序是由于对协议栈不熟悉, 所以需要对协议栈的每一个文件进行关键词搜索, 同时列举出来
9 | """
10 | import os
11 | import argparse
12 |
13 | __author__ = '__L1n__w@tch'
14 |
15 |
16 | def is_valid_file_type(name, types):
17 | """
18 | :param name: 文件名, 比如 '.DS_Store'
19 | :param types: 要搜寻的文件类型, 比如 [".h", ".c"]
20 | :return: False
21 | """
22 | name = name.lower()
23 | for each_type in types:
24 | if name.endswith(each_type):
25 | return True
26 | return False
27 |
28 |
29 | def add_argument(parser):
30 | """
31 | 为解析器添加参数
32 | :param parser: ArgumentParser 实例对象
33 | :return: None
34 | """
35 | parser.add_argument("--path", "-p", type=str,
36 | default=os.curdir, help="文件夹路径")
37 | parser.add_argument("--type", "-t", type=str, default=".c#.h#.cpp#.py#.md",
38 | help="搜索文件类型, 默认值及格式为: \".c#.h#.cpp#.py#.md\"")
39 | parser.add_argument("--keyword", "-k", type=str, default="main", help="要搜索的关键词")
40 |
41 |
42 | def set_argument(options):
43 | """
44 | 读取用户输入的参数, 检验是否合法
45 | :param options: parser.opts
46 | :return: dict()
47 | """
48 | configuration = dict()
49 | configuration["path"] = options.path
50 | configuration["file_type"] = options.type.split("#")
51 | # configuration["keyword"] = options.keyword.lower()
52 |
53 | print("[*] 要搜索的路径为: {}".format(configuration["path"]))
54 | print("[*] 要搜索的文件类型包括: {}".format(configuration["file_type"]))
55 | # print("[*] 要搜索的关键词为: {}".format(configuration["keyword"]))
56 |
57 | return configuration
58 |
59 |
60 | def initialize():
61 | """
62 | 进行初始化操作, 包括 argparse 解析程序的初始化, 参数的相关设定等
63 | :return: path, file_type, keyword
64 | """
65 | parser = argparse.ArgumentParser(description="文件内容搜索程序")
66 | add_argument(parser)
67 | configuration = set_argument(parser.parse_args())
68 |
69 | print("[*] {} 搜索开始 {}".format("-" * 30, "-" * 30))
70 |
71 | return configuration["path"], configuration["file_type"]
72 |
73 |
74 | def search_keyword_infile(file_path, word):
75 | """
76 | 判断一个文件内是否含有该关键词, 并且把含有该关键词的那一行返回回去
77 | :param file_path: 文件路径, 比如 './compare_key.py'
78 | :param word: "main"
79 | :return: 返回含有关键词的那一行, 或者返回 None 表示找不到, 即 None or "int main()"
80 | """
81 | # word 处理
82 | word = word.lower()
83 | word = word.encode("utf8")
84 |
85 | with open(path, "rb") as f:
86 | data = f.readlines()
87 |
88 | for each_line in data:
89 | if word in each_line.lower():
90 | return each_line
91 | return None
92 |
93 |
94 | if __name__ == "__main__":
95 | path, file_type = initialize()
96 | keyword = input("[?] 请输入要搜索的关键词: ")
97 |
98 | for root, dirs, files in os.walk(path):
99 | for each_file in files:
100 | if is_valid_file_type(each_file, file_type):
101 | path = root + os.sep + each_file
102 | line_content = search_keyword_infile(path, keyword)
103 | if line_content:
104 | print("[*] Found in \"{}\", path is \033[95m{}\033[0m".format(each_file, path))
105 | print("[*] {}\033[91m{}\033[0m".format("\t" * 4, line_content.decode("utf8").strip()))
106 | print("[*] {} 搜索结束 {}".format("-" * 30, "-" * 30))
107 |
--------------------------------------------------------------------------------
/python_script/test_check_summary.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """
5 | 2017.03.10 作为 check_summary 的测试文件, 具体实现参考博客源码
6 | """
7 | import unittest
8 | import os
9 | from check_summary import Checker
10 |
11 | __author__ = '__L1n__w@tch'
12 |
13 |
14 | class Tester(unittest.TestCase):
15 | def setUp(self):
16 | self.base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 | self.test_check = Checker()
18 |
19 | def test_get_title_list_from_summary(self):
20 | """
21 | 测试函数是否获取正确
22 | """
23 | summary_path = os.path.join(self.base_dir, "SUMMARY.md")
24 | title_list = self.test_check.get_all_path_in_summary_md_file(summary_path)
25 |
26 | self.assertIn("README.md", title_list)
27 | self.assertIn("腾讯 2017 暑期实习生编程题/腾讯 2017 暑期实习生编程题.md", title_list)
28 | self.assertIn("软件测试题/题目汇总.md", title_list)
29 | self.assertIn("Python 语言特性/3 类变量和实例变量.md", title_list)
30 | self.assertIn("Python 面试编程题/13 单链表逆置/单链表逆置.md", title_list)
31 |
32 |
33 | if __name__ == "__main__":
34 | pass
35 |
--------------------------------------------------------------------------------
/stackoverflow-about-Python/Python中关键字yield有什么作用.md:
--------------------------------------------------------------------------------
1 | ## Python中关键字yield有什么作用?
2 |
3 | 为了理解 yield 有什么用,首先得理解 generators,再之前还要理解 iterables
4 |
5 | ### Iterables
6 |
7 | 可迭代的,比如创建了一个列表,可以一个一个读取它的每一项,这就叫迭代(iteration):
8 |
9 | ```python
10 | >>> mylist = [1, 2, 3]
11 | >>> for i in mylist:
12 | ... print(i)
13 | 1
14 | 2
15 | 3
16 | ```
17 |
18 | 可以用在 `for...in...` 语句中的都是可迭代的,但是必须把它们的值放到内存里,当它们有很多值时就会消耗太多的内存
19 |
20 | ### Generators
21 |
22 | 生成器,也是迭代器的一种,但是只能迭代一次,因为它们不是全部存在内存里,只在要调用的时候在内存里生成:
23 |
24 | ```python
25 | >>> mygenerator = (x*x for x in range(3))
26 | >>> for i in mygenerator:
27 | ... print(i)
28 | 0
29 | 1
30 | 4
31 | ```
32 |
33 | 生成器和迭代器的区别就是用 `()` 代替 `[]`,还有不能用 `for i in mygenerator` 第二次调用生成器,因为每计算完一个值就会丢弃一个值
34 |
35 | ### Yield
36 |
37 | `yield` 用法和 `return` 差不多,下面的函数将会返回一个生成器:
38 |
39 | ```python
40 | >>> def createGenerator():
41 | ... mylist = range(3)
42 | ... for i in mylist:
43 | ... yield i*i
44 | ...
45 | >>> mygenerator = createGenerator() # 创建生成器
46 | >>> print(mygenerator) # mygenerator is an object!
47 |
48 | >>> for i in mygenerator:
49 | ... print(i)
50 | 0
51 | 1
52 | 4
53 | ```
54 |
55 | 如果函数要返回一个非常大的集合,而你只需要读取一次的话,用这个就很合适了。
56 |
57 | 这里当你调用函数时,函数里的代码并没有运行,仅仅返回生成器对象。每当 for 语句迭代生成器的时候代码才会运转。
58 |
59 | 当 `for` 语句第一次调用函数里的生成器对象,函数里的代码就开始运作,直到碰到 `yield`,然后会返回本次循环的第一个返回值。所以下一次调用也将运行一次循环然后返回下一个值,直到没有值可以返回。一旦函数运行没有喷到 yield 语句就认为生成器已经为空了
60 |
61 | ### 生成器的高级用法:控制迭代器的穷尽
62 |
63 | 生成器对于一些不断变化的值很有用,比如控制资源的访问:
64 |
65 | ```python
66 | >>> class Bank(): # 让我们建个银行,生产许多ATM
67 | ... crisis = False
68 | ... def create_atm(self):
69 | ... while not self.crisis:
70 | ... yield "$100"
71 | >>> hsbc = Bank() # 当一切就绪了你想要多少ATM就给你多少
72 | >>> corner_street_atm = hsbc.create_atm()
73 | >>> print([corner_street_atm.next() for cash in range(5)])
74 | ['$100', '$100', '$100', '$100', '$100']
75 | >>> hsbc.crisis = True # 经济危机来了没有钱了!
76 | >>> print(corner_street_atm.next())
77 |
78 | >>> wall_street_atm = hsbc.create_atm() # 对于其他ATM,它还是True
79 | >>> print(wall_street_atm.next())
80 |
81 | >>> hsbc.crisis = False # 麻烦的是,尽管危机过去了,ATM还是空的
82 | >>> print(corner_street_atm.next())
83 |
84 | >>> brand_new_atm = hsbc.create_atm() # 只能重新新建一个bank了
85 | >>> for cash in brand_new_atm:
86 | ... print cash
87 | $100
88 | $100
89 | ```
90 |
91 | ### Itertools 模块
92 |
93 | 该模块包含了一些特殊的函数可以操作可迭代对象,比如复制生成器,链接两个生成器等
94 |
95 | ```python
96 | >>> horses = [1, 2, 3, 4]
97 | >>> races = itertools.permutations(horses)
98 | >>> print(races)
99 | >>> print(list(itertools.permutations(horses)))
100 | [(1, 2, 3, 4),
101 | (1, 2, 4, 3),
102 | (1, 3, 2, 4),
103 | (1, 3, 4, 2),
104 | (1, 4, 2, 3),
105 | ....
106 | ]
107 | ```
108 |
109 | ### 理解迭代的内部机制
110 |
111 | 迭代是可迭代对象(对应 `__iter__()` 方法)和迭代器(对应 `__next__()` 方法)的一个过程。
--------------------------------------------------------------------------------
/stackoverflow-about-Python/join的问题.md:
--------------------------------------------------------------------------------
1 | ## join的问题
2 |
3 | 为什么是 `string.join(list)` 而不是 `list.join(string)`?
4 |
5 | 比如:
6 |
7 | ```python
8 | my_list = ["Hello", "world"]
9 | print(my_list.join("-"))
10 | # Produce: "Hello-world"
11 | ```
12 |
13 | 其实因为所有的可迭代对象都能被 `join`,不仅仅是列表,但一般情况下我们要 `join` 的都是字符串
14 |
15 | 比如:
16 |
17 | ```python
18 | import urllib2
19 | print '\n############\n'.join(urllib2.urlopen('http://data.stackexchange.com/users/7095'))
20 | ```
21 |
22 |
--------------------------------------------------------------------------------
/stackoverflow-about-Python/name=main的作用.md:
--------------------------------------------------------------------------------
1 | ## name=main的作用
2 |
3 | 当 Python 解析器读取一个源文件时,它会执行所有的代码。在执行代码前,会定义一些特殊的变量。如果解析器运行的模块(源文件)作为主程序,它会把 `__name__` 变量设置成 `__main__`,如果只是引入其他的模块,`__name__` 变量将会设置成模块的名字
4 |
5 | 这么做的原因是有时你需要你写的模块既可以直接执行,还可以被当做模块导入到其他模块中去。通过检查是不是主函数,可以让你的代码只在它作为主程序运行时执行,而当其他人调用你的模块中的函数时不必执行
6 |
7 | 更多详情可以查看该[网址](http://ibiblio.org/g2swap/byteofpython/read/module-name.html)
--------------------------------------------------------------------------------
/stackoverflow-about-Python/readme.md:
--------------------------------------------------------------------------------
1 | ## 说明
2 |
3 | 记录一下学习 pdf: stackoverflow-about-Python 的笔记
4 |
5 | 资料链接: [https://taizilongxu.gitbooks.io/stackoverflow-about-python/content/](https://taizilongxu.gitbooks.io/stackoverflow-about-python/content/)
--------------------------------------------------------------------------------
/stackoverflow-about-Python/str与repr的区别.md:
--------------------------------------------------------------------------------
1 | ## str与repr的区别
2 |
3 | 有一点是可以肯定的:如果 `__repr__` 被定义而 `__str__` 没有,那么对象会自动设置 `__str__ = __repr__`
4 |
5 | 这意味着,几乎所有的对象你需要实现 `__repr__` 以便使用者更好地理解这个对象。然而实现 `__str__` 只是为了一个更漂亮的输出
6 |
7 | 实现 `__repr__` 是为了明确
8 |
9 | 实现 `__str__` 是为了可读性
10 |
11 |
--------------------------------------------------------------------------------
/stackoverflow-about-Python/super与init方法.md:
--------------------------------------------------------------------------------
1 | ## super与init方法
2 |
3 | `super()` 的好处是可以避免直接使用父类的名字,主要用于多重继承。
4 |
5 | 注意在 Python3 里面语法有所改变,可以用 `super().__init___()` 代替 `super(ChildB, self).__init__()`
6 |
7 | DEMO:
8 |
9 | ```python
10 | class Base(object):
11 | def __init__(self):
12 | print "Base created"
13 |
14 | class ChildA(Base):
15 | def __init__(self):
16 | Base.__init__(self)
17 |
18 | class ChildB(Base):
19 | def __init__(self):
20 | super(ChildB, self).__init__()
21 |
22 | class ChildC(Base):
23 | def __init__(self):
24 | super().__init__()
25 |
26 | print ChildA(), ChildB(), ChildC()
27 | ```
28 |
29 |
--------------------------------------------------------------------------------
/stackoverflow-about-Python/为什么代码在一个函数里运行的更快.md:
--------------------------------------------------------------------------------
1 | ## 为什么代码在一个函数里运行的更快?
2 |
3 | 比如同样的一段代码,放在函数里:
4 |
5 | ```python
6 | def main():
7 | for i in xrange(10**8):
8 | pass
9 | main()
10 | ```
11 |
12 | 运行时间:
13 |
14 | ```shell
15 | real 0m1.841s
16 | user 0m1.828s
17 | sys 0m0.012s
18 | ```
19 |
20 | 不放在函数里:
21 |
22 | ```python
23 | for i in xrange(10**8):
24 | pass
25 | ```
26 |
27 | 运行时间:
28 |
29 | ```shell
30 | real 0m4.543s
31 | user 0m4.524s
32 | sys 0m0.012s
33 | ```
34 |
35 | ### 解答
36 |
37 | 这是因为存取一个本地变量比全局变量要快,这有关 CPython 的实现细节。
38 |
39 | 记住 CPython 解析器运行的是被编译过的字节编码(bytecode)。当一个函数被编译后,局部变量被存储在了固定大小的数组(不是一个 dict),而变量名赋值给了索引。于是你不能动态地为一个函数添加局部变量,检查一个局部变量就好像是一个指针去查找列表,对于在 PyObject 上的引用计数增长是微不足道的
40 |
41 | 在查找全局变量(`LOAD_GLOBAL`)时,涉及到一个实实在在的 dict 的哈希查找。同时,这也是你想要一个全局变量时需要加上 `global i` 的原因:如果你在一个区域内指定变量,编译器就会建立一个 `STORE_FAST` 的入口,除非你不让它这么做。
42 |
43 | 全局查找速度其实也不慢,真正拖慢速度的是像 `foo.bar` 这样的属性查找
44 |
45 | ***
46 |
47 | 对比函数和全局的字节码:
48 |
49 | ```python
50 | # 函数
51 | 2 0 SETUP_LOOP 20 (to 23)
52 | 3 LOAD_GLOBAL 0 (xrange)
53 | 6 LOAD_CONST 3 (100000000)
54 | 9 CALL_FUNCTION 1
55 | 12 GET_ITER
56 | >> 13 FOR_ITER 6 (to 22)
57 | 16 STORE_FAST 0 (i)
58 |
59 | 3 19 JUMP_ABSOLUTE 13
60 | >> 22 POP_BLOCK
61 | >> 23 LOAD_CONST 0 (None)
62 | 26 RETURN_VALUE
63 | # 全局
64 | 1 0 SETUP_LOOP 20 (to 23)
65 | 3 LOAD_NAME 0 (xrange)
66 | 6 LOAD_CONST 3 (100000000)
67 | 9 CALL_FUNCTION 1
68 | 12 GET_ITER
69 | >> 13 FOR_ITER 6 (to 22)
70 | 16 STORE_NAME 1 (i)
71 |
72 | 2 19 JUMP_ABSOLUTE 13
73 | >> 22 POP_BLOCK
74 | >> 23 LOAD_CONST 2 (None)
75 | 26 RETURN_VALUE
76 | ```
77 |
78 | 区别在于 `STORE_FAST` 比 `STORE_NAME` 要快很多。这是因为在函数里 `i` 是一个局部变量而在全局区域它是一个全局变量
79 |
80 | 用 `dis` 模块可以看字节编码,可以直接解析函数。但是要解析全局代码必须用 `compile` 内建模块
--------------------------------------------------------------------------------
/stackoverflow-about-Python/为什么用pip比用easy_install的好.md:
--------------------------------------------------------------------------------
1 | ## 为什么用pip比用easy_install的好?
2 |
3 | `pip` 是对 `easy_install` 以下方面进行了改进:
4 |
5 | * 所有的包是在安装之前就下载了,所以不会出现只安装了一部分的情况
6 | * 在终端上的输出更加友好
7 | * 对于动作的原因会进行持续的跟踪
8 | * 错误信息会非常有用
9 | * 代码简洁精悍可以很好地编程
10 | * 不必作为 egg 存档,能扁平化安装(仍然保存 egg 元数据)
11 | * 原生的支持其他版本控制系统(Git、Mercurial、Bazaar)
12 | * 卸载包
13 | * 可以简单地定义修改一系列的安装依赖等
--------------------------------------------------------------------------------
/stackoverflow-about-Python/单下划线和双下划线的含义.md:
--------------------------------------------------------------------------------
1 | ## 单下划线和双下划线的含义?
2 |
3 | ### 单下划线
4 |
5 | 在一个类中的方法或属性,用单下划线开头,就是告诉别的程序这个属性或方法是私有的。
6 |
7 | 引自 PEP-8:
8 |
9 | > 单下划线: “内部使用” 的弱指示器。比如,`from M import *` 将不会引进用单下划线开头的对象。
10 |
11 | ### 双下划线
12 |
13 | 引自 Python 文档:
14 |
15 | > 任何 `__spam` 形式(至少两个下划线开头,最多一个下划线结尾)都是代替 `_classname__spam`,其中 `classname` 是当前类的名字。
16 |
17 | ### 约定
18 |
19 | `__foo__`:Python 内部的名字,用来区别其他用户自定义的命名,以防冲突
20 |
21 | `_foo`:用来指定变量私有
22 |
23 | `__foo`:解析器将会用 `_classname__foo` 来代替这个名字,以区别和其他类相同的命名
--------------------------------------------------------------------------------
/stackoverflow-about-Python/变化的默认参数.md:
--------------------------------------------------------------------------------
1 | ## 变化的默认参数
2 |
3 | 存在一个奇怪的现象:
4 |
5 | ```python
6 | def foo(a=[]):
7 | a.append(5)
8 | return a
9 | >>> foo()
10 | [5]
11 | >>> foo()
12 | [5, 5]
13 | >>> foo()
14 | [5, 5, 5]
15 | >>> foo()
16 | [5, 5, 5, 5]
17 | >>> foo()
18 | ```
19 |
20 | 曾经被称为动态设计缺陷,然而这个问题应当有更深层次的解释。
21 |
22 | Python 中的函数是最高等级的对象,而不仅仅是一小段代码。一个函数是一个被它自己定义而执行的对象,默认参数是一种“成员数据”,所以它们的状态和其他对象一样,会随着每一次调用而改变。
23 |
24 | 更详细的内容参考:[Python中的默认参数](http://effbot.org/zone/default-values.htm)
--------------------------------------------------------------------------------
/stackoverflow-about-Python/在Android上运行Python.md:
--------------------------------------------------------------------------------
1 | ## 在 Android 上运行 Python
2 |
3 | 有一种方法,使用 Kivy。Kivy 是交互界面快速开发应用的 Python 开源库,类似于多点触控 APP
4 |
5 | Kivy 运行在 Linux、Windows、macOS、Android 和 iOS。你也可以在所有的平台上运行 Python 代码
6 |
7 | 参考:[Kivy的应用](https://play.google.com/store/apps/details?id=org.kivy.showcase)
--------------------------------------------------------------------------------
/stackoverflow-about-Python/在Windows下安装pip.md:
--------------------------------------------------------------------------------
1 | ## 在Windows下安装pip
2 |
3 | ### Python3.4+
4 |
5 | Python3.4 已经自带 pip 了,自带的包管理器中加入了 Ruby、Nodejs、Haskell、Perl、Go 等其他几乎所有的开源社区流行语言
6 |
7 | ### Python2.x 和 Python <=3.3
8 |
9 | * 官方指南,下载 `get-pip.py`,然后运行
10 | * 另一种方法:Python 包的安装器:`.msi`,可以在这个[网站](http://www.lfd.uci.edu/~gohlke/pythonlibs/)上下载
11 |
12 | ### 代理问题
13 |
14 | 可能需要 HTTP 代理,把环境变量设置为 `http_proxy` 和 `https_proxy`
15 |
16 | ```python
17 | http://proxy_url:port
18 | http://username:password@proxy_url:port
19 | ```
20 |
21 | 如果用的是微软的 NTLM 代码,还是换一个友好一点的吧
22 |
23 | ### 找不到 `vcvarsall.bat`
24 |
25 | Pythoon 中有的模块是用 C/C++ 编写的,pip 将尝试从源码进行编译。如果没有安装或设置过 C/C++ 编译器,将会看到这个错误
26 |
27 | ```shell
28 | Error: Unable to find vcvarsall.bat
29 | ```
30 |
31 | 可以通过安装像 MinGw 或者 VC++ 这样的编译器来解决。微软实际上已经子弟啊了一个为 Python 准备的编译器:`vcpython27`
--------------------------------------------------------------------------------
/stackoverflow-about-Python/在函数里使用全局变量.md:
--------------------------------------------------------------------------------
1 | ## 在函数里使用全局变量
2 |
3 | 使用 global 关键字就可以了,例如:
4 |
5 | ```python
6 | globvar = 0
7 |
8 | def set_globvar_to_one():
9 | global globvar # 需要用global修饰一下globvar
10 | globvar = 1
11 |
12 | def print_globvar():
13 | print globvar # 如果要读globbar的值的话不需要用global修饰
14 |
15 | set_globvar_to_one()
16 | print_globvar() # 输出 1
17 | ```
18 |
19 | 如果只进行读取全局变量的值,就不需要用 global 修饰
--------------------------------------------------------------------------------
/stackoverflow-about-Python/如何判断一个文件是否存在.md:
--------------------------------------------------------------------------------
1 | ## 如何判断一个文件是否存在?
2 |
3 | 不想用 `try` 语句,如何判断一个文件是否存在?
4 |
5 | 答案是:
6 |
7 | ```python
8 | import os.path
9 | os.path.isfile(file_name)
10 | ```
11 |
12 |
--------------------------------------------------------------------------------
/stackoverflow-about-Python/如何知道一个对象有一个特定的属性.md:
--------------------------------------------------------------------------------
1 | ## 如何知道一个对象有一个特定的属性?
2 |
3 | 使用 `hasattr()`:
4 |
5 | ```python
6 | if hasattr(a, 'property'):
7 | a.property
8 | ```
9 |
10 | 在大多数实际情况下,如果一个属性有很大可能存在,那么就直接调用它或者让它引发异常,或者用 `try/except` 捕获,这种方法比 `hasattr` 快。如果这个属性很多情况下不在,或者你不确定,那么用 `hasattr` 将会比触发异常更快。
11 |
12 |
--------------------------------------------------------------------------------
/stackoverflow-about-Python/如何调用外部命令.md:
--------------------------------------------------------------------------------
1 | ## 如何调用外部命令?
2 |
3 | 各种方法及各自的优缺点如下:
4 |
5 | ### os 库
6 |
7 | #### system 函数
8 |
9 | 对于运行简单的 Shell 命令而不去调用外部程序来说是非常好用的:
10 |
11 | ```python
12 | os.system("命令加参数")
13 | ```
14 |
15 | 把命令和参数传递给你系统的 Shell 中。
16 |
17 | 用这个命令的好处在于你可以一次运行好多命令,还可以设置管道来进行重定向等。但是,这要求你手动输入空格等 Shell 字符。
18 |
19 | #### popen 函数
20 |
21 | ```python
22 | stream = os.popen("命令和参数")
23 | ```
24 |
25 | 和 `os.stream` 差不多,但是它提供了一个链接标准输入/输出的管道,还有其他 3 个 `popen` 可以调用。可以传递字符串,也可以传递列表,列表就不用担心溢出字符了(`escaping characters`
26 |
27 | ## subprocess 库
28 |
29 | #### Popen 管道
30 |
31 | 这个 `Popen` 是打算用来替代 `os.popen` 方法的,有点复杂:
32 |
33 | ```python
34 | subprocess.Popen("echo aaa", shell=True, stdout=PIPE).stdout.read()
35 | ```
36 |
37 | 而使用 `os.popen`:
38 |
39 | ```python
40 | os.popen("echo aaa").read()
41 | ```
42 |
43 | 它的最大优点就是一个类代替了原来 4 个不同的 popen
44 |
45 | #### call 方法
46 |
47 | 基本用法和 Popen 类参数一致,但是它会等待命令结束后才会返回程序
48 |
49 | ```python
50 | return_code = subprocess.call("echo aaa", shell=True)
51 | ```
52 |
53 | ### 总结
54 |
55 | * OS 模块里也有 C 语言里的 `fork/exec/spawn` 方法,但是不建议直接使用
56 | * 需要注意传递到 shell 命令一定要注意参数的安全性
57 |
58 | ```python
59 | subprocess.Popen("echo %s" % user_input, stdout=PIPE).stdout.read()
60 | ```
61 |
62 | 如果传入 `go die && rm -rf /` 会如何。。。
--------------------------------------------------------------------------------
/stackoverflow-about-Python/如何通过函数名的字符串来调用函数.md:
--------------------------------------------------------------------------------
1 | ## 如何通过函数名的字符串来调用这个函数?
2 |
3 | 假设我们有一个模块名字为 foo,其中有一个函数为 bar,但现在只给了字符串 `"bar"`,如何通过字符串 "bar" 来调用对应的函数 `foo.bar()`?
4 |
5 | ### Solve
6 |
7 | 通过 `getattr` 方法:
8 |
9 | ```python
10 | import foo
11 | methodToCall = getattr(foo, 'bar')
12 | result = methodToCall()
13 | ```
14 |
15 | 可以简写为:
16 |
17 | ```python
18 | result = getattr(foo, 'bar')()
19 | ```
20 |
21 | 另外 `getattr` 可以用在实例绑定、模块级方法、类方法等
--------------------------------------------------------------------------------
/stackoverflow-about-Python/字典合并问题.md:
--------------------------------------------------------------------------------
1 | ## 字典合并问题
2 |
3 | 利用 update 方法,合并后是修改原来的字典,而不是新建一个字典作为返回值,比如:
4 |
5 | ```python
6 | >>> x = {'a':1, 'b': 2}
7 | >>> y = {'b':10, 'c': 11}
8 | >>> z = x.update(y)
9 | >>> print z
10 | None
11 | >>> x
12 | {'a': 1, 'b': 10, 'c': 11}
13 | ```
14 |
15 | ### 解决方法一
16 |
17 | ```python
18 | z = dict(x.items() + y.items())
19 | ```
20 |
21 | 其中相同的键的值会被后一个字典的值覆盖
22 |
23 | 另外,如果是 Python3:
24 |
25 | ```python
26 | >>> z = dict(list(x.items()) + list(y.items()))
27 | ```
28 |
29 | ### 解决方法二
30 |
31 | 手动复制一遍再 update
32 |
33 | ```python
34 | z = x.copy()
35 | z.update(y)
36 | ```
--------------------------------------------------------------------------------
/stackoverflow-about-Python/循环中获取索引.md:
--------------------------------------------------------------------------------
1 | ## 如何在循环中获取索引
2 |
3 | 如果像 C 或者 PHP 那样加入一个状态变量那就太不 pythonic 了
4 |
5 | 最好的选择就是用内建函数 `enumerate()`
6 |
7 | ```python
8 | for idx, val in enumerate(ints):
9 | print(idx, val)
10 | ```
11 |
12 |
--------------------------------------------------------------------------------
/stackoverflow-about-Python/快速合并列表中的列表.md:
--------------------------------------------------------------------------------
1 | ## 如何快速合并列表中的列表?
2 |
3 | 除了循环,有没有更快的方法来实现一行合并列表中的列表?
4 |
5 | 比如这样的:
6 |
7 | ```python
8 | l = [[1,2,3],[4,5,6], [7], [8,9]]
9 | reduce(lambda x,y: x.extend(y),l)
10 | ```
11 |
12 | 当然上面这样会报错。。
13 |
14 | ### Solve
15 |
16 | 目前看来,最快的方法应该是:
17 |
18 | ```python
19 | [item for sublist in l for item in sublist]
20 | ```
21 |
22 | 可以用 `timeit` 模块进行验证:
23 |
24 | ```python
25 | $ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
26 | 10000 loops, best of 3: 143 usec per loop
27 | $ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
28 | 1000 loops, best of 3: 969 usec per loop
29 | $ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
30 | 1000 loops, best of 3: 1.1 msec per loop
31 | ```
32 |
33 | ### 解释
34 |
35 | 当有 L 个子串的时候用 `+`,即 (`sum`)的时间复杂度是 `O(L**2)`,每次迭代的时候作为中间结果的列表的长度就会越来越长,而且前一个中间结果的所有项都会再拷贝一遍给下一个中间结果。所以当你的列表 I 含有 L 个子串,I 列表的第一项需要拷贝 `L-1` 次,而第二项要拷贝 `L-2` 次,以此类推总数为: `I * (L ** 2) / 2`
36 |
37 | 列表推导式(`list comprehension`)只是生成一个列表,每次运行只拷贝一次(从开始的地方拷贝到最终结果)
--------------------------------------------------------------------------------
/stackoverflow-about-Python/怎么在终端里输出颜色.md:
--------------------------------------------------------------------------------
1 | ## 怎么在终端里输出颜色
2 |
3 | ### 方法一
4 |
5 | [Python termcolor module 模块](https://pypi.python.org/pypi/termcolor)
6 |
7 | ```python
8 | from termcolor import colored
9 | print(colored("hello", "red"))
10 | print(colored("world", "green"))
11 | ```
12 |
13 | ***
14 |
15 | ### 方法二
16 |
17 | 这依赖于你使用哪种操作系统,最常用的方法就是输出 ANSI 转义序列:
18 |
19 | ```python
20 | class bcolors:
21 | HEADER = '\033[95m'
22 | OKBLUE = '\033[94m'
23 | OKGREEN = '\033[92m'
24 | WARNING = '\033[93m'
25 | FAIL = '\033[91m'
26 | ENDC = '\033[0m'
27 | ```
28 |
29 | 可以这么使用上面的代码:
30 |
31 | ```python
32 | print(bcolors.WARNING + "Warning: No active frommets remain. Continue?" + bcolors.ENDC)
33 | ```
34 |
35 | 这种方法适合 macOS、Linux 和 Windows。还有一些其他的 ANSI 代码可以设置颜色,消除光标或者其他
36 |
37 | 如果想要应用更复杂的功能,应该看看 `curses` 模块,参考:[Python Curses HowTO](https://docs.python.org/2/howto/curses.html)
38 |
39 | 如果不使用拓展的 ASCII,比如不是一个 PC,那么 `#` 或者 `@` 可能是最好的选择
40 |
41 | 如果用的是 [IBM扩展ascii字符设置](http://telecom.tbi.net/asc-ibm.html),你还可以有更多的选择。176,177,178和219是"块字符"。
42 |
43 | 一些现代的基于文本的程序,像 Swarf Fortress 显示的文本使用图像模式,而用的字体也是传统的计算机字体的图像。可以在 [Dwarf Fortress Wiki](http://dwarffortresswiki.org/DF2014:Tilesets) 找到你可以用的字符.
44 |
45 | [Text Mode Demo Contest ](http://en.wikipedia.org/wiki/Text_Mode_Demo_Contest)也有许多资料可供参考。
46 |
47 |
--------------------------------------------------------------------------------
/stackoverflow-about-Python/怎么用引用来改变一个变量.md:
--------------------------------------------------------------------------------
1 | ## 怎么用引用来改变一个变量?
2 |
3 | Python 文档里,参数传递的是值还是引用并没有明确说明,现在想要通过引用来改变变量,如何实现?
4 |
5 | ***
6 |
7 | 参数是通过 assignment 来传递的,原因:
8 |
9 | * 传递的参数实际上是一个对象的引用(但是这个引用是通过值传递的)
10 | * 一些数据类型是可变的,但有一些就不是
11 |
12 | 所以:
13 |
14 | * 如果传递的是可变对象,那么就可以在方法里面改变,除非重新绑定了这个引用
15 | * 如果传递的是一个不可变对象,那么就无法实现
16 |
17 | ### 是否可变类型?
18 |
19 | * 列表-可变类型
20 | * 字符串-不可变类型
21 |
22 | ### Solve
23 |
24 | * 可以通过返回值实现
25 | * 可以建一个存放值的类,然后把它传递给函数或者用一个已有的类,比如列表:
26 |
27 | ```python
28 | def use_a_wrapper_to_simulate_pass_by_reference(stuff_to_change):
29 | new_string = something_to_do_with_the_old_string(stuff_to_change[0])
30 | stuff_to_change[0] = new_string
31 |
32 | # 你可以像这样调用
33 | wrapper = [my_string]
34 | use_a_wrapper_to_simulate_pass_by_reference(wrapper)
35 |
36 | do_something_with(wrapper[0])
37 | ```
38 |
39 | 尽管看上去很笨重,但是实现需求了。。。
--------------------------------------------------------------------------------
/stackoverflow-about-Python/把列表分割成同样大小的块.md:
--------------------------------------------------------------------------------
1 | ## 把列表分割成同样大小的块
2 |
3 | 希望有个方法,比如生成器,可以实现下面的效果:
4 |
5 | ```python
6 | l = range(1, 1000)
7 | print(chunks(l, 10))
8 | # [ [ 1..10 ], [ 11..20 ], .., [ 991..999 ] ]
9 | ```
10 |
11 | ### Solve
12 |
13 | ```python
14 | def chunks(l, n):
15 | """ Yield successive n-sized chunks from l.
16 | """
17 | for i in xrange(0, len(l), n):
18 | yield l[i:i+n]
19 | ```
20 |
21 | 或者
22 |
23 | ```python
24 | tuple(l[i:i+n] for i in xrange(0, len(l), n))
25 | ```
26 |
27 | ### 打印效果
28 |
29 | ```python
30 | import pprint
31 | pprint.pprint(list(chunks(range(10, 75), 10)))
32 | [[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
33 | [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
34 | [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
35 | [40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
36 | [50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
37 | [60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
38 | [70, 71, 72, 73, 74]]
39 | ```
--------------------------------------------------------------------------------
/stackoverflow-about-Python/枚举类型的使用.md:
--------------------------------------------------------------------------------
1 | ## 枚举类型的使用?
2 |
3 | PEP435 标准已经把枚举添加到 Python3.4 版本,在 PyPi 中也可以向后支持,通过:
4 |
5 | ```python
6 | pip install enum34
7 | ```
8 |
9 | 如果下载 `enum` 没有数字将会是另一个版本
10 |
11 | ```python
12 | from enum import Enum
13 | animal = Enum("Animal", "ant bee cat dog")
14 | ```
15 |
16 | 等价于:
17 |
18 | ```python
19 | class Animals(Enum):
20 | ant = 1
21 | bee = 2
22 | cat = 3
23 | dog = 4
24 | ```
25 |
26 | 在更早以前,有这些方法:
27 |
28 | ```python
29 | def enum(**enums):
30 | return type('Enum', (), enums)
31 |
32 | >>> Numbers = enum(ONE=1, TWO=2, THREE='three')
33 | >>> Numbers.ONE
34 | 1
35 | >>> Numbers.TWO
36 | 2
37 | >>> Numbers.THREE
38 | 'three'
39 | ```
40 |
41 | 或者
42 |
43 | ```python
44 | def enum(*sequential, **named):
45 | enums = dict(zip(sequential, range(len(sequential))), **named)
46 | return type('Enum', (), enums)
47 |
48 | >>> Numbers = enum('ZERO', 'ONE', 'TWO')
49 | >>> Numbers.ZERO
50 | 0
51 | >>> Numbers.ONE
52 | 1
53 | ```
54 |
55 | 把值转换为名字:
56 |
57 | ```python
58 | def enum(*sequential, **named):
59 | enums = dict(zip(sequential, range(len(sequential))), **named)
60 | reverse = dict((value, key) for key, value in enums.iteritems())
61 | enums['reverse_mapping'] = reverse
62 | return type('Enum', (), enums)
63 | >>> Numbers.reverse_mapping['three']
64 | 'THREE'
65 | ```
66 |
67 | 这样会覆盖名字下的所有东西,但是对于枚举的输出很有用。如果转换的值不存在就会抛出 KeyError 异常
--------------------------------------------------------------------------------
/stackoverflow-about-Python/根据字典值进行排序.md:
--------------------------------------------------------------------------------
1 | ## 根据字典值进行排序
2 |
3 | 对字典进行排序是不可能的,只有把字典转换成另一种方式才能排序。字典本身是无序的,但是像列表、元祖等其他类型是有序的。所以需要一个元祖列表来表示排序的字典
4 |
5 | DEMO:
6 |
7 | ```python
8 | import operator
9 | x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
10 | sorted_x = sorted(x.items(), key=operator.itemgetter(1))
11 | ```
12 |
13 | 也可以:
14 |
15 | ```python
16 | sorted(d.items(), key=lambda x: x[1])
17 | ```
18 |
19 |
--------------------------------------------------------------------------------
/stackoverflow-about-Python/检查列表为空的最好办法.md:
--------------------------------------------------------------------------------
1 | ## 检查列表为空的最好办法
2 |
3 | 用隐藏的空列表的布尔值才是最 Pythonic 的方法:
4 |
5 | ```python
6 | if not a:
7 | print("list a is empty")
8 | ```
9 |
10 | 虽然我自己一般用 `len(a) == 0`
--------------------------------------------------------------------------------
/stackoverflow-about-Python/检查文件夹是否存在的操作.md:
--------------------------------------------------------------------------------
1 | ## 检查文件夹是否存在的操作
2 |
3 | 方法一:
4 |
5 | ```python
6 | filename = "/my/directory/filename.txt"
7 | dir = os.path.dirname(filename)
8 |
9 | try:
10 | os.stat(dir)
11 | except:
12 | os.mkdir(dir)
13 |
14 | f = file(filename)
15 | ```
16 |
17 | 方法二:
18 |
19 | ```python
20 | def ensure_dir(f):
21 | d = os.path.dirname(f)
22 | if not os.path.exists(d):
23 | os.makedirs(d)
24 | ```
25 |
26 | 【注意】,如果在调用 `os.path.exists` 和 `os.makedirs` 之间被创建了,将会出现一个 `OSError`。然而捕获 `OSError` 并不能很好地解决这个问题,因为它将会忽略磁盘空间不足,没有足够权限等一些其他造成文件创建失败的因素
27 |
28 | 一个做法是捕获 OSError 异常并检查返回的错误代码
29 |
30 | 方法三:
31 |
32 | ```python
33 | os.makedirs(self.path_dir, exist_ok=True)
34 | ```
35 |
36 |
--------------------------------------------------------------------------------
/stackoverflow-about-Python/类里的静态变量.md:
--------------------------------------------------------------------------------
1 | ## 类里的静态变量
2 |
3 | 变量是在类定义时声明的,不是在类方法或静态变量中:
4 |
5 | ```python
6 | >>> class MyClass:
7 | ... i = 3
8 | ...
9 | >>> MyClass.i
10 | 3
11 | ```
12 |
13 | 注意变量 i 是类级别的,所以它和所有实例的 i 变量是不一样的,比如:
14 |
15 | ```python
16 | >>> m = MyClass()
17 | >>> m.i = 4
18 | >>> MyClass.i, m.i
19 | >>> (3, 4)
20 | ```
21 |
22 | 这与 C++ 以及 Java 不一样,但是和 C# 相同,就是静态成员不能被实例所引用
--------------------------------------------------------------------------------
/stackoverflow-about-Python/装饰器classmethod和staticmethod的区别.md:
--------------------------------------------------------------------------------
1 | ## 装饰器classmethod和staticmethod的区别
2 |
3 | 一个对象实体调用方法,隐藏了传递的第一个参数 `self`:
4 |
5 | ```python
6 | a.foo(1)
7 | ```
8 |
9 | 如果方法是用 `classmethods` 装饰,那么被隐藏的第一个参数是对象的类而不是 `self`:
10 |
11 | ```python
12 | a.class_foo(1)
13 | ```
14 |
15 | 也可以用类调用,一般被装饰为 `classmethod` 是希望用类来调用,而不是实例来调用
16 |
17 | 用 `staticmethods` 装饰,不管传递给第一个参数是 `self` 还是 `cls`,表现都一样,静态方法被用来组织类之间有逻辑关系的函数
18 |
19 | 静态方法就是一个普通方法,一个不带参数绑定的方法
20 |
21 |
--------------------------------------------------------------------------------
/剑指 Offer 编程题/readme.md:
--------------------------------------------------------------------------------
1 | # 说明
2 | 本文件保存练习剑指 Offer 时的相关代码及笔记
3 |
4 | # 题目练习链接
5 | [牛客网](http://www.nowcoder.com/ta/coding-interviews?page=)
--------------------------------------------------------------------------------
/剑指 Offer 编程题/二维数组中的查找/python_solve.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """
5 | Python 解决二维数组中的查找问题
6 | """
7 |
8 | __author__ = '__L1n__w@tch'
9 |
10 |
11 | class Solution:
12 | # array 二维列表
13 | @classmethod
14 | def Find(cls, array, target):
15 | # write code here
16 | row = len(array)
17 | column = len(array[0])
18 |
19 | if row > 0 and column > 0:
20 | x, y = 0, column - 1 # 从右上角第一个数字开始找
21 |
22 | while 0 <= x < row and 0 <= y < column:
23 | if array[x][y] == target:
24 | return True
25 | elif array[x][y] > target: # 说明当前列不会有这个数了
26 | y -= 1
27 | elif array[x][y] < target: # 说明当前行不会有这个数了
28 | x += 1
29 | return False
30 |
31 |
32 | if __name__ == "__main__":
33 | solution = Solution()
34 | array = [[]]
35 | print(solution.Find(array, 9))
36 |
--------------------------------------------------------------------------------
/剑指 Offer 编程题/二维数组中的查找/readme.md:
--------------------------------------------------------------------------------
1 | # 题目描述
2 | 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
3 |
4 | # 思路解释
5 | 从右上角开始查找, 如果大于右上角的数, 说明当前列不可能存在这个数; 如果小于右上角的数, 说明当前行不可能存在这个数.
6 |
7 | # 条件限制
8 | 时间限制:1秒
9 |
10 | 空间限制:32768K
11 |
12 | # Python 版本最终提交
13 | ```python
14 | # -*- coding:utf-8 -*-
15 | class Solution:
16 | # array 二维列表
17 | def Find(self, array, target):
18 | # write code here
19 | row = len(array)
20 | column = len(array[0])
21 |
22 | if row > 0 and column > 0:
23 | x, y = 0, column - 1 # 从右上角第一个数字开始找
24 |
25 | while 0 <= x < row and 0 <= y < column:
26 | if array[x][y] == target:
27 | return True
28 | elif array[x][y] > target: # 说明当前列不会有这个数了
29 | y -= 1
30 | elif array[x][y] < target: # 说明当前行不会有这个数了
31 | x += 1
32 | return False
33 | ```
34 |
35 | # C/C++ 版本最终提交
36 | ```c++
37 | class Solution {
38 | public:
39 | bool Find(vector > array, int target) {
40 | int row = array.size();
41 | int column = array[0].size();
42 |
43 | if (row > 0 && column > 0) {
44 | int x, y;
45 | x = 0, y = column - 1;
46 | while (x < row && y >= 0) {
47 | if (array[x][y] == target) {
48 | return true;
49 | }
50 | else if (array[x][y] > target) {
51 | --y;
52 | }
53 | else {
54 | ++x;
55 | }
56 | }
57 | }
58 |
59 | return false;
60 | }
61 | };
62 | ```
--------------------------------------------------------------------------------
/剑指 Offer 编程题/二维数组中的查找/unittest_solve.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """
5 | 测试自己写的答案是否正确
6 | """
7 | import random
8 | import unittest
9 | from python_solve import Solution
10 |
11 | __author__ = '__L1n__w@tch'
12 |
13 |
14 | class TestSolution(unittest.TestCase):
15 | def test_solution(self):
16 | for i in range(33):
17 | array, max_number = self.create_array()
18 | target = array[random.randint(0, len(array) - 1)][random.randint(0, len(array[0]) - 1)]
19 | self.assertTrue(Solution.Find(array, target))
20 | self.assertFalse(Solution.Find(array, max_number + random.randint(1, max_number)))
21 |
22 | def create_array(self):
23 | """
24 | 返回一个符合要求的二维数组以及该数组中的最大数字
25 | :return:
26 | """
27 | rows = random.randint(1, 33)
28 | columns = random.randint(1, 55)
29 | array = list()
30 | max_number = 0
31 |
32 | for row in range(rows):
33 | column_list = list()
34 | for column in range(columns):
35 | max_number += 1
36 | column_list.append(max_number)
37 |
38 | array.append(column_list)
39 | return array, max_number
40 |
41 |
42 | if __name__ == "__main__":
43 | pass
44 |
--------------------------------------------------------------------------------
/剑指 Offer 编程题/从尾到头打印链表/python_solve.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """
5 | 输入一个链表,从尾到头打印链表每个节点的值。
6 |
7 | 输入为链表的表头
8 |
9 | 输出为需要打印的“新链表”的表头
10 | """
11 |
12 | __author__ = '__L1n__w@tch'
13 |
14 |
15 | class ListNode:
16 | def __init__(self, x, next):
17 | self.val = x
18 | self.next = next
19 |
20 |
21 | class Solution:
22 | # 返回从尾部到头部的列表值序列,例如[1,2,3]
23 | def printListFromTailToHead(self, listNode):
24 | # write code here
25 | res = []
26 |
27 | if listNode:
28 | res.insert(0, listNode.val) # 注意插入的是数值而不是整个对象
29 | while listNode.next:
30 | res.insert(0, listNode.next.val)
31 | listNode = listNode.next
32 |
33 | return res
34 |
35 |
36 | if __name__ == "__main__":
37 | listNode = ListNode(67, ListNode(0, ListNode(24, ListNode(58, None))))
38 | solution = Solution()
39 | for each in solution.printListFromTailToHead(listNode):
40 | print(each)
41 |
--------------------------------------------------------------------------------
/剑指 Offer 编程题/从尾到头打印链表/readme.md:
--------------------------------------------------------------------------------
1 | # 题目描述
2 | 输入一个链表,从尾到头打印链表每个节点的值。
3 |
4 | 输入描述:
5 |
6 | 输入为链表的表头
7 |
8 | 输出描述:
9 |
10 | 输出为需要打印的“新链表”的表头
11 |
12 | # Python 版本提交
13 | ```python
14 | class Solution:
15 | # 返回从尾部到头部的列表值序列,例如[1,2,3]
16 | def printListFromTailToHead(self, listNode):
17 | # write code here
18 | res = list()
19 |
20 | if listNode:
21 | res.insert(0, listNode.val) # 注意插入的是数值而不是整个对象
22 | while listNode.next:
23 | res.insert(0, listNode.next.val)
24 | listNode = listNode.next
25 |
26 | return res
27 | ```
28 |
29 | # C/C++ 版本提交
30 | 思路跟 Python 版本一样
31 |
32 | ```c++
33 | class Solution {
34 | public:
35 | vector printListFromTailToHead(struct ListNode *head)
36 | {
37 | vector result;
38 |
39 | if (head != NULL)
40 | {
41 | result.insert(result.begin(), head->val);
42 | while (head->next != NULL)
43 | {
44 | result.insert(result.begin(), head->next->val);
45 | head = head->next;
46 | }
47 | }
48 | return result;
49 | }
50 | };
51 | ```
--------------------------------------------------------------------------------
/剑指 Offer 编程题/旋转数组的最小数字/readme.md:
--------------------------------------------------------------------------------
1 | # 题目描述
2 | 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
3 |
4 | 输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。
5 |
6 | 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
7 |
8 | NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
9 |
10 | # Python 版本最终提交
11 | 看别人的 C/C++ 答案那么长, 结果 Python 就一行, 果然还是得自己用 C 重写
12 |
13 | ```python
14 | class Solution:
15 | def minNumberInRotateArray(self, rotateArray):
16 | # write code here
17 | return min(rotateArray)
18 | ```
19 |
20 | # C/C++ 版本最终提交
21 | 根据二分查找改编的, 思路是参考剑指 Offer 里给的
22 |
23 | ```
24 | class Solution {
25 | public:
26 | int minNumberInRotateArray(vector rotateArray)
27 | {
28 | if (rotateArray.size() > 0)
29 | {
30 | int low, high, middle;
31 | low = 0;
32 | high = rotateArray.size() - 1;
33 | middle = low;
34 |
35 | // 结束条件
36 | while (rotateArray[low] >= rotateArray[high])
37 | {
38 | // 结束条件
39 | if (high - low == 1)
40 | {
41 | middle = high;
42 | break;
43 | }
44 |
45 | // 求取中间的索引值
46 | middle = (low + high) / 2;
47 |
48 | // 判断中间值的大小, 知道它是前面的递增序列还是后面的递增序列
49 | if (rotateArray[middle] <= rotateArray[high])
50 | {
51 | high = middle;
52 | }
53 | else if (rotateArray[middle] >= rotateArray[low])
54 | {
55 | low = middle;
56 | }
57 | }
58 |
59 | return rotateArray[middle];
60 | }
61 | return 0;
62 | }
63 | };
64 | ```
--------------------------------------------------------------------------------
/剑指 Offer 编程题/替换空格/readme.md:
--------------------------------------------------------------------------------
1 | # 题目描述
2 | 请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
3 |
4 | # 思路
5 | * Python: 直接 replace() 方法就行了....
6 | * C/C++: 剑指 Offer 给出了两种方法, 一种是 O(n^2), 从头遍历, 遇到空格就进行替换操作, 同时把其余字符往后移动; 另一种方法是先遍历一遍, 知道有几个空格, 接着准备两个指针及一个数组, 指针分别指向原始字符串以及数组的末尾, 然后从后头开始遍历, 直至两个指针相遇
7 |
8 | # Python 版本最终提交
9 | 感觉跟作弊一样的 Python:
10 |
11 | ```python
12 | # -*- coding:utf-8 -*-
13 | class Solution:
14 | # s 源字符串
15 | def replaceSpace(self, s):
16 | # write code here
17 | return s.replace(" ", "%20")
18 | ```
19 |
20 | # C/C++ 版本最终提交
21 | 注意对 length 参数的理解, 还有这里返回结果是直接修改 str 而不是重新申请一段内存空间
22 |
23 | ```c++
24 | //length为牛客系统规定字符串输出的最大长度,固定为一个常数
25 | class Solution {
26 | public:
27 | void replaceSpace(char *str, int length)
28 | {
29 | // 这其实可以忽略
30 | if (str == NULL || length < 0)
31 | {
32 | return;
33 | }
34 |
35 | // 遍历一遍数一下有多少个空格
36 | int space_numbers = 0;
37 | int i = 0;
38 | while (str[i] != '\0') // 注意不能数 length, 否则会越界
39 | {
40 | if (str[i++] == ' ')
41 | {
42 | ++space_numbers;
43 | }
44 | }
45 |
46 | // 计算替换后的长度
47 | int raw_length = strlen(str);
48 | int after_replace_length = raw_length + space_numbers * 2;
49 |
50 | // 定义指针
51 | int point_to_raw, point_to_new;
52 | point_to_new = after_replace_length;
53 | point_to_raw = raw_length;
54 |
55 | // while 循环遍历, 条件是两个索引值相等
56 | // while 结构体实现替换操作
57 | while (point_to_new != point_to_raw)
58 | {
59 | if (str[point_to_raw] != ' ')
60 | {
61 | str[point_to_new] = str[point_to_raw];
62 | --point_to_new;
63 | }
64 | else
65 | {
66 | str[point_to_new] = '0';
67 | str[point_to_new - 1] = '2';
68 | str[point_to_new - 2] = '%';
69 | point_to_new -= 3;
70 | }
71 | --point_to_raw;
72 | }
73 |
74 | }
75 | };
76 | ```
77 |
--------------------------------------------------------------------------------
/剑指 Offer 编程题/用两个栈实现队列/readme.md:
--------------------------------------------------------------------------------
1 | # 题目描述
2 | 用两个栈来实现一个队列,完成队列的 Push 和 Pop 操作。队列中的元素为 int 类型。
3 |
4 | # Python 版本最终提交
5 | ```python
6 | class Solution:
7 | def __init__(self):
8 | self.first_stack = list()
9 | self.second_stack = list()
10 |
11 | def push(self, node):
12 | # write code here
13 | self.first_stack.append(node)
14 |
15 | def pop(self):
16 | # return xx
17 | if len(self.second_stack) <= 0:
18 | while len(self.first_stack) > 0:
19 | self.second_stack.append(self.first_stack.pop())
20 | return self.second_stack.pop()
21 | ```
22 |
23 | # C/C++ 版本最终提交
24 | 突然发现 C/C++ 的 pop() 方法并不返回值啊...
25 | ```c++
26 | class Solution {
27 | public:
28 | void push(int node)
29 | {
30 | stack1.push(node);
31 | }
32 |
33 | int pop()
34 | {
35 | if (stack2.size() <= 0)
36 | {
37 | while (stack1.size() > 0)
38 | {
39 | stack2.push(stack1.top());
40 | stack1.pop();
41 | }
42 | }
43 | int result = stack2.top();
44 | stack2.pop();
45 | return result;
46 | }
47 |
48 | private:
49 | stack stack1;
50 | stack stack2;
51 | };
52 | ```
--------------------------------------------------------------------------------
/剑指 Offer 编程题/用两个栈实现队列/two_stack_implement_queue.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """
5 | 利用两个栈来实现队列
6 | """
7 | import queue
8 |
9 | __author__ = '__L1n__w@tch'
10 |
11 |
12 | class Solution:
13 | def __init__(self):
14 | self.first_stack = list()
15 | self.second_stack = list()
16 |
17 | def push(self, node):
18 | # write code here
19 | self.first_stack.append(node)
20 |
21 | def pop(self):
22 | # return xx
23 | if len(self.second_stack) <= 0:
24 | while len(self.first_stack) > 0:
25 | self.second_stack.append(self.first_stack.pop())
26 | return self.second_stack.pop()
27 |
28 |
29 | if __name__ == "__main__":
30 | data = [1, 2, 3, 4, 5, 6, 7, 8]
31 | q = queue.Queue()
32 | s = Solution()
33 |
34 | for each in data:
35 | q.put(each)
36 | s.push(each)
37 |
38 | for i in range(len(data)):
39 | print(s.pop(), end=" ")
40 |
41 | print("")
42 |
43 | for i in range(len(data)):
44 | print(q.get(), end=" ")
45 |
--------------------------------------------------------------------------------
/剑指 Offer 编程题/重建二叉树/readme.md:
--------------------------------------------------------------------------------
1 | # 题目描述
2 | 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
3 |
4 | # Python 最终提交
5 | ```python
6 | class Solution:
7 | # 返回构造的TreeNode根节点
8 | def reConstructBinaryTree(self, pre, tin):
9 | # write code here
10 | if pre and tin:
11 | # 找到根节点
12 | root = TreeNode(pre[0])
13 |
14 | # 计算根节点在中序中的索引
15 | root_position_in_order = tin.index(root.val)
16 |
17 | # 计算左子树长度
18 | left_length = root_position_in_order
19 | right_length = len(tin) - root_position_in_order - 1
20 |
21 | # 比该索引值小的为左子树
22 | if left_length > 0:
23 | root.left = Solution().reConstructBinaryTree(pre[1:root_position_in_order + 1],
24 | tin[:root_position_in_order])
25 |
26 | # 计算右子树长度
27 | if right_length > 0:
28 | # 比该索引值大的为右子树
29 | root.right = Solution().reConstructBinaryTree(pre[root_position_in_order + 1:],
30 | tin[root_position_in_order + 1:])
31 |
32 | return root
33 | ```
34 |
35 | # C/C++ 最终提交
36 | 思路差不多, 不过换了种实现法
37 |
38 | ```c++
39 | class Solution {
40 | public:
41 | struct TreeNode *reConstructBinaryTree(vector pre, vector in)
42 | {
43 | if (pre.size() > 0 && in.size() > 0)
44 | {
45 | TreeNode * root = new TreeNode(pre[0]);
46 |
47 | vector::iterator root_position_in_order = find(in.begin(), in.end(), root->val);
48 |
49 | int left_length = root_position_in_order - in.begin();
50 |
51 |
52 | root->left = Solution().reConstructBinaryTree(
53 | vector(pre.begin() + 1, pre.begin() + left_length + 1),
54 | vector(in.begin(), root_position_in_order));
55 | root->right = Solution().reConstructBinaryTree(
56 | vector(pre.begin() + left_length + 1, pre.end()),
57 | vector(root_position_in_order + 1, in.end()));
58 |
59 | return root;
60 | }
61 | return NULL;
62 | }
63 | };
64 | ```
--------------------------------------------------------------------------------
/剑指 Offer 编程题/重建二叉树/rebuild_binary_tree_pre_in_order.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # version: Python3.X
4 | """
5 | 根据前序和中序重建二叉树
6 | """
7 |
8 | __author__ = '__L1n__w@tch'
9 |
10 |
11 | class TreeNode:
12 | def __init__(self, x):
13 | self.val = x
14 | self.left = None
15 | self.right = None
16 |
17 |
18 | class Solution:
19 | # 返回构造的TreeNode根节点
20 | def reConstructBinaryTree(self, pre, tin):
21 | # write code here
22 | if pre and tin:
23 | # 找到根节点
24 | root = TreeNode(pre[0])
25 |
26 | # 计算根节点在中序中的索引
27 | root_position_in_order = tin.index(root.val)
28 |
29 | # 计算左子树长度
30 | left_length = root_position_in_order
31 | right_length = len(tin) - root_position_in_order - 1
32 |
33 | # 比该索引值小的为左子树
34 | if left_length > 0:
35 | root.left = Solution().reConstructBinaryTree(pre[1:root_position_in_order + 1],
36 | tin[:root_position_in_order])
37 |
38 | # 计算右子树长度
39 | if right_length > 0:
40 | # 比该索引值大的为右子树
41 | root.right = Solution().reConstructBinaryTree(pre[root_position_in_order + 1:],
42 | tin[root_position_in_order + 1:])
43 |
44 | return root
45 |
46 |
47 | def post_order_print(list_node):
48 | if list_node:
49 | if list_node.left:
50 | post_order_print(list_node.left)
51 | if list_node.right:
52 | post_order_print(list_node.right)
53 | print(list_node.val, end=" ")
54 |
55 |
56 | if __name__ == "__main__":
57 | pre_order = [1, 2, 4, 7, 3, 5, 6, 8]
58 | in_order = [4, 7, 2, 1, 5, 3, 8, 6]
59 | root = Solution().reConstructBinaryTree(pre_order, in_order)
60 | post_order_print(root)
61 |
--------------------------------------------------------------------------------
/安全测试开发相关面试/readme.md:
--------------------------------------------------------------------------------
1 | # 说明
2 |
3 | 主要是整理以下几个岗位的面试经历:
4 |
5 | * 安全测试
6 | * 测试开发
7 | * 自动化测试
8 | * 业务安全
9 | * ...
--------------------------------------------------------------------------------
/安全测试开发相关面试/业务安全类面试参考.md:
--------------------------------------------------------------------------------
1 | # Q&A
2 |
3 | ```shell
4 | 1、SDLC,项目有部分是 SDLC,从业务需求开始就介入,需求评审、代码审计、安全测试整个流程,安全培训,做把一些东西想要自动化,测试过程,代码审计过程;
5 |
6 | 2、负责一个业务,安全流程跟进一下,某些类型测试,自动化,推广使用
7 |
8 | 3、代码审计工具,安全扫描 app-scan,一个需求、活动、要不要上线,设计阶段就有问题,设计阶段提出问题就避免开发阶段返工开发
9 |
10 | 4、功能测试有没有接触过
11 |
12 | 5、IPS/WAF、二进制、内网渗透,哪方面更擅长
13 |
14 | 6、业务安全与二进制跨度挺大,怎么解决这个问题
15 |
16 | 7、业务安全与需求相关,敏捷开发,跟进需求有没有风险,防止数据泄露相关,风险控制类的东西,业务会上一些活动
17 |
18 | 8、讲一下工作经历
19 |
20 | 9、黑链,做哪些工作
21 |
22 | 10、判断黑链正则,自动化脚本的内容
23 |
24 | 11、主要语言是什么
25 |
26 | 12、IPS/WAF 测试效果
27 |
28 | 13、黑链工作,是负责收集数据
29 |
30 | 14、漏洞规则库,也是这种类型,写过这方面的正则吗
31 |
32 | 15、攻击 poc 是自己写的
33 |
34 | 16、SQL 注入怎么生成有效 poc 产生绕过规则
35 |
36 | 17、fuzz 负责哪一部分
37 |
38 | 18、漏洞挖掘,实战经验
39 |
40 | 19、SRC 授权,漏洞挖掘经验
41 |
42 | 20、CTF 类型,主要擅长哪方面
43 |
44 | 21、WEB 这块,业务上的问题 WEB 页面、小程序,API 调用,偏向于 WEB 这块
45 |
46 | 22、反序列化漏洞
47 |
48 | 23、Java 能力怎么样
49 |
50 | 24、WEB-XSS 过滤哪些字符
51 |
52 | 25、比较熟悉哪一块,WEB 类的
53 |
54 | 26、伪造 Cookie 怎么弄的
55 |
56 | 27、文件包含,getshell,场景,常见题目
57 |
58 | 28、二进制,绕过病毒,杀毒软件
59 |
60 | 29、分析 EXE、ELF
61 |
62 | 30、给个新的病毒,分析行为,别人没分析过的
63 |
64 | 31、分析找到 CC2C 后门的
65 |
66 | 32、方向规划
67 |
68 | 33、倾向于手工测试、自动化测试【攻击】
69 |
70 | 34、burpsuite 用过吗
71 |
72 | 35、burpsuite 写插件
73 |
74 | 36、SDLC 不做测试,不做评审,转做大数据方面安全研究,数据方面的安全研究
75 |
76 | 37、蓝军,WEB、内网渗透
77 |
78 | 38、利用已有的安全的知识,去实现一系列自动化测试
79 |
80 | 39、自动化挖掘,SRC
81 |
82 | 40、离开的原因,薪资
83 |
84 | 41、有什么问题
85 |
86 | ```
--------------------------------------------------------------------------------
/安全测试开发相关面试/安全测试类面试参考.md:
--------------------------------------------------------------------------------
1 | # Q&A
2 |
3 | 安全、测试方案等多个维度
4 |
5 | ```shell
6 | 1、自我介绍
7 | 不要有太多口语化的词汇,比如老是说【然后】
8 |
9 | 2、测试方案的介绍
10 | 【需求分析】 -> 跟干系人沟通,不同产品线不同层次的干系人有不同的需求,做到什么目标要覆盖到哪些测试面;
11 | 【攻击手段梳理】 -> 站在攻击者的角度,搜集攻击场景,比如说 IPS/WAF 漏洞攻击,WEB 就经常分为 SQL 注入、XSS、CSRF 之类的;然后黑链的话,就分为 JS 挂链,黑词替换,词本身形态变换之类的;文件杀毒的话,几个维度,比如传播方式,或者病毒种类,蠕虫、木马、勒索、挖矿之类的;
12 | 【测试项梳理】 -> 整合需求分析、整合攻击手段,用一些测试项设计的方法,测试项设计方法比如:需求分析、场景分析、逻辑分析、关联分析;
13 | 【测试点梳理】 -> 也是用测试点设计方法来生成,比如说,等价类、边界值、正反对比、业务逻辑等等
14 | 【测试案例的编写以及自动化】 -> 包括了样本建设、测试自动化,竞品分析之类的
15 | 【效果改进】 -> 开评审会,讨论测出来的效果,哪方面是劣势,哪方面需要优先改,包括产品本身,测试优化,以及测试输出(PK 样本,竞标打法等)
16 | 【测试结果归档】 -> 测出来的各种打法以及对应的 PK 样本,提供给一线用的之类的东西;测试数据测试结果啥的,都要归档整理吗
17 |
18 | 3、通用方案只在 AI 里面进行了测试吗
19 | 这套方案经过多个安全项目测试之后整合出来的一套方案,安全项目测试里面包括了 AI 和非 AI 都有涉及到,理论上方案是通用各个安全方向的,只是不同方向的细节需要考虑一下
20 |
21 | 4、文件大小,测试项
22 | 有几个维度产生测试点,比如说产品线,对 2MB 可以作为一个临界值,比如说场景,PE 头 224 字节,可能刚好少了那么 1 个字节引擎就判黑了,224 也可以作为一个边界值
23 |
24 | 5、测试点,自动化测试脚本可以测试任何产品吗
25 | 分俩块,一个是测试数据,一个是测试脚本,测试数据是通用的,就通过脚本,包括爬虫脚本/文件生成脚本之类的,生成出来的数据;还有一个测试脚本,针对不同形态产品的自动化测试
26 |
27 | 6、腾讯电脑管家企业版和个人版的竞品分析
28 | 公司对标产品线干系人讨论,比如说防火墙对标,AF部门,友商是华为防火墙、360防火墙之类的,就讨论比如说病毒名的显示、文件大小的支持、企业版个人版之类的
29 |
30 | 7、有跟腾讯沟通吗?
31 | 做竞品分析怕泄露样本之类的
32 |
33 | 8、页面安全产品的测试?
34 | 测的安全产品是单独的模块,抽离出来测试了,提高测试效率;然后页面端的测试就做一些偏功能性的测试,比如说病毒名显示是否正常,黑产溯源能不能准确判定出黑词之类的
35 |
36 | 9、核心,各种类型的安全测试
37 | 主要是安全产品做自动化测试,以及后面研究不同安全方向设计测试方案并落地同时自动化之类的
38 |
39 | 10、通用测试方案,学习阶段,学校阶段,能够输出类似的产出吗,工作跟学校最大的区别
40 | 工作思维,学生思维:工作中讲究尽可能快的把时间做好做成,学生可能就是给你一段时间,你慢慢研究,这段时间内尽可能做完这件事情然后反馈
41 | 学校里面可以产生类似的报告,各种研究报告,就给你一个攻击场景,中间人攻击场景,然后你怎么复现之类的
42 |
43 | 11、工作中尽快出成果,是怎么确保的
44 | 接到任务后分清核心需求,然后排计划,工作量小就先做出成果,再来看怎么改进;工作量大就先选方案,快速出小成果,根据小成果来进一步做决策
45 |
46 | 12、这个快速 DEMO 的模式,是怎么学到的
47 | 导师传授了一部分经验,说是要快速产生价值;
48 |
49 | 13、AI 引擎,测试需求,怎么完成需求分析,做什么测试
50 | 通用的测试方案里面
51 |
52 | 14、所有安全类测试产品都总结到这个测试方案里面
53 | 不同的安全方向,测试产品主要是有需求不同,自动化测试方法不同啊
54 |
55 | 15、杀毒引擎是 AI 杀毒引擎
56 | SAVE-AI 引擎 + 小红伞黑盒引擎
57 |
58 | 16、不同于通用测试方案的测试点
59 | 每个安全方向或者每个测试产品都有不同的,就比如 blablabla
60 |
61 | 17、AI 有什么特别的地方,测试项和测试点
62 | AI 是通过学习生成的引擎,还有泛化的概念,测试的时候得避免用学习过的数据来测试,然后 AI 引擎具有不确定性,比如俩恶意文件,利用同样的漏洞 永恒之蓝,一个能检出一个没法检出
63 |
64 | 18、测试数据是怎么选择的
65 | 避免学习过的数据,测试项整理不同维度,然后筛选
66 |
67 | 19、没学习过的数据,怎么弄到
68 | 避开爬取的网站,然后自己生成,md5 清单区别,测试项区分等
69 |
70 | 20、结果改进,建议,优先级
71 | (1)安全事件;(2)公司战略;(3)CVE 编号高中低威胁程度;(4)客户反馈;
72 |
73 | 21、规则制定,怎么知道有这些东西
74 | 摸索,整合零散的,得到的,然后落地,看效果,效果不错就继续使用
75 |
76 | 22、调研,论文,博客园,安全测试方案
77 | 各种网站各种论坛搜索
78 |
79 | 23、CTF 比赛,比赛的内容,如何去做的
80 | 基于刷题经验积累
81 |
82 | 24、CTF 经验是哪里来的
83 | 刷题,大学期间,还有自己业余刷题
84 |
85 | 25、在学校的时候没有参加过正式的 CTF 比赛吗
86 | 有,比较少
87 |
88 | 26、学校有自己的战队
89 | 有,但是没去
90 |
91 | 27、上完本科之后没继续研究,钻研信息安全
92 | 以工作优先,工作有涉及会研究,工作没涉及看自己私下需求了
93 |
94 | 28、学校是自己准备东西上去讲的
95 | 翻转课堂
96 |
97 | 29、老师的作用是啥
98 | 搜集资料,提供
99 |
100 | 30、爬虫的了解
101 | 简单的网站,requests 库爬取,复杂一点的,selenium 库
102 |
103 | 31、滑动检测之类的,反爬技术,怎么解决
104 | 基本思路就是,识别出【目标区域】、然后拟人拖动到对应区域,https://juejin.im/entry/5b9b995cf265da0ac1390530
105 |
106 | 32、滑动的那个,验证过一次,之后还会再次校验
107 | 不同网站反爬技术不同,所以需要区别对待
108 |
109 | 33、安全测试对本身的安全性要求也比较高
110 | 安全测试俩目标:产品本身的安全性以及、安全产品的安全能力
111 |
112 | 34、单元测试
113 | django-test 框架,unittest 框架,mock 模块,selenium 框架,无界面框架比如(PhantomJS)之类的
114 |
115 | 35、网站源码,情况
116 | 放到 github 上了
117 |
118 | 36、单测,怎么实现的
119 | unittest 库,用断言来判断结果是不是正确的,然后可以用 mock 模拟一下中间函数的调用
120 |
121 | 37、当导师带徒弟
122 | 快速产生工作价值
123 |
124 | 38、怎么判断哪些东西比较重要
125 | (1)公司战略;(2)BOSS关注点;(3)市场价值
126 |
127 | 39、2 月离职现在回
128 | 很多个因素
129 |
130 | 40、个人规划是什么样的
131 | 测试开发
132 |
133 | 41、你还有什么想问的
134 | 想提升测试能力,想问公司测试技术属于大概什么水平
135 | ```
--------------------------------------------------------------------------------
/安全测试开发相关面试/测试开发类面试参考.md:
--------------------------------------------------------------------------------
1 | # Q&A
2 |
3 | ## 笔试
4 |
5 | ```shell
6 | 1、列表生成式,去重,排序
7 |
8 | 2、SQL 语句,多个表联合查询
9 | SELECT * FROM
10 |
11 | 3、ANR
12 | https://baike.baidu.com/item/ANR
13 |
14 | 4、KNN 算法
15 | https://baike.baidu.com/item/%E9%82%BB%E8%BF%91%E7%AE%97%E6%B3%95/1151153?fromtitle=Knn&fromid=3479559
16 |
17 | 5、激活函数
18 | https://blog.csdn.net/qrlhl/article/details/60883604
19 |
20 | 6、装饰器作用,使用,如何编写
21 |
22 | 7、单线程模型,Manager、Manager_Queue,Looper 啥的
23 | https://blog.csdn.net/Skypine_Lee/article/details/7692693
24 |
25 | 8、private、protected、publice 区别
26 |
27 | 9、常用 Linux/adb 命令
28 | ```
29 |
30 | ## 面试
31 |
32 | ```shell
33 | 1、先做个自我介绍
34 |
35 | 2、安全测试应用到手机的话会有什么测试方法
36 |
37 | 3、有没有针对手机做过这种测试
38 |
39 | 4、如果特意针对手机端要怎么做
40 |
41 | 5、如果自动化实施
42 |
43 | 6、有对 Linux 系统做安全测试
44 |
45 | 7、自动化经验主要集中在哪一块
46 |
47 | 8、哪一块做得比较好的,是有可扩展性
48 |
49 | 9、了解过框架的源码,工作原理
50 |
51 | 10、网站是怎么做的,具体讲一下
52 |
53 | 11、硬件开发的经历
54 |
55 | 12、安全方面的自动化流程,相关的业务介绍
56 |
57 | 13、做的工具在安全测试那一套
58 |
59 | 14、这套自动化逻辑应该放到哪个阶段去用,效率最大化,价值体现
60 |
61 | 15、按想法,自动化框架,会做成什么样子
62 |
63 | 16、安全测试部门,主要内容
64 |
65 | 17、自动化测试工程师要什么阶段接入
66 |
67 | 18、现在行业现状,测试都是什么阶段接入,最好应该是什么接入
68 |
69 | 19、系统测试,内容,正常来说会不会有大量的自动化接入,再开放到系统测试,也会有测试工程师,自动化工程师
70 |
71 | 20、个人的规划是怎么样的
72 |
73 | 21、理解的测试开发是做什么的
74 |
75 | 22、自动化生成自动化案例的方法
76 |
77 | 23、前端测试,UI 的稳定性是怎么保证,维护成本
78 |
79 | 24、WEB 端和手机 APP,兼容性怎么保证的,遍历测试,弹窗
80 |
81 | 25、怎么保证自动化流程能够跑通,自动化的维护成本
82 |
83 | 26、有没有好的方法
84 |
85 | 27、异常弹窗,正常提示,系统测试
86 |
87 | 28、迁移工作量
88 |
89 | 29、测微信、QQ,突然有个异常弹窗,大量的处理这种场景,处理这些异常的东西
90 |
91 | 30、自动化,脚本执行的成功率,跑的效果达不到预期
92 |
93 | 31、前沿的测试领域有什么可以发挥的地方
94 |
95 | 32、短期内,进来的话期望的工作,具体一点
96 |
97 | 33、有什么其它问题
98 |
99 | 34、airtest 是基于谷歌原生的测试框架做的
100 |
101 | 35、进来之后的工作内容
102 |
103 | 36、对工作状态,不断换新项目
104 |
105 | 37、离职原因
106 |
107 | 38、下一份工作的期待
108 |
109 | 39、对加班怎么看
110 |
111 | 40、大学的大部分时间都处理自己的事情,加班是处理公司的事情,会占用个人的时间,怎么看?
112 |
113 | 41、996 怎么看
114 | ```
--------------------------------------------------------------------------------
/安全测试开发相关面试/测试开发类面试参考2.md:
--------------------------------------------------------------------------------
1 | # Q&A
2 |
3 | ```shell
4 | 1、电话面试介绍
5 |
6 | 2、除 Python 外其他语言的情况
7 |
8 | 3、测试开发分前端、后台,后台用的 node.js
9 |
10 | 4、讲一下项目的测试,以及内容介绍
11 |
12 | 5、并发上的改动
13 |
14 | 6、网站,单元测试覆盖率,80%,觉得这个覆盖率够不够
15 |
16 | 7、假设,测试开发的项目,哈希碰撞,测不到的分支,测不到的,这种问题,要怎么处理
17 |
18 | 8、C++ 的程序,类里面的私有函数,对外的接口只有 public 公有函数,私有函数 mock 不到的
19 |
20 | 9、不是简单的哈希碰撞还是特有格式哈希碰撞
21 |
22 | 10、代码实在覆盖不到的,想什么办法去保证这个正确
23 |
24 | 11、大概的规划
25 |
26 | 12、2 月份离职
27 |
28 | 13、语言学习需要多久
29 |
30 | 14、C++、Java、node.js、Python
31 |
32 | 15、管家,更喜欢什么项目一些
33 |
34 | 16、测试开发,30% 做业务的测试,70% 时间做工具开发,项目紧急可能会在业务上多做一些
35 |
36 | 17、不做业务的话不知道用什么工具去优化测试效率
37 |
38 | ```
--------------------------------------------------------------------------------
/安全测试开发相关面试/测试开发类面试参考3.md:
--------------------------------------------------------------------------------
1 | # Q&A
2 |
3 | ## 笔试题
4 |
5 | ## 一面
6 |
7 | ```shell
8 | 1、住在哪边
9 |
10 | 2、做下自我介绍
11 |
12 | 3、离开上家的原因
13 |
14 | 4、做项目自动化,详细说一下
15 |
16 | 5、多个环境切换着跑
17 |
18 | 6、不同的系统之间,怎么切换
19 |
20 | 7、淘宝下单,提交,整个流程路径如何覆盖测试,多个系统测试怎么想
21 |
22 | 8、UI 层的测试
23 |
24 | 9、硬件这块,如何去断言的
25 |
26 | 10、selenium 框架,定位元素,有没有其他方法
27 |
28 | 11、Selenium 截图(get_screenshot_as_file)、ActionChains、wait_for_element_with_id
29 |
30 | 12、断言函数,True、Contains、None、Equal、TemplateUsed
31 |
32 | 13、自动化测试案例的管理框架
33 |
34 | 14、最后自动化测试报告的形式
35 |
36 | 15、自动化框架的优缺点
37 |
38 | 16、接口自动化测试
39 |
40 | 17、接口的测试,接触过哪些协议
41 |
42 | 18、接口,加密测试,登录,加密接口测试,自动化测试
43 |
44 | 19、加密,二次处理
45 |
46 | 20、Python 考点有哪些
47 |
48 | 21、安卓相关的接触
49 |
50 | 22、下份工作的规划
51 |
52 | 23、测试领域,具体一点
53 |
54 | 24、黑盒测试
55 |
56 | 25、自动化项目的人员情况
57 |
58 | 26、有没有什么想问的
59 |
60 | ```
61 |
62 | ## 二面
63 |
64 | ```shell
65 | 1、自我介绍
66 |
67 | 2、测试领域指的是什么
68 |
69 | 3、自动化测试框架都是自己搭建的吗
70 |
71 | 4、自动化引擎具体说明一下
72 |
73 | 5、举一些攻击的场景
74 |
75 | 6、智能家居,安全攻击
76 |
77 | 7、做安全测试的经验比较多,功能性测试能做吗
78 |
79 | 8、创新指的是什么
80 |
81 | 9、有什么要问的
82 |
83 | 10、为什么不读研
84 |
85 | ```
86 |
87 | ## 三面
88 |
89 | ```shell
90 | 1、做过自动化测试的项目,自动化测试的框架,描述一下
91 |
92 | 2、什么叫数据驱动
93 |
94 | 3、数据驱动和关键字驱动的区别
95 |
96 | 4、关键字驱动怎么实现
97 |
98 | 5、由关键字找函数
99 |
100 | 6、如果没有 Python 的字典,字典的底层,怎么实现
101 |
102 | 7、哈希表的原理
103 |
104 | 8、结构体怎么存
105 |
106 | 9、除了哈希表,怎么实现字典
107 |
108 | 10、举例来说,什么时候用关键字的模式,什么时候用数据驱动的模式
109 |
110 | 11、概要设计,怎么设计框架
111 |
112 | 12、同一个行为,实现不同,怎么做
113 |
114 | 13、安全测试的例子
115 |
116 | 14、系统有什么安全问题,怎么发现,内网渗透流程
117 |
118 | 15、密码学了解多少
119 |
120 | 16、C 语言掌握怎么样
121 |
122 | 17、自己的兴趣,倾向
123 |
124 | 18、开发和测试之间的倾向
125 |
126 | ```
127 |
128 | ## HR 面
129 |
130 | ```shell
131 | 1、跟面试官讨论的规划如何
132 |
133 | 2、从哪里过来的
134 |
135 | 3、专业
136 |
137 | 4、离职原因
138 |
139 | 5、同班的有多少
140 |
141 | 6、上一家公司呆的哪些部门
142 |
143 | 7、职称评定
144 |
145 | 8、做得好是因为什么
146 |
147 | 9、看公司,哪些维度排序
148 |
149 | 10、智能家居有前景
150 |
151 | 11、待遇这块,需要个参考标准
152 |
153 | 12、想问的
154 |
155 | ```
--------------------------------------------------------------------------------
/安全测试开发相关面试/测试类HR面参考.md:
--------------------------------------------------------------------------------
1 | # Q&A
2 |
3 | ```shell
4 | 1、做自我介绍
5 |
6 | 2、离职的原因
7 |
8 | 3、对工作的规划与期待
9 |
10 | 4、测试,长期规划
11 |
12 | 5、工作与生活的时间
13 |
14 | 6、工作强度,手机厂商竞争激烈,能不能接受,怎么看待
15 |
16 | 7、加班费,体现在月薪、年薪里
17 |
18 | 8、有其他的 Offer
19 |
20 | 9、为什么对本公司比较感兴趣
21 |
22 | 10、目前用的什么手机
23 |
24 | 11、过往的工作经历,最有成就感
25 |
26 | 12、做了 17 个项目
27 |
28 | 13、为什么能够比较快的产生价值,原因
29 |
30 | 14、工作过程,挫败感很强
31 |
32 | 15、能力长板短板
33 |
34 | 16、工作过程中的困难有没有遇到过
35 |
36 | 17、压力非常大
37 |
38 | 18、过往有没有经历过没有做好的,对自己有过怀疑,不自信的
39 |
40 | 19、用三个词来形容一下自己
41 |
42 | 20、涉猎广,深度不够,怎么改善
43 |
44 | 21、领导怎么评价
45 |
46 | 22、同事怎么评价
47 |
48 | 23、最大的优点,最大的缺点
49 |
50 | 24、做好测试需要哪些因素
51 |
52 | 25、目前,薪资情况
53 |
54 | 26、找工作的薪资需求,自己满意的薪资情况
55 |
56 | 27、做测试工作的过程,有产品要上市了,前一天或者前一周突然发现了一个很大的漏洞和 BUG
57 |
58 | 28、家里情况,回去的情况
59 |
60 | 29、怎么看待给的岗位
61 |
62 | 30、会考虑哪些方面,了解的维度
63 |
64 | 31、有没有什么问题要问的
65 |
66 | ```
--------------------------------------------------------------------------------
/安全测试开发相关面试/测试类综合面试参考.md:
--------------------------------------------------------------------------------
1 | # Q&A
2 |
3 | ```shell
4 | 1、具体什么原因从上家离职
5 |
6 | 2、16 年就开始工作了吗
7 |
8 | 3、分享下家庭的情况
9 |
10 | 4、老家在哪里
11 |
12 | 5、父母在深圳还是在哪
13 |
14 | 6、自动化测试的经历讲一下
15 |
16 | 7、手机端相关的经验
17 |
18 | 8、最大的优势
19 |
20 | 9、对安全比较感兴趣
21 |
22 | 10、性格
23 |
24 | 11、...声音太小了
25 | ```
--------------------------------------------------------------------------------
/深信服_sangfor_相关/readme.md:
--------------------------------------------------------------------------------
1 | # 深信服
2 |
3 | 主要是自己在深信服工作期间接触到的知识点整理
4 |
5 | ## 清单
6 |
7 | * 软件测试面试题【作为面试官,拿到的部分问题】
8 | * 比赛的题目【智安全杯、acm 之类的,部分题目】
9 | * 期间整理的培训学习资料啥
10 |
11 | ## 备注
12 |
13 | 由于安全性考虑,部分涉密的,需要过滤一下
--------------------------------------------------------------------------------
/深信服_sangfor_相关/sangfor_acm_oj/2016_12_03/A.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8 #默认编码格式为utf-8
2 | import sys
3 |
4 | def solve(question_list, t):
5 | sum_all = 0
6 | for each in question_list:
7 | p, s = each.split(" ")
8 | if s == "0":
9 | # no
10 | sum_all += int(p) * 2
11 | else:
12 | sum_all += int(p) * t
13 |
14 | print("{}".format(sum_all))
15 |
16 |
17 | if __name__ == "__main__":
18 | with open("test_A.txt", "r") as f:
19 | sys.stdin = f
20 |
21 | while True:
22 | try:
23 | n = input()
24 | if n == 0:
25 | break
26 | else:
27 | question = list()
28 | for i in range(n):
29 | question.append(raw_input().strip())
30 | t = input()
31 | solve(question, t)
32 | except EOFError:
33 | break
34 |
--------------------------------------------------------------------------------
/深信服_sangfor_相关/sangfor_acm_oj/2016_12_03/C.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import sys
3 |
4 | def change_hour(hour, limit):
5 | hour = str(hour)
6 |
7 | if limit == 12:
8 | # 改变 0
9 | for each in range(0, 10):
10 | try_change = "{}{}".format(each, hour[1])
11 | if 1 <= int(try_change) <= limit:
12 | return try_change
13 |
14 | # 改变 1
15 | for each in range(1, 10):
16 | try_change = "{}{}".format(hour[0], each)
17 | if 1 <= int(try_change) <= limit:
18 | return try_change
19 | else:
20 | # 改变 0
21 | for each in range(0, 10):
22 | try_change = "{}{}".format(each, hour[1])
23 | if 0 <= int(try_change) < limit:
24 | return try_change
25 |
26 | # 改变 1
27 | for each in range(0, 10):
28 | try_change = "{}{}".format(hour[0], each)
29 | if 0 <= int(try_change) < limit:
30 | return try_change
31 |
32 |
33 | def change_minute(hour, minute, limit):
34 | minute = str(minute)
35 | # minute < 59
36 | # 改变 0
37 | for each in range(0, 10):
38 | try_change = "{}{}".format(each, minute[1])
39 | if 0 <= int(try_change) <= 59:
40 | return try_change
41 |
42 | # 改变 1
43 | for each in range(0, 10):
44 | try_change = "{}{}".format(minute[0], each)
45 | if 0 <= int(try_change) <= 59:
46 | return try_change
47 |
48 |
49 | def deal_24(time):
50 | hour, minute = time.split(":")
51 | hour, minute = int(hour), int(minute)
52 |
53 | if hour < 24 and minute > 59:
54 | minute = change_minute(hour, minute, 24)
55 | elif hour < 24 and minute == 59:
56 | pass
57 | elif hour < 24 and minute < 59:
58 | pass
59 | elif hour == 24 and minute > 59:
60 | hour = 23
61 | minute = change_minute(hour, minute, 24)
62 | elif hour == 24 and 0 <= minute <= 59:
63 | hour = 23
64 | elif hour > 24 and minute > 59:
65 | hour = change_hour(hour, 24)
66 | minute = change_minute(hour, minute, 24)
67 | elif hour > 24 and minute <= 59:
68 | hour = change_hour(hour, 24)
69 |
70 | return "{}:{}".format(str(hour).zfill(2), str(minute).zfill(2))
71 |
72 |
73 | def deal_12(time):
74 | hour, minute = time.split(":")
75 | hour, minute = int(hour), int(minute)
76 |
77 | if hour == 0 and minute > 59:
78 | hour = 1
79 | minute = change_minute(hour, minute, 12)
80 | elif hour == 0 and minute == 59:
81 | hour = 1
82 | elif hour == 0 and minute < 59:
83 | hour = 1
84 | elif 0 < hour <= 12 and minute > 59:
85 | minute = change_minute(hour, minute, 12)
86 | elif 0 < hour <= 12 and minute == 59:
87 | pass
88 | elif 0 < hour <= 12 and minute < 59:
89 | pass
90 | elif hour == 13 and minute > 59:
91 | hour = 12
92 | minute = change_minute(hour, minute, 12)
93 | elif hour == 13 and 0 <= minute <= 59:
94 | hour = 12
95 | elif hour > 13 and minute > 59:
96 | hour = change_hour(hour, 12)
97 | minute = change_minute(hour, minute, 12)
98 | elif hour > 13 and minute <= 59:
99 | hour = change_hour(hour, 12)
100 |
101 | return "{}:{}".format(str(hour).zfill(2), str(minute).zfill(2))
102 |
103 |
104 | def solve(n, time):
105 | if n == 24:
106 | return deal_24(time)
107 | else:
108 | return deal_12(time)
109 |
110 |
111 | if __name__ == "__main__":
112 | with open("test_C.txt", "r") as f:
113 | sys.stdin = f
114 |
115 | with open("test_C_answer.txt", "w") as f1:
116 | while True:
117 | try:
118 | n = int(input())
119 | # n = input()
120 | # time = raw_input()
121 | time = input()
122 | # print(solve(n, time))
123 | print("{}小时,原来={},自己的答案={}".format(n, time, solve(n, time)), file=f1)
124 | except EOFError:
125 | break
126 |
--------------------------------------------------------------------------------
/深信服_sangfor_相关/sangfor_acm_oj/2016_12_03/C_ACM/out(2).zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/L1nwatch/interview_collect/a3ec3f4bf57099cbd6acf9ba4e9797e685d5a4ce/深信服_sangfor_相关/sangfor_acm_oj/2016_12_03/C_ACM/out(2).zip
--------------------------------------------------------------------------------
/深信服_sangfor_相关/sangfor_acm_oj/2016_12_03/C_ACM/right_C_answer.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/L1nwatch/interview_collect/a3ec3f4bf57099cbd6acf9ba4e9797e685d5a4ce/深信服_sangfor_相关/sangfor_acm_oj/2016_12_03/C_ACM/right_C_answer.zip
--------------------------------------------------------------------------------
/深信服_sangfor_相关/sangfor_acm_oj/2016_12_03/C_ACM/sxf.cpp:
--------------------------------------------------------------------------------
1 | //题目描述
2 | //火星探险队到了一个洞穴,里面有一座桥,由石板铺就,石板上面有大写英文字母,经探索发现,只有
3 | //
4 | //标有元音字母A,E,I,O,U,Y的字母的石板是安全的,其它石板都会翻动。
5 | //
6 | //只有从桥左边位置走到桥右边位置才能算脱险。对于不是连续元音的石板,只能采用跳过去的方法。
7 | //
8 | //如下石板桥
9 | //
10 | //
11 | //
12 | //如果跳跃能力达不到4个格是无法穿越石板桥的。
13 | //
14 | //帮忙算一下探险队要安全脱险的最小跳跃能力是多少。
15 | //
16 | //输入
17 | //一个字符串只有大写英文字母。
18 | //
19 | //长度最大为100
20 | //
21 | //输出
22 | //一个整数,代表最小的跳跃能力。
23 | //样例输入
24 | //ABABBBACFEYUKOTT
25 | //AAA
26 | //样例输出
27 | //4
28 | //1
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include