├── .gitignore ├── Makefile ├── README.md ├── codes ├── c02 │ ├── p01_all_is_object.py │ └── p02_type_object_class.py ├── c03 │ ├── p01_magic_fun.py │ └── p03_magic_overview.py ├── c04 │ ├── p01_duct_polymorphism.py │ ├── p02_abstract_base_class.py │ ├── p03_isinstance_type.py │ ├── p04_class_variable.py │ ├── p05_attr_mro.py │ ├── p06_class_method.py │ ├── p07_private_method.py │ ├── p08_self_ex.py │ └── p09_super.py ├── c05 │ ├── p01_sequeue_type.py │ ├── p02_collections_abc.py │ ├── p03_list_extend.py │ ├── p04_implement_sliencable.py │ ├── p04_slice_object.py │ ├── p05_bisect.py │ ├── p06_altertive_to_list.py │ └── p07_comprehension.py ├── c06 │ ├── p01_mapping_type.py │ ├── p02_dict_methods.py │ ├── p03_dict_subclass.py │ └── p04_set_frozenset.py ├── c07 │ ├── p01_python_variable.py │ ├── p02_is_equal.py │ ├── p03_del.py │ ├── p04_argument_error.py │ └── p04_argument_error01.py ├── c08 │ ├── p01_property.py │ ├── p02_getattr_getattritute.py │ ├── p03_descriptor.py │ ├── p03_descriptor02.py │ ├── p04_new_init.py │ ├── p05_metaclass.py │ ├── p05_metaclass02.py │ └── p06_orm.py └── c09 │ ├── input │ ├── p01_iter_protocol.py │ ├── p02_iterator_iterable.py │ ├── p03_generator.py │ ├── p03_generator02.py │ ├── p04_build_generator.py │ ├── p04_build_generator02.py │ ├── p05_userlist_generator.py │ └── p06_generator_file.py ├── make.bat └── source ├── aboutme.rst ├── c01 └── p01_introduce.rst ├── c02 ├── p01_all_is_object.rst ├── p02_type_object_class.rst ├── p03_builtin_types.rst ├── p04_conclusion.rst └── type-object-class.jpg ├── c03 ├── p01_magic_func.rst ├── p02_data_model.rst ├── p03_magic_overview.rst ├── p04_func_len.rst └── p05_conclusion.rst ├── c04 ├── mro1.jpg ├── mro2.jpg ├── p01_duct_polymorphism.rst ├── p02_abstract_base_class.rst ├── p03_isinstance_type.rst ├── p04_class_variable.rst ├── p05_attr_method.rst ├── p06_class_method.rst ├── p07_private_method.rst ├── p08_private_method.rst └── p09_super.rst ├── c05 ├── p01_sequeue_type.rst ├── p02_collections_abc.rst ├── p03_list_extend.rst ├── p04_implement_sliencable.rst ├── p05_bisect.rst ├── p06_altertive_to_list.rst ├── p07_comprehension.rst └── p08_conclusion.rst ├── c06 ├── p01_mapping_type.rst ├── p02_dict_methods.rst ├── p03_dict_subclass.rst ├── p04_set_frozenset.rst ├── p05_dict_set_principle.rst └── p06_conclusion.rst ├── c07 ├── p01_python_variable.rst ├── p02_is_equal.rst ├── p03_del.rst ├── p04_argument_error.rst └── p05_conclusion.rst ├── c08 ├── p01_property.rst ├── p02_getattr_getattritute.rst ├── p03_descriptor.rst ├── p04_new_init.rst ├── p05_metaclass.rst ├── p06_orm.rst └── p07_conclusion.rst ├── c09 ├── function.jpg ├── generator.jpg ├── p01_iter_protocol.rst ├── p02_iterator_iterable.rst ├── p03_generator.rst ├── p04_build_generator.rst ├── p05_userlist_generator.rst ├── p06_generator_file.rst └── p07_conclusion.rst ├── chapters ├── p01_introduce.rst ├── p02_all_is_object.rst ├── p03_magic_function.rst ├── p04_class_object.rst ├── p05_sequeue_class.rst ├── p06_dict_and_set.rst ├── p07_reference_del.rst ├── p08_meta_class.rst └── p09_iterator_generator.rst ├── conf.py ├── index.rst └── roadmap.rst /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # IPython Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | venv/ 83 | ENV/ 84 | 85 | # Spyder project settings 86 | .spyderproject 87 | 88 | # Rope project settings 89 | .ropeproject 90 | .pytest_cache 91 | 92 | .idea/ 93 | 94 | .DS_Store 95 | 96 | services.json 97 | 98 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Python 高级编程 4 | 5 | - /codes 源码目录 6 | - /source 笔记目录 7 | 8 | 欢迎访问笔记网站 https://advance-python.readthedocs.io 9 | -------------------------------------------------------------------------------- /codes/c02/p01_all_is_object.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | def bar(name): 5 | print('Hello %s' % name) 6 | 7 | 8 | class Person(object): 9 | def __init__(self, name): 10 | print('Hello %s' % name) 11 | 12 | 13 | def decorator_func(): 14 | print('from decorator_func') 15 | return bar 16 | 17 | 18 | def print_type(obj): 19 | print(type(obj)) 20 | 21 | 22 | # 赋值给一个变量 23 | func = bar 24 | func('Linda') 25 | my_class = Person 26 | my_class('Tom') 27 | 28 | 29 | # 可以添加到集合对象中 30 | obj_list = list() 31 | obj_list.append(bar) 32 | obj_list.append(Person) 33 | for item in obj_list: 34 | print_type(item) 35 | # 可以作为参数传递给函数 36 | 37 | # 可以当做函数的返回值 38 | deco_bar = decorator_func() 39 | deco_bar('deco_bar') 40 | -------------------------------------------------------------------------------- /codes/c02/p02_type_object_class.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | num = 1 4 | name = 'linda' 5 | print(type(num)) 6 | print(type(int)) 7 | print(type(name)) 8 | print(type(str)) 9 | 10 | # type -> int -> 1 11 | # type -> str -> 'linda' 12 | # type -> Student -> stu 13 | # so: type -> class -> obj 14 | 15 | 16 | class Student: 17 | pass 18 | 19 | 20 | class MyStudent(Student): 21 | pass 22 | 23 | 24 | # object 是最顶层基类 25 | # type 是一个类,同时 type 也是一个对象 26 | 27 | stu = Student() 28 | print(type(stu)) 29 | print(type(Student)) 30 | 31 | print(int.__bases__) 32 | print(str.__bases__) 33 | print(Student.__bases__) 34 | print(MyStudent.__bases__) 35 | 36 | print(type.__bases__) # (,) 37 | print(object.__bases__) # () 最顶层基类,即没有基类 38 | 39 | print(type(object)) # 40 | -------------------------------------------------------------------------------- /codes/c03/p01_magic_fun.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | class Company: 5 | def __init__(self, employee_list): 6 | self.employee = employee_list 7 | 8 | def __getitem__(self, index): 9 | return self.employee[index] 10 | 11 | 12 | company = Company(['alex', 'linda', 'catherine']) 13 | employee = company.employee 14 | 15 | for item in employee: 16 | print(item) 17 | 18 | # for 首先去找 __iter__, 没有时优化去找__getitem__ 19 | for item in company: 20 | print(item) 21 | -------------------------------------------------------------------------------- /codes/c03/p03_magic_overview.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | class Company: 5 | def __init__(self, name): 6 | self.name = name 7 | 8 | def __str__(self): 9 | return '' % self.name 10 | 11 | def __repr__(self): 12 | return '' % self.name 13 | 14 | 15 | company = Company('Apple') 16 | print(company) 17 | 18 | # Python 解释器会隐含调用 19 | print(company.__repr__()) 20 | 21 | 22 | class Num: 23 | def __init__(self, num): 24 | self.num = num 25 | 26 | def __abs__(self): 27 | return abs(self.num) 28 | 29 | 30 | n = Num(-1) 31 | print(abs(n)) 32 | 33 | 34 | class Vector: 35 | def __init__(self, x, y): 36 | self.x = x 37 | self.y = y 38 | 39 | def __add__(self, other): 40 | return Vector(self.x + other.x, self.y + other.y) 41 | 42 | def __str__(self): 43 | return 'Vector(%s, %s)' % (self.x, self.y) 44 | 45 | 46 | v1 = Vector(1, 3) 47 | v2 = Vector(2, 4) 48 | print(v1 + v2) 49 | -------------------------------------------------------------------------------- /codes/c04/p01_duct_polymorphism.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | class Cat: 5 | def say(self): 6 | print('I am a cat.') 7 | 8 | 9 | class Dog: 10 | def say(self): 11 | print('I am a dog.') 12 | 13 | 14 | class Duck: 15 | def say(self): 16 | print('I am a duck.') 17 | 18 | 19 | # Python中较灵活,只要实现say方法就行,实现了多态 20 | animal = Cat 21 | animal().say() 22 | 23 | # 实现多态只要定义了相同方法即可 24 | animal_list = [Cat, Dog, Duck] 25 | for an in animal_list: 26 | an().say() 27 | 28 | """ 29 | class Animal: 30 | def say(self): 31 | print('I am a animal.') 32 | 33 | # 需要继承Animal,并重写say方法 34 | class Cat(Animal): 35 | def say(self): 36 | print('I am a cat.') 37 | 38 | # Java 中定义需要指定类型 39 | Animal an = new Cat() 40 | an.say() 41 | """ 42 | 43 | li1 = ['i1', 'i2'] 44 | li2 = ['i3', 'i4'] 45 | 46 | tu = ('i5', 'i6') 47 | s1 = set() 48 | s1.add('i7') 49 | s1.add('i8') 50 | 51 | # 转变观念,传入的不单单是list,甚至自己实现 iterable 对象 52 | li1.extend(li2) # iterable 53 | li1.extend(tu) 54 | li1.extend(s1) 55 | print(li1) 56 | 57 | -------------------------------------------------------------------------------- /codes/c04/p02_abstract_base_class.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | # 场景一:检查某个类是否有某种方法 5 | class Company: 6 | def __init__(self, name): 7 | self.name = name 8 | 9 | def __len__(self): 10 | return len(self.name) 11 | 12 | 13 | company = Company('Linda Process Ltd.') 14 | print(hasattr(company, '__len__')) 15 | 16 | # 某些情况下,想判断某个对象的类型 17 | from collections.abc import Sized 18 | print(isinstance(company, Sized)) 19 | 20 | 21 | # 场景二:强制子类必须实现某些方法 22 | class CacheBase: 23 | def get(self, key): 24 | raise NotImplementedError 25 | 26 | def set(self, key, value): 27 | raise NotImplementedError 28 | 29 | 30 | class RedisCache(CacheBase): 31 | pass 32 | 33 | 34 | # 只有调用的时候才抛异常 35 | redis = RedisCache() 36 | # redis.get('key') 37 | 38 | 39 | import abc 40 | 41 | 42 | class CacheBase(metaclass=abc.ABCMeta): 43 | 44 | @abc.abstractmethod 45 | def get(self, key): 46 | pass 47 | 48 | @abc.abstractmethod 49 | def set(self, key, value): 50 | pass 51 | 52 | 53 | class MemoryCache(CacheBase): 54 | pass 55 | 56 | 57 | # 初始化时就抛异常 58 | memory = MemoryCache() -------------------------------------------------------------------------------- /codes/c04/p03_isinstance_type.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | class A: 5 | pass 6 | 7 | 8 | class B(A): 9 | pass 10 | 11 | 12 | b = B() 13 | 14 | print(isinstance(b, B)) 15 | print(isinstance(b, A)) 16 | 17 | # is 判断 id 的意思 18 | print(type(b) is B) 19 | print(type(b) is A) # False 20 | -------------------------------------------------------------------------------- /codes/c04/p04_class_variable.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | class A: 5 | aa = 1 6 | 7 | def __init__(self, x, y): 8 | self.x = x 9 | self.y = y 10 | 11 | 12 | a = A(2, 3) 13 | print(a.x, a.y, A.aa) 14 | 15 | A.aa = 111 16 | a.aa = 100 # 新建一个a的属性aa, 100赋值给该aa 17 | print(A.aa, a.aa) 18 | -------------------------------------------------------------------------------- /codes/c04/p05_attr_mro.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | # class A: 5 | # name = 'linda' 6 | # 7 | # def __init__(self): 8 | # self.name = 'object' 9 | # 10 | # 11 | # a = A() 12 | # print(a.name) 13 | 14 | # class D: 15 | # pass 16 | # 17 | # 18 | # class C(D): 19 | # pass 20 | # 21 | # 22 | # class B(D): 23 | # pass 24 | # 25 | # 26 | # class A(B, C): 27 | # pass 28 | # 29 | # 30 | # print(A.__mro__) 31 | 32 | class D: 33 | pass 34 | 35 | 36 | class E: 37 | pass 38 | 39 | 40 | class C(E): 41 | pass 42 | 43 | 44 | class B(D): 45 | pass 46 | 47 | 48 | class A(B, C): 49 | pass 50 | 51 | 52 | print(A.__mro__) 53 | -------------------------------------------------------------------------------- /codes/c04/p06_class_method.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | class Date: 5 | def __init__(self, year, month, day): 6 | self.year = year 7 | self.month = month 8 | self.day = day 9 | 10 | def tomorrow(self): 11 | self.day += 1 12 | 13 | @staticmethod 14 | def date_from_str(date_str): 15 | year, month, day = tuple(date_str.split('-')) 16 | return Date(int(year), int(month), int(day)) 17 | 18 | @classmethod 19 | def date_from_string(cls, date_str): 20 | year, month, day = tuple(date_str.split('-')) 21 | return cls(int(year), int(month), int(day)) 22 | 23 | def __str__(self): 24 | return '{year}/{month}/{day}'.format(year=self.year, month=self.month, day=self.day) 25 | 26 | 27 | if __name__ == '__main__': 28 | new_day = Date(2020, 2, 20) 29 | new_day.tomorrow() 30 | print(new_day) 31 | 32 | date_str = '2020-12-12' 33 | print(Date.date_from_str(date_str)) 34 | print(Date.date_from_string(date_str)) -------------------------------------------------------------------------------- /codes/c04/p07_private_method.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | class User: 5 | def __init__(self): 6 | self.__age = 18 7 | 8 | def get_age(self): 9 | return self.__age 10 | 11 | 12 | if __name__ == '__main__': 13 | user = User() 14 | print(user.get_age()) 15 | 16 | # print(user.__age) 17 | 18 | # _class__attr, 做了变形 19 | print(user._User__age) 20 | -------------------------------------------------------------------------------- /codes/c04/p08_self_ex.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # 通过一定的机制查询对象的内部结构 4 | 5 | 6 | class User: 7 | name = 'user' 8 | 9 | 10 | class Student(User): 11 | def __init__(self): 12 | self.school_name = 'school' 13 | 14 | 15 | if __name__ == '__main__': 16 | stu = Student() 17 | 18 | # 通过__dict__ 查询属性, C语言实现,经过优化,较快 19 | print(stu.__dict__) 20 | stu.__dict__['age'] = 18 21 | print(stu.age) 22 | 23 | print(User.__dict__) 24 | 25 | print(dir(stu)) -------------------------------------------------------------------------------- /codes/c04/p09_super.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | -------------------------------------------------------------------------------- /codes/c05/p01_sequeue_type.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # 元素类型任意 4 | my_list = list() 5 | my_list.append(100) 6 | my_list.append(True) 7 | -------------------------------------------------------------------------------- /codes/c05/p02_collections_abc.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from collections import abc 4 | -------------------------------------------------------------------------------- /codes/c05/p03_list_extend.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # + 加新增 4 | l1 = [1, 2] 5 | l2 = l1 + [3, 4] 6 | print("type(l1): %d, and l1: %s" % (id(l1), l1)) 7 | print("type(l2): %d, and l2: %s" % (id(l2), l2)) 8 | 9 | # += 就地加 10 | l1 += ['3', '4'] 11 | l1 += ('5', '6') 12 | l1 += range(2) 13 | print("type(l1): %d, and l1: %s" % (id(l1), l1)) 14 | 15 | 16 | # + 两边类型需相同 17 | # += 只需要可迭代的就行,__iadd__ 魔法函数实现 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /codes/c05/p04_implement_sliencable.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | ''' 4 | 模式 [start:end:step] 5 | 6 | 第一个数字 start 表示切片开始位置,默认 0 7 | 第二个数字 end 表示切片截止(但不包含)位置,默认列表长度 8 | 第三个数字 step 表示切片的步骤,默认为 1 9 | 10 | 当 start 为 0 时可以省略 11 | 当 end 为列表长度时可以省略 12 | 当 step 为 1 时可以省略,并且省略步长时可以同时省略最后一个冒号 13 | 当 step 为负数时,表示反向切片,这时 start 应该比 end 的值要大才行 14 | ''' 15 | 16 | a_list = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17] 17 | a_list[::] # 返回包含原列表中所有元素的新列表 18 | a_list[::-1] # 返回包含原列表中所有元素的逆向新列表 19 | a_list[::2] # 隔一个元素取一个,获取偶数位置的元素 20 | a_list[1::2] # 隔一个元素取一个,获取奇数位置的元素 21 | a_list[3:6] # 指定切片的开始和结束位置 22 | a_list[0:100] # 切片结束位置大于列表长度是,从列表尾部截断 23 | a_list[100:] # 切片开始位置大于列表长度时,返回空列表 24 | 25 | a_list[len(a_list):0] = [9] # 在列表尾部增加元素 26 | a_list[:0] = [1, 2] # 在列表头部增加元素 27 | a_list[3:3] = [100] # 在列表中间位置插入元素 28 | a_list[:2] = [100, 200] # 替换列表元素,等号两边长度相等 29 | a_list[3:] = [4, 5, 6] # 替换列表元素,等号两边长度可以不相等 30 | a_list[:3] = [] # 删除列表中前 3 个元素 31 | 32 | print(a_list) 33 | -------------------------------------------------------------------------------- /codes/c05/p04_slice_object.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | """ 3 | 自定义序列对象 4 | """ 5 | 6 | import numbers 7 | 8 | 9 | class Group: 10 | def __init__(self, group_name, company_name, staff): 11 | self.group_name = group_name 12 | self.company_name = company_name 13 | self.staffs = staff 14 | 15 | def __reversed__(self): 16 | self.staffs.reverse() 17 | 18 | def __getitem__(self, item): 19 | cls = type(self) 20 | if isinstance(item, slice): 21 | return cls(group_name=self.group_name, company_name=self.company_name, staff=self.staffs[item]) 22 | elif isinstance(item, numbers.Integral): 23 | return cls(group_name=self.group_name, company_name=self.company_name, staff=[self.staffs[item]]) 24 | 25 | def __len__(self): 26 | return len(self.staffs) 27 | 28 | def __iter__(self): 29 | return iter(self.staffs) 30 | 31 | def __contains__(self, item): 32 | if item in self.staffs: 33 | return True 34 | else: 35 | return False 36 | 37 | 38 | staffs = ['linda', 'alex', 'catherine', 'nash', 'curry'] 39 | group = Group(group_name='group', company_name='company', staff=staffs) 40 | sub_group = group[0] 41 | 42 | print('linda' in sub_group) 43 | print(len(sub_group)) 44 | 45 | -------------------------------------------------------------------------------- /codes/c05/p05_bisect.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | import bisect 4 | 5 | # 处理已排序 序列 升序 6 | # 内部二分查找算法实现 7 | 8 | l1 = list() 9 | bisect.insort(l1, 10) 10 | bisect.insort(l1, 3) 11 | bisect.insort(l1, 2) 12 | bisect.insort(l1, 6) 13 | 14 | print(l1) 15 | -------------------------------------------------------------------------------- /codes/c05/p06_altertive_to_list.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | import array 4 | 5 | my_array = array.array('i') 6 | my_array.append(100) 7 | my_array.append('abc') -------------------------------------------------------------------------------- /codes/c05/p07_comprehension.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # 列表推导式(列表生成式): 通过一行代码生成列表 4 | 5 | # 提取出 1-20 之间的奇数 6 | odd_list = [i for i in range(21) if i % 2 == 1] 7 | print(odd_list) 8 | 9 | # 逻辑复杂的情况 10 | 11 | 12 | def handle_item(item): 13 | return item * item 14 | 15 | 16 | odd_list = [handle_item(i) for i in range(21) if i % 2 == 1] 17 | print(odd_list) 18 | 19 | 20 | # 列表生成式性能高于列表操作 21 | # 逻辑过于复杂时,列表生成式可读性降低 22 | 23 | 24 | # 生成器表达式,[] -> () 25 | my_gen = (i for i in range(21) if i % 2 == 1) 26 | print(type(my_gen)) # 27 | for i in my_gen: 28 | print(i) 29 | 30 | # 字典推到式 31 | d1 = {'key1': 'value1', 'key2': 'value2'} 32 | d2 = {v: k for (k, v) in d1.items()} 33 | print(d2) 34 | 35 | 36 | # 集合推导式 37 | set1 = {v for v in d1.values()} 38 | print(set1) -------------------------------------------------------------------------------- /codes/c06/p01_mapping_type.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from collections.abc import Mapping 4 | 5 | 6 | # dict 属于 Mapping 类型 7 | d = dict() 8 | print(isinstance(d, Mapping)) 9 | -------------------------------------------------------------------------------- /codes/c06/p02_dict_methods.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | d = { 4 | 'linda': {'company': 'Yahoo'}, 5 | 'catherine': {'company': 'Google'} 6 | } 7 | 8 | # 清空 9 | # d.clear() 10 | 11 | # 浅拷贝 12 | new_dict = d.copy() 13 | # 深拷贝 14 | import copy 15 | new_dict_deep = copy.deepcopy(d) 16 | 17 | new_dict['linda']['company'] = 'Ali' 18 | print(d) 19 | print(new_dict) 20 | print(new_dict_deep) 21 | 22 | dd = dict.fromkeys(['key1', 'key2'], 'default') 23 | dd.get('key', None) 24 | dd.keys(), dd.values(), dd.items() 25 | 26 | # 获取key的value, 没有时更新为默认值 27 | print(dd.setdefault('key', 'value')) 28 | dd.update({'name': 'linda'}) 29 | print(dd) 30 | 31 | 32 | -------------------------------------------------------------------------------- /codes/c06/p03_dict_subclass.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | class MyDict(dict): 5 | def __setitem__(self, key, value): 6 | super().__setitem__(key, value * 2) 7 | 8 | 9 | my_dict = MyDict(one=1) 10 | print(my_dict) # 1, 某些情况下,不会调用重写的__setitem__ 11 | my_dict['one'] = 1 12 | print(my_dict) # 2, 触发重写的 __setitem__ 13 | 14 | from collections import UserDict, defaultdict 15 | 16 | 17 | # python 语法模拟 c 语言实现细节 18 | class CustomDict(UserDict): 19 | def __setitem__(self, key, value): 20 | super().__setitem__(key, value * 2) 21 | 22 | 23 | dd = CustomDict(one=1) 24 | print(dd) 25 | 26 | 27 | d1 = UserDict({'kk': 'vv'}, k1='v1') 28 | print(d1) 29 | 30 | d2 = defaultdict(list) 31 | # 实现了 __missing__ 魔法函数,可参考UserDict __getitem__ 实现 32 | value = d2['key'] 33 | print(value) 34 | print(dict(d2)) 35 | -------------------------------------------------------------------------------- /codes/c06/p04_set_frozenset.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # set 不重复、无序 4 | s1 = set('abcc') 5 | print(s1) # {'a', 'c', 'b'} 6 | 7 | # frozenset 不可变可以作为 dict key 8 | f1 = frozenset('abcc') 9 | print(f1) 10 | -------------------------------------------------------------------------------- /codes/c07/p01_python_variable.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # a 贴到 1 上面 4 | a = 1 5 | # a 再贴到 'abc' 上 6 | a = 'abc' 7 | 8 | # 先生成对象,然后贴便利贴 9 | 10 | la = [1, 2, 3] 11 | lb = la 12 | # is, 本质 id(a) 与 id(b) 比较 13 | print(lb is la) 14 | print(id(la), id(lb)) 15 | 16 | la.append(100) 17 | print(lb) 18 | -------------------------------------------------------------------------------- /codes/c07/p02_is_equal.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # is, 本质 id(a) 与 id(b) 比较 4 | # = 右边为对象时,表示生成新对象 5 | a = [1, 2, 3, 4] 6 | b = [1, 2, 3, 4] 7 | print(a is b) # False, 说明 id 不同 8 | print(id(a), id(b)) 9 | print(a == b) # True, 值相同,内部 __eq__ 魔法函数 10 | 11 | # 内部优化 小整数、小字符串 全局唯一 intern机制 12 | a1 = 1 13 | a2 = 1 14 | print(a1 is a2) # True 15 | 16 | s1 = 'abc' 17 | s2 = 'abc' 18 | print(s1 is s2) # True 19 | 20 | 21 | class People: 22 | pass 23 | 24 | 25 | # People 全局唯一 26 | person = People() 27 | print(type(person) is People) # True 28 | 29 | -------------------------------------------------------------------------------- /codes/c07/p03_del.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # python 中垃圾回收算法为 引用计数 4 | 5 | a = 1 6 | b = a 7 | del a 8 | 9 | # del 触发 __del__ 逻辑 10 | 11 | -------------------------------------------------------------------------------- /codes/c07/p04_argument_error.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | def add(a, b): 5 | a += b 6 | return a 7 | 8 | 9 | if __name__ == '__main__': 10 | # a, b = 1, 2 11 | # c = add(a, b) 12 | # print('a: %s, b: %s, c: %s' % (a, b, c)) 13 | 14 | # a, b = [1, 2], [3, 4] 15 | # c = add(a, b) 16 | # print('a: %s, b: %s, c: %s' % (a, b, c)) 17 | 18 | a, b = (1, 2), (3, 4) 19 | c = add(a, b) 20 | print('a: %s, b: %s, c: %s' % (a, b, c)) -------------------------------------------------------------------------------- /codes/c07/p04_argument_error01.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | class Company: 5 | def __init__(self, name, staff_list=[]): 6 | self.name = name 7 | self.staff_list = staff_list 8 | 9 | def add(self, staff): 10 | self.staff_list.append(staff) 11 | 12 | def remove(self, staff): 13 | self.staff_list.remove(staff) 14 | 15 | 16 | if __name__ == '__main__': 17 | com1 = Company('com1', ['staff1', 'staff11']) 18 | com1.add('staff111') 19 | com1.remove('staff11') 20 | print(com1.staff_list) 21 | 22 | com2 = Company('com2') 23 | com2.add('staff2') 24 | 25 | com3 = Company('com3') 26 | com3.add('staff3') 27 | 28 | print(com2.staff_list) # ['staff2', 'staff3'] 29 | print(com3.staff_list) # ['staff2', 'staff3'] 30 | -------------------------------------------------------------------------------- /codes/c08/p01_property.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | from datetime import date 3 | 4 | 5 | class User: 6 | def __init__(self, name, birthday): 7 | self.name = name 8 | self.birthday = birthday 9 | self._age = 0 # _ 一种编程规范 10 | 11 | @property 12 | def age(self): 13 | return date.today().year - self.birthday.year 14 | 15 | @age.setter 16 | def age(self, value): 17 | self._age = value 18 | 19 | def get_age(self): 20 | return self._age 21 | 22 | 23 | if __name__ == '__main__': 24 | user = User('linda', date(1987, 11, 14)) 25 | print(user.age) # @property 用变量的方式去封装逻辑 26 | user.age = 100 # @age.setter 接收参数 27 | print(user.get_age()) # self._age 实例内部有存储的变量 _age 28 | -------------------------------------------------------------------------------- /codes/c08/p02_getattr_getattritute.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # __getattr__, 在查找不到属性的时候调用 4 | 5 | # class User: 6 | # def __init__(self, name): 7 | # self.name = name 8 | # 9 | # def __getattr__(self, item): 10 | # return 'Not found attribute %s' % item 11 | # 12 | # 13 | # if __name__ == '__main__': 14 | # user = User('linda') 15 | # print(user.age) 16 | 17 | 18 | # class User: 19 | # def __init__(self, info=None): 20 | # if not info: 21 | # info = {} 22 | # self.info = info 23 | # 24 | # def __getattr__(self, item): 25 | # return self.info[item] 26 | # 27 | # 28 | # if __name__ == '__main__': 29 | # user = User({'name': 'linda', 'age': 18}) 30 | # print(user.name) 31 | # print(user.age) 32 | 33 | class User: 34 | def __init__(self, name): 35 | self.name = name 36 | 37 | def __getattribute__(self, item): 38 | return 'get_attribute' 39 | 40 | 41 | if __name__ == '__main__': 42 | user = User('linda') 43 | print(user.name) # get_attribute 44 | print(user.test) # get_attribute 45 | print(user.other) # get_attribute 46 | -------------------------------------------------------------------------------- /codes/c08/p03_descriptor.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # property 可以更好低获取和设置,如果大量属性需要执行相同操作,如类型检测,则需要每个属性都要写一遍 4 | # ORM 比较常见 5 | 6 | # 实现了 __get__ 和 __set__ 数据属性描述符 7 | # 只实现了 __get__ 非数据属性描述符 8 | # 查找顺序也不同 9 | 10 | import numbers 11 | 12 | 13 | class IntField: 14 | def __init__(self): 15 | self._data = None 16 | 17 | def __get__(self, instance, owner): 18 | print(instance) # <__main__.User object at 0x000002B88B270288> 19 | print(owner) # 20 | print(type(instance) is owner) # True 21 | print(instance.__class__ is owner) # True 22 | return self._data 23 | 24 | def __set__(self, instance, value): 25 | if not isinstance(value, numbers.Integral): 26 | raise ValueError('Need int value') 27 | # 重点来了,如何保存 value 呢,instance or self 28 | # 如果 instance.attribute 又会触发 __set__ 描述符 29 | self._data = value 30 | 31 | def __delete__(self, instance): 32 | pass 33 | 34 | 35 | class User: 36 | age = IntField() 37 | num = IntField() 38 | 39 | 40 | if __name__ == '__main__': 41 | user = User() 42 | user.age = 18 43 | print(user.__dict__) # {} "age" 并没有进入到 __dict__ 44 | 45 | print(user.age) 46 | -------------------------------------------------------------------------------- /codes/c08/p03_descriptor02.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | """ 3 | user 某个类实例,user.age 等价于 getattr(user, 'age') 4 | 首先调用 __getattribute__ 5 | 如果定义了 __getattr__ 方法,调用 __getattribute__ 抛出异常 AttributeError 触发__getattr__ 6 | 而对于描述符(__get__)的调用,则是发生在 __getattribute__内部 7 | 8 | user = User(), 调用 user.age 顺序如下: 9 | (1) 如果 'age' 是出现在 User 或基类的 __dict__ 中,且 age 是data descriptor,那么调用其 __get__(instance, owner) 方法,否则 10 | (2) 如果 'age' 出现在 user 的 __dict__ 中,那么直接返回 user.__dict__['age'],否则 11 | (3) 如果 'age' 出现在 User 或基类的 __dict__ 中 12 | (3.1) 如果 age 是 non-data descriptor, 那么调用其 __get__ 方法,否则 13 | (3.2) 返回 User.__dict__['age'] 14 | (4) 如果 User 有 __getattr__ 方法,调用 __getattr__ 方法,否则 15 | (5) 抛出异常 AttributeError 16 | 17 | """ 18 | 19 | 20 | class NonDataIntFiled: 21 | def __get__(self, instance, owner): 22 | print(instance) 23 | print(owner) 24 | return 100 25 | 26 | 27 | class User: 28 | age = NonDataIntFiled() 29 | 30 | 31 | if __name__ == '__main__': 32 | user = User() 33 | # user.__dict__['age'] = 18 34 | # user.age = 18 35 | # print(user.__dict__) 36 | print(user.age) 37 | 38 | -------------------------------------------------------------------------------- /codes/c08/p04_new_init.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # __new__ cls: 用来控制对象的生成过程,在对象之前 4 | # __init__ self:用来完善对象,如赋值 5 | 6 | # new 在 init 之前 7 | # 如果 __new__ 方法无返回值,则不会调用 __init__函数 8 | 9 | 10 | class User(object): 11 | 12 | # 新式类才有,生成对象 user 之前加逻辑 13 | def __new__(cls, *args, **kwargs): 14 | print('from __new__') 15 | # self = super().__new__(cls) 16 | self = object.__new__(cls) 17 | return self 18 | 19 | def __init__(self, name, age=18): 20 | self.name = name 21 | self.age = age 22 | print('from __init__') 23 | 24 | 25 | if __name__ == '__main__': 26 | user = User('linda', age=20) 27 | -------------------------------------------------------------------------------- /codes/c08/p05_metaclass.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # 类也是对象,type创建类的类 4 | # 如何不写 class 关键字,更加灵活创建类呢 5 | 6 | # 什么是元类,元类是创建类的类, 对象 <- class(对象) <- type 7 | 8 | 9 | def create_class(name): 10 | 11 | if name == 'user': 12 | class User: 13 | def __str__(self): 14 | return 'User' 15 | return User 16 | 17 | elif name == 'company': 18 | class Company: 19 | def __str__(self): 20 | return 'Company' 21 | return Company 22 | 23 | 24 | def func(self): 25 | return 'I am from func.' 26 | 27 | 28 | class Base: 29 | def answer(self): 30 | return 'I am from Base.answer.' 31 | 32 | 33 | if __name__ == '__main__': 34 | # MyClass = create_class('user') 35 | # obj = MyClass() 36 | # print(obj) 37 | # print(type(obj)) 38 | 39 | # type 动态创建类 40 | User = type('User', (Base, ), {'name': 'user', 'func': func}) 41 | user = User() 42 | print(user.name) 43 | print(user.func()) 44 | print(user.answer()) 45 | print(type(user)) 46 | 47 | -------------------------------------------------------------------------------- /codes/c08/p05_metaclass02.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # 元类创建类的类 metaclass(type) -> class -> instance 4 | 5 | 6 | class MetaClass(type): 7 | # 用来控制 User 的创建过程 与 User 中的 __new__ 有区别 8 | def __new__(cls, name, bases, attrs, **kw): 9 | return super().__new__(cls, name, bases, attrs, **kw) 10 | 11 | 12 | class User(object, metaclass=MetaClass): 13 | 14 | def __init__(self, name): 15 | self.name = name 16 | 17 | def bar(self): 18 | print('from bar.') 19 | 20 | 21 | # python 在实例化的过程 user = User() 22 | # (1) 首先寻找 metaclass,来创建 User,否则 23 | # (2) 再次寻找基类 BaseUser 的 metaclass,来创建 User,否则 24 | # (3) 接着寻找模块 metaclass,来创建 User,否则 25 | # (4) 最后默认 type 为 metaclass 来创建 User 26 | 27 | -------------------------------------------------------------------------------- /codes/c08/p06_orm.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | """ 3 | 明确需求 4 | class User: 5 | name = CharFiled(db_column="", max_length=32) 6 | age = IntFiled(db_column="", min_value=0, max_value=100) 7 | class Meta: 8 | db_table = 'user' 9 | 10 | user = User() 11 | user.name = 'linda' 12 | user.age = 18 13 | user.save() 14 | """ 15 | 16 | from collections import OrderedDict 17 | 18 | 19 | class Field: 20 | pass 21 | 22 | 23 | class IntField(Field): 24 | def __init__(self, db_column, min_value=0, max_value=100): 25 | self.db_column = db_column 26 | self.min_value = min_value 27 | self.max_value = max_value 28 | self._value = None 29 | 30 | def __get__(self, instance, owner): 31 | return self._value 32 | 33 | def __set__(self, instance, value): 34 | if not isinstance(value, int): 35 | raise TypeError('need int value') 36 | if value < self.min_value or value > self.max_value: 37 | raise ValueError('need [%s, %s] value' % (self.min_value, self.max_value)) 38 | self._value = value 39 | 40 | 41 | class CharField(Field): 42 | def __init__(self, db_column, max_length=32): 43 | self.db_column = db_column 44 | self.max_length = max_length 45 | self._value = None 46 | 47 | def __get__(self, instance, owner): 48 | return self._value 49 | 50 | def __set__(self, instance, value): 51 | if not isinstance(value, str): 52 | raise TypeError('need str value') 53 | if len(value) > self.max_length: 54 | raise ValueError('len need lower than %s' % self.max_length) 55 | self._value = value 56 | 57 | 58 | # 元类注入一系列属性 59 | class MetaClass(type): 60 | def __new__(cls, name, bases, attrs, **kw): 61 | # BaseModel 也会调用 Metaclass,但没有定义 name,age 等属性,可特殊判断 62 | if name == 'BaseModel': 63 | return super().__new__(cls, name, bases, attrs, **kw) 64 | 65 | fields = {} 66 | for key, value in attrs.items(): 67 | if isinstance(value, Field): 68 | fields[key] = value 69 | 70 | attrs_meta = attrs.get('Meta', None) 71 | _meta = {} 72 | db_table = name.lower() 73 | if attrs_meta is not None: 74 | table = getattr(attrs_meta, 'db_table', None) 75 | if not table: 76 | db_table = table 77 | 78 | _meta['db_table'] = db_table 79 | attrs['_meta'] = _meta 80 | attrs['fields'] = fields 81 | if attrs.get('Meta'): 82 | del attrs['Meta'] 83 | return super().__new__(cls, name, bases, attrs, **kw) 84 | 85 | 86 | class BaseModel(metaclass=MetaClass): 87 | def __init__(self, **kw): 88 | for key, value in kw.items(): 89 | setattr(self, key, value) 90 | super().__init__() 91 | 92 | def save(self): 93 | fields = OrderedDict(self.fields) 94 | fields_str = ", ".join([value.db_column for value in fields.values()]) 95 | values_str = ', '.join([str(getattr(self, field)) if not isinstance(value, CharField) 96 | else "'%s'" % str(getattr(self, field)) 97 | for field, value in fields.items()]) 98 | sql = "insert into %s (%s) values (%s)" % (self._meta['db_table'], fields_str, values_str) 99 | print(sql) 100 | # insert into user (name1, age) values ('linda', 20) 101 | 102 | 103 | # 自定义类时写少量属性,元类帮助我们注入很多通用属性 104 | class User(BaseModel): 105 | name = CharField('name1', max_length=16) 106 | age = IntField('age', min_value=0, max_value=100) 107 | 108 | class Meta: 109 | db_table = 'user' 110 | 111 | 112 | if __name__ == '__main__': 113 | user = User(name='linda') 114 | user.age = 20 115 | user.save() 116 | -------------------------------------------------------------------------------- /codes/c09/input: -------------------------------------------------------------------------------- 1 | Oh, my love, my darling, {|}I have hungered {|}for you touch a long time.{|}And time goes by so slowly, and time can do so much.Are you still{|} mine?I need your love,God speed your love to me. -------------------------------------------------------------------------------- /codes/c09/p01_iter_protocol.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # 什么是迭代协议? Iterable,Iterator 4 | 5 | # 迭代器是什么? 迭代器是访问集合内元素的一种方式,一般用来遍历数据 6 | # 迭代器和以下标的访问方式不一样,迭代器是不能返回的,迭代器提供了一种惰性访问数据的方式 7 | 8 | # [] list __iter__ 9 | 10 | from collections.abc import Iterable, Iterator 11 | a = [1, 2] 12 | print(isinstance(a, Iterable)) 13 | print(isinstance(a, Iterator)) 14 | -------------------------------------------------------------------------------- /codes/c09/p02_iterator_iterable.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # 实现__iter__时,必须返回Iterator对象 3 | 4 | from collections.abc import Iterator 5 | 6 | 7 | class MyIterator(Iterator): 8 | def __init__(self, employee): 9 | self.employee = employee 10 | self.index = 0 11 | 12 | def __next__(self): 13 | # 真正返回迭代值的逻辑 14 | # 迭代器不支持切片,不会接收索引值,只能一步一步走 15 | # 遍历大文件 16 | try: 17 | word = self.employee[self.index] 18 | except IndexError: 19 | raise StopIteration 20 | self.index += 1 21 | return word 22 | 23 | 24 | class Company: 25 | def __init__(self, employee): 26 | self.employee = employee 27 | 28 | # def __iter__(self): 29 | # return 1 # TypeError: iter() returned non-iterator of type 'int' 30 | 31 | # def __iter__(self): 32 | # return self # TypeError: iter() returned non-iterator of type 'Company' 33 | 34 | # 使用内置方法 iter 35 | # def __iter__(self): 36 | # return iter(self.employee) # 37 | 38 | # 使用自定义 MyIterator ****** 39 | def __iter__(self): 40 | return MyIterator(self.employee) # <__main__.MyIterator object at 0x0000013462EF0848> 41 | 42 | def __getitem__(self, index): 43 | return self.employee[index] 44 | 45 | 46 | if __name__ == '__main__': 47 | company = Company(['linda', 'alex', 'catherine']) 48 | my_iterator = iter(company) 49 | print(my_iterator) 50 | # for 循环首先查找 __iter__;如果没有自动生成一个__iter__,里面遍历__getitem__ 51 | # for item in company: 52 | # print(item) 53 | 54 | while True: 55 | try: 56 | print(next(my_iterator)) 57 | except StopIteration: 58 | break 59 | 60 | """ 61 | 迭代器设计模式,不要在Company中实现 __next__ 方法,而要单独实现MyIterator实现,Company中__iter__调用MyIterator就行 62 | """ 63 | -------------------------------------------------------------------------------- /codes/c09/p03_generator.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # 生成器函数,函数里只要有 yield 关键字 4 | # - yield 5 | # - 不再是普通的函数 6 | 7 | 8 | def gen_func(): 9 | yield 1 10 | yield 2 11 | yield 3 12 | 13 | 14 | # 惰性求值,延迟求值提供了可能性 15 | # 斐波拉契函数 0 1 1 2 3 5 8 ... 16 | def fib(index): 17 | if index <= 2: 18 | return 1 19 | else: 20 | return fib(index-1) + fib(index-2) 21 | 22 | 23 | def func(): 24 | return 1 25 | 26 | 27 | if __name__ == '__main__': 28 | # 返回为生成器对象,python编译字节码的时候产生 29 | gen = gen_func() 30 | 31 | # 生成器对象也是实现了迭代协议的,可以for循环 32 | for value in gen: 33 | print(value) 34 | 35 | ret = func() 36 | -------------------------------------------------------------------------------- /codes/c09/p03_generator02.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # 斐波拉契 1 1 2 3 5 8 ... 3 | 4 | 5 | # 获取对应位置的值 6 | def fib(index): 7 | if index <= 2: 8 | return 1 9 | else: 10 | return fib(index-1) + fib(index-2) 11 | 12 | 13 | # 获取整个过程 14 | def fib2(index): 15 | ret_list = [] 16 | n, a, b = 0, 0, 1 17 | while n < index: 18 | ret_list.append(b) 19 | a, b = b, a + b 20 | n += 1 21 | return ret_list 22 | 23 | 24 | # yield 25 | def gen_fib(index): 26 | n, a, b = 0, 0, 1 27 | while n < index: 28 | yield b 29 | a, b = b, a + b 30 | n += 1 31 | 32 | 33 | print(fib(10)) 34 | print(fib2(10)) 35 | for value in gen_fib(10): 36 | print(value) 37 | -------------------------------------------------------------------------------- /codes/c09/p04_build_generator.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # python中函数工作原理 3 | 4 | import inspect 5 | 6 | frame = None 7 | 8 | 9 | def foo(): 10 | bar() 11 | 12 | 13 | def bar(): 14 | global frame 15 | frame = inspect.currentframe() 16 | 17 | 18 | # python.exe会用一个叫做PyEval_EvalFrameEx(c函数)去执行foo函数 首先会创建一个栈帧(stack_frame),一个上下文 19 | """ 20 | python中一切皆对象,栈帧对象中运行foo函数字节码对象 21 | 当foo调用子函数bar,又会创建一个栈帧对象,在此栈帧对象中运行bar函数字节码对象 22 | 23 | 所有的栈帧都是分配再堆内存上(不会自动释放),这就对定了栈帧可以独立于调用者存在 24 | 不用于静态语言的调用,静态语言是栈的形式,调用完就自动释放 25 | """ 26 | 27 | # 查看函数实现原理 28 | # import dis 29 | # print(dis.dis(foo)) 30 | 31 | foo() 32 | print(frame.f_code.co_name) # 函数名 bar 33 | 34 | caller_frame = frame.f_back 35 | print(caller_frame.f_code.co_name) # 函数名 foo 36 | 37 | -------------------------------------------------------------------------------- /codes/c09/p04_build_generator02.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | def gen_func(): 5 | address = 'China' 6 | yield 1 7 | name = 'linda' 8 | yield 2 9 | age = 20 10 | return 'done' 11 | 12 | 13 | gen = gen_func() 14 | 15 | import dis 16 | print(dis.dis(gen)) 17 | 18 | print(gen.gi_frame.f_lasti) 19 | print(gen.gi_frame.f_locals) 20 | 21 | print('\nfirst value: %s' % next(gen)) 22 | print(gen.gi_frame.f_lasti) 23 | print(gen.gi_frame.f_locals) 24 | 25 | print('\nsecond value: %s' % next(gen)) 26 | print(gen.gi_frame.f_lasti) 27 | print(gen.gi_frame.f_locals) 28 | 29 | 30 | # 控制整个生成器函数暂定和继续前进 gen.gi_frame.f_lasti 31 | # 整个生成器函数作用域逐渐变化 gen.gi_frame.f_locals 32 | 33 | -------------------------------------------------------------------------------- /codes/c09/p05_userlist_generator.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | 4 | # Python 实现 list 5 | # 重点分析 __iter__ 6 | 7 | from collections import UserList 8 | -------------------------------------------------------------------------------- /codes/c09/p06_generator_file.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | # 500G 文件 特殊只有一行,特殊分割符号 {|} 4 | 5 | 6 | def my_readline(f, newline): 7 | buf = '' 8 | while True: 9 | while newline in buf: 10 | pos = buf.index(newline) 11 | yield buf[:pos] 12 | buf = buf[pos + len(newline):] 13 | chunk = f.read(4096 * 10) 14 | if not chunk: 15 | yield buf 16 | break 17 | buf += chunk 18 | 19 | 20 | with open('input') as f: 21 | for line in my_readline(f, '{|}'): 22 | print(line) 23 | -------------------------------------------------------------------------------- /make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /source/aboutme.rst: -------------------------------------------------------------------------------- 1 | ============== 2 | 关于作者 3 | ============== 4 | 5 | *关于作者* 6 | 7 | * 姓名: ni-ning 8 | * Email: nining1314@gmail.com 9 | * 博客: https://ni-ning.cn/ 10 | * GitHub: https://github.com/ni-ning 11 | -------------------------------------------------------------------------------- /source/c01/p01_introduce.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 1.1 课程介绍 3 | =============================== 4 | 5 | ---------- 6 | 你是否遇到 7 | ---------- 8 | - 看不懂优秀库和框架的源码 9 | - 不知道如何才能进一步优化自己的代码 10 | - asyncio、tornado 等异步框架背后的原理 11 | - python 代码灵活背后的设计原理 12 | - 对生成器稀里糊涂 13 | - 很多 python 抛的异常看不懂 14 | 15 | 16 | ---------- 17 | 如何进阶 18 | ---------- 19 | - 和大神一起 20 | - 阅读优秀源码、懂原理 21 | - 面试、多做项目 22 | 23 | 24 | ---------- 25 | 课程收获 26 | ---------- 27 | - 应对 python 高级工程师面试 28 | - 从深度和广度都扩充自己的知识体系 29 | - 能应对各种难度的框架和库的源码 30 | - 深入理解 python 的设计理念和背后的原理 31 | -------------------------------------------------------------------------------- /source/c02/p01_all_is_object.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 2.1 python中一切皆对象 3 | =============================== 4 | 5 | ------------------------------- 6 | 一切皆对象是python灵活性的根本 7 | ------------------------------- 8 | 9 | - python是动态语言,面向对象更加彻底 10 | - 函数和类也是对象,属于python的一等公民 11 | 12 | 一等公民特性 13 | 14 | - 赋值给一个变量 15 | - 可以添加到集合对象中 16 | - 可以作为参数传递给函数 17 | - 可以当做函数的返回值 18 | 19 | .. code-block:: py 20 | 21 | def bar(name): 22 | print('Hello %s' % name) 23 | 24 | class Person(object): 25 | def __init__(self, name): 26 | print('Hello %s' % name) 27 | 28 | def decorator_func(): 29 | print('from decorator_func') 30 | return bar 31 | 32 | def print_type(obj): 33 | print(type(obj)) 34 | 35 | # 赋值给一个变量 36 | func = bar 37 | func('Linda') 38 | my_class = Person 39 | my_class('Tom') 40 | 41 | # 可以添加到集合对象中 42 | obj_list = [] 43 | obj_list.append(bar) 44 | obj_list.append(Person) 45 | for item in obj_list: 46 | # 可以作为参数传递给函数 47 | print_type(item) 48 | 49 | # 可以当做函数的返回值 50 | deco_bar = decorator_func() 51 | deco_bar('deco_bar') 52 | 53 | 54 | ------------------------------- 55 | 小试牛刀 56 | ------------------------------- 57 | 58 | 实际项目中定义Model来管理存储的数据,可以在Model层之上加一些元操作函数,如get,update,delete等等 59 | 60 | 定义handle接收函数预处理数据 61 | 62 | .. code-block:: py 63 | 64 | def get_record_by_id(_id, handle=None): 65 | record = Model.get(id=_id) 66 | if not record: 67 | return False, '无相关记录' 68 | if handle: 69 | record = handle(record) 70 | return True, record.to_dict 71 | -------------------------------------------------------------------------------- /source/c02/p02_type_object_class.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 2.2 type、object和class之间的关系 3 | =============================== 4 | 5 | -------------------- 6 | type 实例化常见类型 7 | -------------------- 8 | 9 | .. code-block:: py 10 | 11 | >>> name = 'linda' 12 | >>> type(num) 13 | 14 | >>> type(int) 15 | 16 | >>> type(object) 17 | 18 | >>> type(type) 19 | 20 | 21 | - 类 str 实例化 'linda' 22 | - 类 type 实例化 str 23 | - 类 type 实例化 object 24 | - 类 type 实例化 type (具体实现 类似C语言指针) 25 | 26 | 27 | -------------------- 28 | object 是最顶层基类 29 | -------------------- 30 | 31 | .. code-block:: py 32 | 33 | >>> int.__bases__ 34 | (, ) 35 | >>> type.__bases__ 36 | (, ) 37 | >>> object.__bases__ 38 | () 39 | 40 | - 类 str 继承 object 41 | - 类 type 继承 object 42 | - object.__bases__ 值为 () 43 | 44 | -------------------- 45 | type、object、class关系图 46 | -------------------- 47 | 48 | 49 | .. image:: type-object-class.jpg 50 | 51 | 52 | - 把 list,dict 等类做成对象,后续后修改特别方便 53 | - object 是所有类的基类,type 也要继承它 54 | - type 也是自身的实例,一切皆对象,一切继承object 55 | -------------------------------------------------------------------------------- /source/c02/p03_builtin_types.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 2.3 python 中的内置类型 3 | =============================== 4 | 5 | -------------------- 6 | 对象的三个特征 7 | -------------------- 8 | 9 | - 身份,对象在内存中的地址 10 | - 类型,每个对象都应该有个类型,分类思想 11 | - 值,度量大小 12 | 13 | 14 | .. code-block:: py 15 | 16 | >>> name = 'linda' 17 | >>> id(name) 18 | 2247760594928 19 | >>> type(name) 20 | 21 | >>> name 22 | 'linda' 23 | 24 | 25 | 26 | -------------------- 27 | python 常见数据类型 28 | -------------------- 29 | 30 | - None(全局只有一个),即解释器启动时定义 31 | - 数值:int、float、complex、bool 32 | - 迭代类型 33 | - 序列类型:list、tuple、str、bytes 34 | - 映射类型:dict 35 | - 集合类型:set、frozenset 36 | - 上下文管理类型:with语句 37 | - 其他:模块类型、class和实例、函数类型、方法类型、代码类型、object对象、type类型、notimplemented类型 38 | 39 | set和dict.keys()实现原理相同,较快 40 | 41 | 42 | -------------------- 43 | 小试牛刀 44 | -------------------- 45 | 46 | 问:这些常见类型是划分的本质是什么呢,又如何自定义这些类型呢 47 | 48 | 答: 魔法函数 49 | -------------------------------------------------------------------------------- /source/c02/p04_conclusion.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 2.4 本章小结 3 | =============================== 4 | 5 | - python 一切皆对象,以及如何实现一切皆对象 6 | - python 一等公民的特性 7 | - python 常见数据类型概述 8 | -------------------------------------------------------------------------------- /source/c02/type-object-class.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ni-ning/AdvancePython/012da5c234a5efba4b4a5d21549aada5ac9d4d6b/source/c02/type-object-class.jpg -------------------------------------------------------------------------------- /source/c03/p01_magic_func.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 3.1 什么是魔法函数 3 | =============================== 4 | 5 | python 定义类时中,以双下划线开头,以双下划线结尾函数为魔法函数 6 | 7 | - 魔法函数可以定义类的特性 8 | - 魔法函数是解释器提供的功能 9 | - 魔法函数只能使用 python 提供的魔法函数,不能自定义 10 | 11 | .. code-block:: py 12 | 13 | class Company: 14 | def __init__(self, employee_list): 15 | self.employee = employee_list 16 | 17 | def __getitem__(self, index): 18 | return self.employee[index] 19 | 20 | 21 | company = Company(['alex', 'linda', 'catherine']) 22 | employee = company.employee 23 | 24 | for item in employee: 25 | print(item) 26 | 27 | # for 首先去找 __iter__, 没有时优化去找__getitem__ 28 | for item in company: 29 | print(item) 30 | -------------------------------------------------------------------------------- /source/c03/p02_data_model.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 3.2 python 数据模型 3 | =============================== 4 | 5 | -------------------- 6 | python 数据模型 7 | -------------------- 8 | 9 | 数据模型,涉及到知识点其实就是魔法函数 10 | 11 | - 魔法函数会影响 python 语法 company[:2] 12 | - 魔法函数会影响内置函数调用 len(company) 13 | -------------------------------------------------------------------------------- /source/c03/p03_magic_overview.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 3.3 魔法函数一览 3 | =============================== 4 | 5 | ------------- 6 | 非数据运算 7 | ------------- 8 | 9 | 字符串表示 10 | 11 | - __repr__ 12 | - __str__ 13 | 14 | .. code-block:: py 15 | 16 | class Company: 17 | def __init__(self, name): 18 | self.name = name 19 | 20 | def __str__(self): 21 | return '' % self.name 22 | 23 | def __repr__(self): 24 | return '' % self.name 25 | 26 | 27 | company = Company('Apple') 28 | print(company) 29 | 30 | # Python 解释器会隐含调用 31 | print(company.__repr__()) 32 | 33 | 34 | 35 | 集合、序列相关 36 | 37 | - __len__ 38 | - __getitem__ 39 | - __setitem__ 40 | - __delitem__ 41 | - __contains__ 42 | 43 | 迭代相关 44 | 45 | - __iter__ 46 | - __next__ 47 | 48 | 可调用 49 | 50 | - __call__ 51 | 52 | with 上下文管理器 53 | 54 | - __enter__ 55 | - __exit__ 56 | 57 | 58 | 59 | ------------- 60 | 数据运算 61 | ------------- 62 | 63 | - __abs__ 64 | - __add__ 65 | 66 | .. code-block:: py 67 | 68 | class Num: 69 | def __init__(self, num): 70 | self.num = num 71 | 72 | def __abs__(self): 73 | return abs(self.num) 74 | 75 | 76 | n = Num(-1) 77 | print(abs(n)) 78 | 79 | 80 | class Vector: 81 | def __init__(self, x, y): 82 | self.x = x 83 | self.y = y 84 | 85 | def __add__(self, other): 86 | return Vector(self.x + other.x, self.y + other.y) 87 | 88 | def __str__(self): 89 | return 'Vector(%s, %s)' % (self.x, self.y) 90 | 91 | 92 | v1 = Vector(1, 3) 93 | v2 = Vector(2, 4) 94 | print(v1 + v2) 95 | -------------------------------------------------------------------------------- /source/c03/p04_func_len.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 3.4 len 函数的特殊性 3 | =============================== 4 | 5 | CPython时,向list,dict等内部做过优化,len(list)效率高 6 | -------------------------------------------------------------------------------- /source/c03/p05_conclusion.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 3.5 本章小结 3 | =============================== 4 | 5 | - 什么是魔法函数,如何增加类型的特性 6 | - 不需要显示调用魔法函数,内置函数或相应python语法时会自动触发魔法函数 7 | - 通过魔法函数去理解 python 类型 8 | - len 内部有优化 9 | -------------------------------------------------------------------------------- /source/c04/mro1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ni-ning/AdvancePython/012da5c234a5efba4b4a5d21549aada5ac9d4d6b/source/c04/mro1.jpg -------------------------------------------------------------------------------- /source/c04/mro2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ni-ning/AdvancePython/012da5c234a5efba4b4a5d21549aada5ac9d4d6b/source/c04/mro2.jpg -------------------------------------------------------------------------------- /source/c04/p01_duct_polymorphism.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 4.1 鸭子类型和多态 3 | =============================== 4 | 5 | -------------------- 6 | 鸭子类型 7 | -------------------- 8 | 9 | 当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来像鸭子,那么这只鸟可以被称为鸭子 10 | 11 | 12 | .. code-block:: py 13 | 14 | class Cat: 15 | def say(self): 16 | print('I am a cat.') 17 | 18 | class Dog: 19 | def say(self): 20 | print('I am a dog.') 21 | 22 | class Duck: 23 | def say(self): 24 | print('I am a duck.') 25 | 26 | 27 | # Python中较灵活,只要实现say方法就行,实现了多态 28 | animal = Cat 29 | animal().say() 30 | 31 | # 实现多态只要定义了相同方法即可 32 | animal_list = [Cat, Dog, Duck] 33 | for an in animal_list: 34 | an().say() 35 | 36 | """ 37 | class Animal: 38 | def say(self): 39 | print('I am a animal.') 40 | 41 | # 需要继承Animal,并重写say方法 42 | class Cat(Animal): 43 | def say(self): 44 | print('I am a cat.') 45 | 46 | # Java 中定义需要指定类型 47 | Animal an = new Cat() 48 | an.say() 49 | """ 50 | 51 | li1 = ['i1', 'i2'] 52 | li2 = ['i3', 'i4'] 53 | 54 | tu = ('i5', 'i6') 55 | s1 = set() 56 | s1.add('i7') 57 | s1.add('i8') 58 | 59 | # 转变观念,传入的不单单是list,甚至自己实现 iterable 对象 60 | li1.extend(li2) # iterable 61 | li1.extend(tu) 62 | li1.extend(s1) 63 | print(li1) 64 | 65 | 66 | - 实现多态只要定义了相同方法即可 67 | - 魔法函数充分利用了鸭子类型的特性,只要把函数塞进类型中即可 68 | -------------------------------------------------------------------------------- /source/c04/p02_abstract_base_class.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 4.2 抽象基类(abc模块) 3 | =============================== 4 | 5 | -------------------- 6 | 抽象基类 7 | -------------------- 8 | 9 | - 抽象基类无法实例化 10 | - 变量没有类型限制,可以指向任何类型 11 | - 抽象基类和魔法函数构成了python的基础,即协议 12 | 13 | 在抽象基类定义了抽象方法,继承了抽象基类的类,必须实现这些方法 14 | 15 | 场景一:想判断某个对象的类型 16 | 17 | .. code-block:: py 18 | 19 | # 检查某个类是否有某种方法 20 | class Company: 21 | def __init__(self, name): 22 | self.name = name 23 | 24 | def __len__(self): 25 | return len(self.name) 26 | 27 | 28 | company = Company('Linda Process Ltd.') 29 | print(hasattr(company, '__len__')) 30 | 31 | from collections.abc import Sized 32 | print(isinstance(company, Sized)) 33 | 34 | 35 | 36 | 场景二:强制子类必须实现某些方法 37 | 38 | .. code-block:: py 39 | 40 | import abc 41 | 42 | class CacheBase(metaclass=abc.ABCMeta): 43 | 44 | @abc.abstractmethod 45 | def get(self, key): 46 | pass 47 | 48 | @abc.abstractmethod 49 | def set(self, key, value): 50 | pass 51 | 52 | 53 | class MemoryCache(CacheBase): 54 | pass 55 | 56 | 57 | 58 | 注意:抽象基类容易设计过度,多继承推荐使用Mixin 59 | -------------------------------------------------------------------------------- /source/c04/p03_isinstance_type.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 4.3 isinstance 和 type 的区别 3 | =============================== 4 | 5 | - isinstance 会去查找继承链 6 | - type 只判断变量的内存地址 7 | 8 | .. code-block:: py 9 | 10 | class A: 11 | pass 12 | 13 | class B(A): 14 | pass 15 | 16 | b = B() 17 | print(isinstance(b, B)) 18 | print(isinstance(b, A)) 19 | 20 | # is 判断 id 的意思 21 | print(type(b) is B) 22 | print(type(b) is A) # False 23 | -------------------------------------------------------------------------------- /source/c04/p04_class_variable.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 4.4 类变量与实例变量 3 | =============================== 4 | 5 | - 类变量定义与使用 6 | - 实例变量定义与使用 7 | - 类变量是所有实例变量共享 8 | 9 | .. code-block:: py 10 | 11 | class A: 12 | aa = 1 13 | 14 | def __init__(self, x, y): 15 | self.x = x 16 | self.y = y 17 | 18 | 19 | a = A(2, 3) 20 | print(a.x, a.y, A.aa) 21 | 22 | A.aa = 111 23 | a.aa = 100 # 新建一个a的属性aa, 100赋值给该aa 24 | print(A.aa, a.aa) 25 | -------------------------------------------------------------------------------- /source/c04/p05_attr_method.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 4.5 类属性和实例属性以及查找顺序 3 | =============================== 4 | 5 | -------------------- 6 | 类属性和实例属性 7 | -------------------- 8 | 9 | - 类属性:定义在类中的变量和方法 10 | - 实例属性:__init__中定义 11 | 12 | 13 | -------------------- 14 | 深度优先 DFS 15 | -------------------- 16 | 17 | 18 | .. image:: mro1.jpg 19 | 20 | - 查找顺序为 A -> B -> D -> C -> E 21 | - 此种场景深度优先较为合适 22 | 23 | 24 | .. image:: mro2.jpg 25 | 26 | - 查找顺序为 A -> B -> D -> C 27 | - 此种场景 当C中重载了D中某个方法,该查找顺序就不合适 28 | 29 | 30 | -------------------- 31 | 广度优先 BFS 32 | -------------------- 33 | 34 | 35 | .. image:: mro2.jpg 36 | 37 | - 查找顺序为 A -> B -> C -> D 38 | - 此种场景深度优先较为合适 39 | 40 | 41 | .. image:: mro1.jpg 42 | 43 | - 查找顺序为 A -> B -> C -> D -> E 44 | - 此种场景 B继承D,B和D是一体的,D应该先于C 45 | 46 | 47 | -------------------- 48 | MRO C3 算法 49 | -------------------- 50 | 51 | 菱形功能继承D场景 52 | 53 | .. code-block:: py 54 | 55 | class D: 56 | pass 57 | 58 | class C(D): 59 | pass 60 | 61 | class B(D): 62 | pass 63 | 64 | class A(B, C): 65 | pass 66 | 67 | print(A.__mro__) 68 | # (, , , , ) 69 | 70 | 71 | B、C 各自继承D、E场景 72 | 73 | .. code-block:: py 74 | 75 | class D: 76 | pass 77 | 78 | class E: 79 | pass 80 | 81 | class C(E): 82 | pass 83 | 84 | class B(D): 85 | pass 86 | 87 | class A(B, C): 88 | pass 89 | 90 | print(A.__mro__) 91 | # (, , , , , ) 92 | -------------------------------------------------------------------------------- /source/c04/p06_class_method.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 4.6 静态方法、类方法、对象方法以及参数 3 | =============================== 4 | 5 | - 静态方法 @staticmethod 6 | - 类方法 @classmethod 7 | - 实例方法 8 | 9 | .. code-block:: py 10 | 11 | class Date: 12 | def __init__(self, year, month, day): 13 | self.year = year 14 | self.month = month 15 | self.day = day 16 | 17 | def tomorrow(self): 18 | self.day += 1 19 | 20 | @staticmethod 21 | def date_from_str(date_str): 22 | year, month, day = tuple(date_str.split('-')) 23 | return Date(int(year), int(month), int(day)) 24 | 25 | @classmethod 26 | def date_from_string(cls, date_str): 27 | year, month, day = tuple(date_str.split('-')) 28 | return cls(int(year), int(month), int(day)) 29 | 30 | def __str__(self): 31 | return '{year}/{month}/{day}'.format(year=self.year, month=self.month, day=self.day) 32 | 33 | 34 | if __name__ == '__main__': 35 | new_day = Date(2020, 2, 20) 36 | new_day.tomorrow() 37 | print(new_day) 38 | 39 | date_str = '2020-12-12' 40 | print(Date.date_from_str(date_str)) 41 | print(Date.date_from_string(date_str)) 42 | -------------------------------------------------------------------------------- /source/c04/p07_private_method.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 4.7 数据封装和私有属性 3 | =============================== 4 | 5 | 6 | 定义类时双下划线的属性,为私有属性 7 | 8 | 9 | .. code-block:: py 10 | 11 | class User: 12 | def __init__(self): 13 | self.__age = 18 14 | 15 | def get_age(self): 16 | return self.__age 17 | 18 | if __name__ == '__main__': 19 | user = User() 20 | print(user.get_age()) 21 | 22 | # print(user.__age) 23 | 24 | # _class__attr, 做了变形 25 | print(user._User__age) 26 | 27 | 28 | - python并不能严格限制私有属性的使用,这是一种写代码规范 29 | -------------------------------------------------------------------------------- /source/c04/p08_private_method.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 4.8 python对象的自省机制 3 | =============================== 4 | 5 | 通过一定的机制查询对象的内部结构 6 | 7 | - __dict__ 8 | - dir() 9 | 10 | .. code-block:: py 11 | 12 | class User: 13 | name = 'user' 14 | 15 | class Student(User): 16 | def __init__(self): 17 | self.school_name = 'school' 18 | 19 | if __name__ == '__main__': 20 | stu = Student() 21 | 22 | # 通过__dict__ 查询属性, C语言实现,经过优化,较快 23 | print(stu.__dict__) 24 | stu.__dict__['age'] = 18 25 | print(stu.age) 26 | 27 | print(User.__dict__) 28 | 29 | print(dir(stu)) 30 | -------------------------------------------------------------------------------- /source/c04/p09_super.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 4.9 super真的是调用父类吗 3 | =============================== 4 | 5 | -------------------------------------------------------------------------------- /source/c05/p01_sequeue_type.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 5.1 python中的序列分类 3 | =============================== 4 | 5 | 序列是 python 中重要的协议 6 | 7 | 8 | 按照元素类型是否相同 9 | 10 | - 容器序列:list、tuple、deque 11 | - 扁平序列:str、bytes、bytearray、array.array 12 | 13 | 按照元素是否可变 14 | 15 | - 可变类型:list、deque、bytearray、array.array 16 | - 不可变:str、tuple、bytes 17 | 18 | 19 | .. code-block:: py 20 | 21 | # 元素类型任意 22 | my_list = list() 23 | my_list.append(100) 24 | my_list.append(True) 25 | 26 | # 指定元素类型 27 | import array 28 | my_array = array.array('i') 29 | my_array.append(100) 30 | # 初始化数组需要整型,附加字符串抛异常 31 | my_array.append('abc') 32 | -------------------------------------------------------------------------------- /source/c05/p02_collections_abc.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 5.2 序列的abc继承关系 3 | =============================== 4 | 5 | python 中内置的 collections.abc 抽象基类,可以帮助我们理解数据类型实现细节 6 | 7 | python 是基于协议的语言,结合鸭子类型和魔法函数,就可以达到实现某种类型 8 | 9 | from collections.abc import * 10 | 11 | - Iterable: __iter__ 12 | - Reversible: __reversed__ 13 | - Sized: __len__ 14 | - Container: __contains__ 15 | - Collection: Sized, Iterable, Container 16 | - Sequence: __getitem__, Reversible, Collection 17 | - MutableSequence: __setitem__, __delitem__, Sequence 18 | 19 | 不同魔法函数的组合,构建不同的类型 20 | -------------------------------------------------------------------------------- /source/c05/p03_list_extend.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 5.3 序列中+、+=和extend的区别 3 | =============================== 4 | 5 | - 加号 + 会新生成对象,并且两边类型需要一致 6 | - 加等 += 就地加,只需要可迭代就行 7 | - append 附加单个元素,extend 扩展多个元素 8 | 9 | .. code-block:: py 10 | 11 | # + 加新增 12 | l1 = [1, 2] 13 | l2 = l1 + [3, 4] 14 | print("type(l1): %d, and l1: %s" % (id(l1), l1)) 15 | print("type(l2): %d, and l2: %s" % (id(l2), l2)) 16 | 17 | # += 就地加 18 | l1 += ['3', '4'] 19 | l1 += ('5', '6') 20 | l1 += range(2) 21 | print("type(l1): %d, and l1: %s" % (id(l1), l1)) 22 | 23 | 24 | # + 两边类型需相同 25 | # += 只需要可迭代的就行,__iadd__ 魔法函数实现 26 | -------------------------------------------------------------------------------- /source/c05/p04_implement_sliencable.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 5.4 实现可切片的对象 3 | =============================== 4 | 5 | -------------------- 6 | 列表切片操作 7 | -------------------- 8 | 9 | .. code-block:: py 10 | 11 | ''' 12 | 模式 [start:end:step] 13 | 14 | 第一个数字 start 表示切片开始位置,默认 0 15 | 第二个数字 end 表示切片截止(但不包含)位置,默认列表长度 16 | 第三个数字 step 表示切片的步骤,默认为 1 17 | 18 | 当 start 为 0 时可以省略 19 | 当 end 为列表长度时可以省略 20 | 当 step 为 1 时可以省略,并且省略步长时可以同时省略最后一个冒号 21 | 当 step 为负数时,表示反向切片,这时 start 应该比 end 的值要大才行 22 | ''' 23 | 24 | a_list = [3, 4, 5, 6, 7, 9, 11, 13, 15, 17] 25 | a_list[::] # 返回包含原列表中所有元素的新列表 26 | a_list[::-1] # 返回包含原列表中所有元素的逆向新列表 27 | a_list[::2] # 隔一个元素取一个,获取偶数位置的元素 28 | a_list[1::2] # 隔一个元素取一个,获取奇数位置的元素 29 | a_list[3:6] # 指定切片的开始和结束位置 30 | a_list[0:100] # 切片结束位置大于列表长度是,从列表尾部截断 31 | a_list[100:] # 切片开始位置大于列表长度时,返回空列表 32 | 33 | a_list[len(a_list):0] = [9] # 在列表尾部增加元素 34 | a_list[:0] = [1, 2] # 在列表头部增加元素 35 | a_list[3:3] = [100] # 在列表中间位置插入元素 36 | a_list[:2] = [100, 200] # 替换列表元素,等号两边长度相等 37 | a_list[3:] = [4, 5, 6] # 替换列表元素,等号两边长度可以不相等 38 | a_list[:3] = [] # 删除列表中前 3 个元素 39 | 40 | 41 | -------------------- 42 | 自定义序列类 43 | -------------------- 44 | 45 | 参考 collections.abc 序列类 Sequence 所需的魔法函数 46 | 47 | .. code-block:: py 48 | 49 | import numbers 50 | 51 | class Group: 52 | def __init__(self, group_name, company_name, staff): 53 | self.group_name = group_name 54 | self.company_name = company_name 55 | self.staffs = staff 56 | 57 | def __reversed__(self): 58 | self.staffs.reverse() 59 | 60 | def __getitem__(self, item): 61 | cls = type(self) 62 | if isinstance(item, slice): 63 | return cls(group_name=self.group_name, company_name=self.company_name, staff=self.staffs[item]) 64 | elif isinstance(item, numbers.Integral): 65 | return cls(group_name=self.group_name, company_name=self.company_name, staff=[self.staffs[item]]) 66 | 67 | def __len__(self): 68 | return len(self.staffs) 69 | 70 | def __iter__(self): 71 | return iter(self.staffs) 72 | 73 | def __contains__(self, item): 74 | if item in self.staffs: 75 | return True 76 | else: 77 | return False 78 | 79 | 80 | staffs = ['linda', 'alex', 'catherine', 'nash', 'curry'] 81 | group = Group(group_name='group', company_name='company', staff=staffs) 82 | sub_group = group[0] 83 | 84 | print('linda' in sub_group) 85 | print(len(sub_group)) 86 | -------------------------------------------------------------------------------- /source/c05/p05_bisect.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 5.5 bisect维护已排序序列 3 | =============================== 4 | 5 | - bisect 维护一个升序的序列 6 | - 内部二分查找实现,效率高 7 | 8 | 9 | .. code-block:: py 10 | 11 | import bisect 12 | 13 | # 处理已排序 序列 升序 14 | # 内部二分查找算法实现 15 | 16 | l1 = list() 17 | bisect.insort(l1, 10) 18 | bisect.insort(l1, 3) 19 | bisect.insort(l1, 2) 20 | bisect.insort(l1, 6) 21 | 22 | print(l1) # [2, 3, 6, 10] 23 | -------------------------------------------------------------------------------- /source/c05/p06_altertive_to_list.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 5.6 什么时候我们不该用列表 3 | =============================== 4 | 5 | - 比 list 更好的 python 内置数据结构 6 | - array 数组 连续的内存空间,性能高 7 | - deque 双向列表 8 | 9 | -------------------- 10 | array 数组 11 | -------------------- 12 | 13 | array 与 list 一个重要区别,array 只能存储指定的数据类型数据 14 | 15 | 16 | .. code-block:: py 17 | 18 | import array 19 | 20 | list 21 | my_array = array.array('i') 22 | my_array.append(100) 23 | my_array.append('abc') 24 | 25 | 26 | 27 | 28 | - 某些应用场景,除了 list 我们还有其他更好的选择 29 | -------------------------------------------------------------------------------- /source/c05/p07_comprehension.rst: -------------------------------------------------------------------------------- 1 | =========================================== 2 | 5.7 列表推导式、生成器表达式和字典推导式 3 | =========================================== 4 | 5 | -------------------- 6 | 列表推导式 7 | -------------------- 8 | 9 | 列表推导式,或列表生成式,通过一行代码生成列表 10 | 11 | .. code-block:: py 12 | 13 | # 提取出 1-20 之间的奇数 14 | odd_list = [i for i in range(21) if i % 2 == 1] 15 | print(odd_list) 16 | 17 | # 逻辑复杂的情况 18 | def handle_item(item): 19 | return item * item 20 | 21 | odd_list = [handle_item(i) for i in range(21) if i % 2 == 1] 22 | print(odd_list) 23 | 24 | - 列表生成式性能高于列表操作 25 | - 逻辑过于复杂时,列表生成式可读性降低 26 | 27 | -------------------- 28 | 生成器表达式 29 | -------------------- 30 | 31 | 列表推导 [] -> () 32 | 33 | .. code-block:: py 34 | 35 | my_gen = (i for i in range(21) if i % 2 == 1) 36 | print(type(my_gen)) # 37 | for i in my_gen: 38 | print(i) 39 | 40 | 41 | -------------------- 42 | 字典推导式 43 | -------------------- 44 | 45 | .. code-block:: py 46 | 47 | d1 = {'key1': 'value1', 'key2': 'value2'} 48 | d2 = {v: k for (k, v) in d1.items()} 49 | print(d2) 50 | 51 | 52 | -------------------- 53 | 集合推导式 54 | -------------------- 55 | 56 | .. code-block:: py 57 | 58 | set1 = {v for v in d1.values()} 59 | print(set1) 60 | -------------------------------------------------------------------------------- /source/c05/p08_conclusion.rst: -------------------------------------------------------------------------------- 1 | =========================================== 2 | 5.8 本章小结 3 | =========================================== 4 | 5 | - 序列类型的分类 6 | - 序列的abc继承关系 7 | - 序列的+、+=和extend的区别 8 | - 实现可切片的对象 9 | - bisect管理可排序序列 10 | - list的其他选项 11 | - 列表字典推导式 12 | -------------------------------------------------------------------------------- /source/c06/p01_mapping_type.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 6.1 dict的abc继承关系 3 | =============================== 4 | 5 | from collections.abc import * 6 | 7 | 8 | - Sized: __len__ 9 | - Iterable: __iter__ 10 | - Container: __contains__ 11 | - Collection: Sized, Iterable, Container 12 | - Mapping: Collection 13 | - MutableMapping: Mapping 14 | 15 | 可以看出来 dict 和 list 有一些共有的魔法函数 16 | 17 | .. code-block:: py 18 | 19 | from collections.abc import Mapping 20 | 21 | # dict 属于 Mapping 类型 22 | d = dict() 23 | print(isinstance(d, Mapping)) 24 | -------------------------------------------------------------------------------- /source/c06/p02_dict_methods.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 6.2 dict的常用方法 3 | =============================== 4 | 5 | 借助编辑器,如 PyCharm 实时查看源码 6 | 7 | .. code-block:: py 8 | 9 | d = { 10 | 'linda': {'company': 'Yahoo'}, 11 | 'catherine': {'company': 'Google'} 12 | } 13 | 14 | # 清空 15 | # d.clear() 16 | 17 | # 浅拷贝 18 | new_dict = d.copy() 19 | # 深拷贝 20 | import copy 21 | new_dict_deep = copy.deepcopy(d) 22 | 23 | new_dict['linda']['company'] = 'Ali' 24 | print(d) 25 | print(new_dict) 26 | print(new_dict_deep) 27 | 28 | dd = dict.fromkeys(['key1', 'key2'], 'default') 29 | dd.get('key', None) 30 | dd.keys(), dd.values(), dd.items() 31 | 32 | # 获取key的value, 没有时更新为默认值 33 | print(dd.setdefault('key', 'value')) 34 | dd.update({'name': 'linda'}) 35 | print(dd) 36 | -------------------------------------------------------------------------------- /source/c06/p03_dict_subclass.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 6.3 dict的子类 3 | =============================== 4 | 5 | - 不建议直接继承 c 语言实现的内置结构 dict,list 6 | 7 | .. code-block:: py 8 | 9 | class MyDict(dict): 10 | def __setitem__(self, key, value): 11 | super().__setitem__(key, value * 2) 12 | 13 | 14 | my_dict = MyDict(one=1) 15 | print(my_dict) # 1, 某些情况下,不会调用重写的__setitem__ 16 | my_dict['one'] = 1 17 | print(my_dict) # 2, 触发重写的 __setitem__ 18 | 19 | 20 | - 可继承 UserDict 实现自定义 21 | - python 语法模拟 c 语言实现细节 22 | 23 | 24 | .. code-block:: py 25 | from collections import UserDict 26 | 27 | # python 语法模拟 c 语言实现细节 28 | class CustomDict(UserDict): 29 | def __setitem__(self, key, value): 30 | super().__setitem__(key, value * 2) 31 | 32 | 33 | dd = CustomDict(one=1) 34 | print(dd) 35 | 36 | 37 | d1 = UserDict({'kk': 'vv'}, k1='v1') 38 | print(d1) 39 | 40 | 41 | - defaultdict 实现 __missing__ 42 | 43 | .. code-block:: py 44 | 45 | from collections import defaultdict 46 | 47 | d2 = defaultdict(list) 48 | # 实现了 __missing__ 魔法函数,可参考UserDict __getitem__ 实现 49 | value = d2['key'] 50 | print(value) 51 | print(dict(d2)) 52 | -------------------------------------------------------------------------------- /source/c06/p04_set_frozenset.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 6.4 set和frozenset 3 | =============================== 4 | 5 | .. code-block:: py 6 | 7 | # set 不重复、无序 8 | s1 = set('abcc') 9 | print(s1) # {'a', 'c', 'b'} 10 | 11 | # frozenset 不可变可以作为 dict key 12 | f1 = frozenset('abcc') 13 | print(f1) 14 | -------------------------------------------------------------------------------- /source/c06/p05_dict_set_principle.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 6.5 dict和set实现原理 3 | =============================== 4 | -------------------------------------------------------------------------------- /source/c06/p06_conclusion.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 6.6 本章小结 3 | =============================== 4 | -------------------------------------------------------------------------------- /source/c07/p01_python_variable.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 7.1 python 的变量是什么 3 | =============================== 4 | 5 | - java 中变量相当于申请一个盒子,盒子有类型大小之说 6 | - python 中变量,类似一个指针,指针的值是固定的,类似便利贴,可以贴到任何对象上 7 | 8 | .. code-block:: py 9 | 10 | # a 贴到 1 上面 11 | a = 1 12 | # a 再贴到 'abc' 上 13 | a = 'abc' 14 | # 注意顺序: 先生成对象,然后贴便利贴 15 | 16 | la = [1, 2, 3] 17 | lb = la 18 | # is, 本质 id(a) 与 id(b) 比较 19 | print(lb is la) # True, id 相同 20 | print(id(la), id(lb)) 21 | 22 | la.append(100) 23 | print(lb) # lb 和 la 指向相同对象,lb 会发生变化 24 | -------------------------------------------------------------------------------- /source/c07/p02_is_equal.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 7.2 is 和 == 区别 3 | =============================== 4 | 5 | - is 比较 id() 6 | - == 比较 变量值 7 | 8 | .. code-block:: py 9 | 10 | # is, 本质 id(a) 与 id(b) 比较 11 | # = 右边为对象时,表示生成新对象 12 | a = [1, 2, 3, 4] 13 | b = [1, 2, 3, 4] 14 | print(a is b) # False, 说明 id 不同 15 | print(id(a), id(b)) 16 | print(a == b) # True, 值相同,内部 __eq__ 魔法函数 17 | 18 | # 内部优化 小整数、小字符串 全局唯一 intern机制 19 | a1 = 1 20 | a2 = 1 21 | print(a1 is a2) # True 22 | 23 | s1 = 'abc' 24 | s2 = 'abc' 25 | print(s1 is s2) # True 26 | 27 | 28 | class People: 29 | pass 30 | 31 | 32 | # People 全局唯一 33 | person = People() 34 | print(type(person) is People) # True 35 | -------------------------------------------------------------------------------- /source/c07/p03_del.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 7.3 del 语句和垃圾回收 3 | =============================== 4 | 5 | .. code-block:: py 6 | 7 | # python 中垃圾回收算法为 引用计数 8 | 9 | a = 1 10 | b = a 11 | del a 12 | 13 | 14 | 15 | - del 触发 __del__ 逻辑 16 | - 对象引用计数为 0 时,会被垃圾回收 17 | -------------------------------------------------------------------------------- /source/c07/p04_argument_error.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 7.4 一个经典的参数错误 3 | =============================== 4 | 5 | a, b 都是整型时 6 | 7 | .. code-block:: py 8 | 9 | def add(a, b): 10 | a += b 11 | return a 12 | 13 | if __name__ == '__main__': 14 | a, b = 1, 2 15 | c = add(a, b) 16 | print('a: %s, b: %s, c: %s' % (a, b, c)) 17 | # 结果为 a: 1, b: 2, c: 3 18 | # a 未发生变化 19 | 20 | 21 | a, b 都是列表时 22 | 23 | .. code-block:: py 24 | 25 | def add(a, b): 26 | a += b 27 | return a 28 | 29 | if __name__ == '__main__': 30 | a, b = [1, 2], [3, 4] 31 | c = add(a, b) 32 | print('a: %s, b: %s, c: %s' % (a, b, c)) 33 | # 结果为 a: [1, 2, 3, 4], b: [3, 4], c: [1, 2, 3, 4] 34 | # a 发生变化 35 | 36 | 37 | a, b 都是元组时 38 | 39 | .. code-block:: py 40 | 41 | def add(a, b): 42 | a += b 43 | return a 44 | 45 | 46 | if __name__ == '__main__': 47 | a, b = (1, 2), (3, 4) 48 | c = add(a, b) 49 | print('a: %s, b: %s, c: %s' % (a, b, c)) 50 | # 结果为 a: (1, 2), b: (3, 4), c: (1, 2, 3, 4) 51 | # a 未发生变化 52 | 53 | 54 | 默认类型为可变类型时 55 | 56 | .. code-block:: py 57 | 58 | class Company: 59 | def __init__(self, name, staff_list=[]): 60 | self.name = name 61 | self.staff_list = staff_list 62 | 63 | def add(self, staff): 64 | self.staff_list.append(staff) 65 | 66 | def remove(self, staff): 67 | self.staff_list.remove(staff) 68 | 69 | 70 | if __name__ == '__main__': 71 | com1 = Company('com1', ['staff1', 'staff11']) 72 | com1.add('staff111') 73 | com1.remove('staff11') 74 | print(com1.staff_list) 75 | 76 | com2 = Company('com2') 77 | com2.add('staff2') 78 | 79 | com3 = Company('com3') 80 | com3.add('staff3') 81 | 82 | print(com2.staff_list) # ['staff2', 'staff3'] 83 | print(com3.staff_list) # ['staff2', 'staff3'] 84 | 85 | - 默认值为可变类型 [],com2.staff_list 和 com3.staff_list 指向一块内存空间 86 | -------------------------------------------------------------------------------- /source/c07/p05_conclusion.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 7.5 本章小结 3 | =============================== 4 | 5 | - python 变量的本质 6 | - is、== 和 = 区别与联系 7 | - del 和垃圾回收 8 | -------------------------------------------------------------------------------- /source/c08/p01_property.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 8.1 property 动态属性 3 | =============================== 4 | 5 | .. code-block:: py 6 | 7 | from datetime import date 8 | 9 | class User: 10 | def __init__(self, name, birthday): 11 | self.name = name 12 | self.birthday = birthday 13 | self._age = 0 # _ 一种编程规范 14 | 15 | @property 16 | def age(self): 17 | return date.today().year - self.birthday.year 18 | 19 | @age.setter 20 | def age(self, value): 21 | self._age = value 22 | 23 | def get_age(self): 24 | return self._age 25 | 26 | 27 | if __name__ == '__main__': 28 | user = User('linda', date(1987, 11, 14)) 29 | print(user.age) # @property 用变量的方式去封装逻辑 30 | user.age = 100 # @age.setter 接收参数 31 | print(user.get_age()) # self._age 实例内部有存储的变量 _age 32 | 33 | 34 | - 对外展示 user.age; 内部存储 self._age 35 | - 动态属性 property 内部有更多的逻辑操作空间 36 | - user.age = 100 仔细体会内部处理过程 37 | -------------------------------------------------------------------------------- /source/c08/p02_getattr_getattritute.rst: -------------------------------------------------------------------------------- 1 | ========================================== 2 | 8.2 __getattr__、__getattribute__魔法函数 3 | ========================================== 4 | 5 | -------------------- 6 | __getattr__ 7 | -------------------- 8 | 9 | .. code-block:: py 10 | 11 | class User: 12 | def __init__(self, name): 13 | self.name = name 14 | 15 | def __getattr__(self, item): 16 | return 'Not found attribute %s' % item 17 | 18 | if __name__ == '__main__': 19 | user = User('linda') 20 | print(user.age) # Not found attribute age 21 | 22 | - __getattr__, 在查找不到属性的时候调用 23 | - 类似 else 机制 24 | 25 | 26 | .. code-block:: py 27 | 28 | class User: 29 | def __init__(self, info=None): 30 | if not info: 31 | info = {} 32 | self.info = info 33 | 34 | def __getattr__(self, item): 35 | return self.info[item] 36 | 37 | 38 | if __name__ == '__main__': 39 | user = User({'name': 'linda', 'age': 18}) 40 | print(user.name) 41 | print(user.age) 42 | 43 | - 神奇的代理操作 44 | 45 | 46 | -------------------- 47 | __getattribute__ 48 | -------------------- 49 | 50 | .. code-block:: py 51 | 52 | class User: 53 | def __init__(self, name): 54 | self.name = name 55 | 56 | def __getattribute__(self, item): 57 | return 'get_attribute' 58 | 59 | 60 | if __name__ == '__main__': 61 | user = User('linda') 62 | print(user.name) # get_attribute 63 | print(user.test) # get_attribute 64 | print(user.other) # get_attribute 65 | 66 | 67 | - 只要调用属性,就会触发 __getattribute__ 68 | - 把持了整个属性调用入口,尽量不要重写这个方法 69 | - 写框架时会涉及到 70 | -------------------------------------------------------------------------------- /source/c08/p03_descriptor.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 8.3 属性描述符和属性查找过程 3 | =============================== 4 | 5 | property 实现在数据获取和设置时增加额外逻辑处理,并对外提供简单接口 6 | 7 | 在批量属性操作,如验证,则需要每个属性都要写一遍,代码重复 8 | 9 | - 数据属性描述符:实现 __get__ 和 __set__ 方法 10 | - 非数据属性描述符: 实现 __get__ 方法 11 | 12 | .. code-block:: py 13 | 14 | import numbers 15 | 16 | class IntField: 17 | def __init__(self): 18 | self._data = None 19 | 20 | def __get__(self, instance, owner): 21 | print(instance) # <__main__.User object at 0x000002B88B270288> 22 | print(owner) # 23 | print(type(instance) is owner) # True 24 | print(instance.__class__ is owner) # True 25 | return self._data 26 | 27 | def __set__(self, instance, value): 28 | if not isinstance(value, numbers.Integral): 29 | raise ValueError('Need int value') 30 | # 重点来了,如何保存 value 呢,instance or self 31 | # 如果 instance.attribute 又会触发 __set__ 描述符 32 | self._data = value 33 | 34 | def __delete__(self, instance): 35 | pass 36 | 37 | 38 | class User: 39 | age = IntField() 40 | num = IntField() 41 | 42 | 43 | if __name__ == '__main__': 44 | user = User() 45 | user.age = 18 46 | print(user.__dict__) # {} "age" 并没有进入到 __dict__ 47 | 48 | print(user.age) 49 | 50 | 51 | 52 | 转变原先简单的属性获取顺序 53 | 54 | 55 | .. code-block:: py 56 | 57 | user 某个类实例,user.age 等价于 getattr(user, 'age') 58 | 59 | 首先调用 __getattribute__ 60 | 如果定义了 __getattr__ 方法,调用 __getattribute__ 抛出异常 AttributeError 触发__getattr__ 61 | 而对于描述符(__get__)的调用,则是发生在 __getattribute__内部 62 | 63 | user = User(), 调用 user.age 顺序如下: 64 | (1) 如果 'age' 是出现在 User 或基类的 __dict__ 中,且 age 是data descriptor,那么调用其 __get__(instance, owner) 方法,否则 65 | (2) 如果 'age' 出现在 user 的 __dict__ 中,那么直接返回 user.__dict__['age'],否则 66 | (3) 如果 'age' 出现在 User 或基类的 __dict__ 中 67 | (3.1) 如果 age 是 non-data descriptor, 那么调用其 __get__ 方法,否则 68 | (3.2) 返回 User.__dict__['age'] 69 | (4) 如果 User 有 __getattr__ 方法,调用 __getattr__ 方法,否则 70 | (5) 抛出异常 AttributeError 71 | 72 | 73 | - 属性描述符优先级最高 74 | 75 | .. code-block:: py 76 | 77 | class NonDataIntFiled: 78 | def __get__(self, instance, owner): 79 | print(instance) 80 | print(owner) 81 | return 100 82 | 83 | class User: 84 | age = NonDataIntFiled() 85 | 86 | if __name__ == '__main__': 87 | user = User() 88 | # user.__dict__['age'] = 18 89 | # user.age = 18 90 | # print(user.__dict__) 91 | print(user.age) 92 | -------------------------------------------------------------------------------- /source/c08/p04_new_init.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 8.4 __new__ 和 __init__ 的区别 3 | =============================== 4 | 5 | - 自定义类中 __new__: 用来控制对象的生成过程,返回 self 对象,如果没有返回值,则不会调用 __init__ 6 | - 自定义类中 __init__: 用来完善对象,如初始化 7 | - __new__ 在 __init__ 之前调用 8 | 9 | 10 | .. code-block:: py 11 | 12 | class User(object): 13 | 14 | # 新式类才有,生成对象 user 之前加逻辑 15 | def __new__(cls, *args, **kwargs): 16 | # args = ('linda', ) 17 | # kwargs = {'age': 20} 18 | # 与自定义 metaclass 中的 __new__ 有区别 19 | print('from __new__') 20 | self = super().__new__(cls) 21 | return self 22 | 23 | def __init__(self, name, age=18): 24 | self.name = name 25 | self.age = age 26 | print('from __init__') 27 | 28 | 29 | if __name__ == '__main__': 30 | user = User('linda', age=20) 31 | 32 | 33 | PS: 统一描述 34 | 35 | - 元类 -> 类对象 36 | - 类 -> 实例 37 | -------------------------------------------------------------------------------- /source/c08/p05_metaclass.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 8.5 自定义元类 3 | =============================== 4 | 5 | - class 关键字 可以字面创建类 6 | 7 | .. code-block:: py 8 | 9 | def create_class(name): 10 | 11 | if name == 'user': 12 | class User: 13 | def __str__(self): 14 | return 'User' 15 | return User 16 | 17 | elif name == 'company': 18 | class Company: 19 | def __str__(self): 20 | return 'Company' 21 | return Company 22 | 23 | MyClass = create_class('user') 24 | obj = MyClass() 25 | print(obj) 26 | print(type(obj)) # .User'> 27 | 28 | 29 | - type 可以动态创建类,动态添加属性和方法 30 | 31 | .. code-block:: py 32 | 33 | def func(self): 34 | return 'I am from func.' 35 | 36 | class Base: 37 | def answer(self): 38 | return 'I am from Base.answer.' 39 | 40 | # type 动态创建类 41 | User = type('User', (Base, ), {'name': 'user', 'func': func}) 42 | user = User() 43 | print(user.name) 44 | print(user.func()) 45 | print(user.answer()) 46 | print(type(user)) 47 | 48 | 49 | 元类创建类的类 metaclass(type) -> class -> instance 50 | 51 | .. code-block:: py 52 | 53 | class MetaClass(type): 54 | # 用来控制 User 的创建过程 与 User 中的 __new__ 有区别 55 | def __new__(cls, name, bases, attrs, **kw): 56 | return super().__new__(cls, name, bases, attrs, **kw) 57 | 58 | 59 | class User(object, metaclass=MetaClass): 60 | 61 | def __init__(self, name): 62 | self.name = name 63 | 64 | def bar(self): 65 | print('from bar.') 66 | 67 | 68 | 69 | python 在实例化的过程 user = User() 70 | 71 | (1) 首先寻找 metaclass,来创建 User,否则 72 | (2) 再次寻找基类 BaseUser 的 metaclass,来创建 User,否则 73 | (3) 接着寻找模块 metaclass,来创建 User,否则 74 | (4) 最后默认 type 为 metaclass 来创建 User 75 | -------------------------------------------------------------------------------- /source/c08/p06_orm.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 8.6 通过元素实现ORM 3 | =============================== 4 | 5 | 首先明确需求 6 | 7 | .. code-block:: py 8 | 9 | # 简单定义 10 | class User: 11 | name = CharFiled(db_column="", max_length=32) 12 | age = IntFiled(db_column="", min_value=0, max_value=100) 13 | class Meta: 14 | db_table = 'user' 15 | 16 | # ORM 17 | user = User() 18 | user.name = 'linda' 19 | user.age = 18 20 | user.save() 21 | 22 | 23 | 迷你版 ORM 24 | 25 | .. code-block:: py 26 | 27 | from collections import OrderedDict 28 | 29 | 30 | class Field: 31 | pass 32 | 33 | 34 | class IntField(Field): 35 | def __init__(self, db_column, min_value=0, max_value=100): 36 | self.db_column = db_column 37 | self.min_value = min_value 38 | self.max_value = max_value 39 | self._value = None 40 | 41 | def __get__(self, instance, owner): 42 | return self._value 43 | 44 | def __set__(self, instance, value): 45 | if not isinstance(value, int): 46 | raise TypeError('need int value') 47 | if value < self.min_value or value > self.max_value: 48 | raise ValueError('need [%s, %s] value' % (self.min_value, self.max_value)) 49 | self._value = value 50 | 51 | 52 | class CharField(Field): 53 | def __init__(self, db_column, max_length=32): 54 | self.db_column = db_column 55 | self.max_length = max_length 56 | self._value = None 57 | 58 | def __get__(self, instance, owner): 59 | return self._value 60 | 61 | def __set__(self, instance, value): 62 | if not isinstance(value, str): 63 | raise TypeError('need str value') 64 | if len(value) > self.max_length: 65 | raise ValueError('len need lower than %s' % self.max_length) 66 | self._value = value 67 | 68 | 69 | # 元类注入一系列属性 70 | class MetaClass(type): 71 | def __new__(cls, name, bases, attrs, **kw): 72 | # BaseModel 也会调用 Metaclass,但没有定义 name,age 等属性,可特殊判断 73 | if name == 'BaseModel': 74 | return super().__new__(cls, name, bases, attrs, **kw) 75 | 76 | fields = {} 77 | for key, value in attrs.items(): 78 | if isinstance(value, Field): 79 | fields[key] = value 80 | 81 | attrs_meta = attrs.get('Meta', None) 82 | _meta = {} 83 | db_table = name.lower() 84 | if attrs_meta is not None: 85 | table = getattr(attrs_meta, 'db_table', None) 86 | if not table: 87 | db_table = table 88 | 89 | _meta['db_table'] = db_table 90 | attrs['_meta'] = _meta 91 | attrs['fields'] = fields 92 | if attrs.get('Meta'): 93 | del attrs['Meta'] 94 | return super().__new__(cls, name, bases, attrs, **kw) 95 | 96 | 97 | class BaseModel(metaclass=MetaClass): 98 | def __init__(self, **kw): 99 | for key, value in kw.items(): 100 | setattr(self, key, value) 101 | super().__init__() 102 | 103 | def save(self): 104 | fields = OrderedDict(self.fields) 105 | fields_str = ", ".join([value.db_column for value in fields.values()]) 106 | values_str = ', '.join([str(getattr(self, field)) if not isinstance(value, CharField) 107 | else "'%s'" % str(getattr(self, field)) 108 | for field, value in fields.items()]) 109 | sql = "insert into %s (%s) values (%s)" % (self._meta['db_table'], fields_str, values_str) 110 | print(sql) 111 | # insert into user (name1, age) values ('linda', 20) 112 | 113 | 114 | # 自定义类时写少量属性,元类帮助我们注入很多通用属性 115 | class User(BaseModel): 116 | name = CharField('name1', max_length=16) 117 | age = IntField('age', min_value=0, max_value=100) 118 | 119 | class Meta: 120 | db_table = 'user' 121 | 122 | 123 | if __name__ == '__main__': 124 | user = User(name='linda') 125 | user.age = 20 126 | user.save() 127 | 128 | 129 | ORM 设计思想 130 | 131 | - 数据属性描述符(__set__, __get__) 实现验证操作 132 | - 自定义元类(MetaClass(type)) 实现参数注入 133 | - 自定义 ORM 类(BaseModel) 获取元类注入的参数 进行额外操作 134 | - 自定义元类 注入 objects 135 | - 需特别注意调用层级顺序,__new__ 在 __init__ 之前,所以 __init__ 中可以使用元类注册测参数 136 | -------------------------------------------------------------------------------- /source/c08/p07_conclusion.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 8.7 本章小结 3 | =============================== 4 | -------------------------------------------------------------------------------- /source/c09/function.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ni-ning/AdvancePython/012da5c234a5efba4b4a5d21549aada5ac9d4d6b/source/c09/function.jpg -------------------------------------------------------------------------------- /source/c09/generator.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ni-ning/AdvancePython/012da5c234a5efba4b4a5d21549aada5ac9d4d6b/source/c09/generator.jpg -------------------------------------------------------------------------------- /source/c09/p01_iter_protocol.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 9.1 python中的迭代协议 3 | =============================== 4 | 5 | 什么是迭代协议? 6 | 7 | - Iterable 8 | - Iterator 9 | 10 | 迭代器是什么? 11 | 12 | 迭代器是访问集合内元素的一种方式,一般用来遍历数据。 13 | 迭代器和以下标访问方式不一样,迭代器是不能返回的,迭代器提供了一种惰性访问数据的方式 14 | 15 | .. code-block:: python 16 | 17 | from collections.abc import Iterable, Iterator 18 | a = [1, 2] 19 | print(isinstance(a, Iterable)) 20 | print(isinstance(a, Iterator)) 21 | -------------------------------------------------------------------------------- /source/c09/p02_iterator_iterable.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 9.2 什么是迭代器和可迭代对象 3 | =============================== 4 | 5 | 实现 __iter__ 时,必须返回 Iterator 对象 6 | 7 | .. code-block:: py 8 | 9 | from collections.abc import Iterator 10 | 11 | 12 | class MyIterator(Iterator): 13 | def __init__(self, employee): 14 | self.employee = employee 15 | self.index = 0 16 | 17 | def __next__(self): 18 | # 真正返回迭代值的逻辑 19 | # 迭代器不支持切片,不会接收索引值,只能一步一步走 20 | # 遍历大文件 21 | try: 22 | word = self.employee[self.index] 23 | except IndexError: 24 | raise StopIteration 25 | self.index += 1 26 | return word 27 | 28 | 29 | class Company: 30 | def __init__(self, employee): 31 | self.employee = employee 32 | 33 | # def __iter__(self): 34 | # return 1 # TypeError: iter() returned non-iterator of type 'int' 35 | 36 | # def __iter__(self): 37 | # return self # TypeError: iter() returned non-iterator of type 'Company' 38 | 39 | # 使用内置方法 iter 40 | # def __iter__(self): 41 | # return iter(self.employee) # 42 | 43 | # 使用自定义 MyIterator ****** 44 | def __iter__(self): 45 | return MyIterator(self.employee) # <__main__.MyIterator object at 0x0000013462EF0848> 46 | 47 | def __getitem__(self, index): 48 | return self.employee[index] 49 | 50 | 51 | if __name__ == '__main__': 52 | company = Company(['linda', 'alex', 'catherine']) 53 | my_iterator = iter(company) 54 | print(my_iterator) 55 | # for 循环首先查找 __iter__;如果没有自动生成一个__iter__,里面遍历__getitem__ 56 | # for item in company: 57 | # print(item) 58 | 59 | while True: 60 | try: 61 | print(next(my_iterator)) 62 | except StopIteration: 63 | break 64 | 65 | """ 66 | 迭代器设计模式,不要在Company中实现 __next__ 方法,而要单独实现MyIterator实现,Company中__iter__调用MyIterator就行 67 | """ 68 | 69 | - Comanpy实例化的对象为可迭代对象,可用for循环遍历数据,内部实现了__iter__方法,该方法返回迭代器 70 | - MyIterator实现化对象为迭代器,可用next()获取数值,内部实现了__iter__和__next__方法 71 | -------------------------------------------------------------------------------- /source/c09/p03_generator.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 9.3 生成器函数的使用 3 | =============================== 4 | 5 | 生成器函数,函数里包含 yield 关键字 6 | 7 | - yield 8 | - 不再是普通的函数 9 | 10 | 11 | .. code-block:: py 12 | 13 | def gen_func(): 14 | yield 1 15 | yield 2 16 | yield 3 17 | 18 | # 惰性求值,延迟求值提供了可能性 19 | # 斐波拉契函数 0 1 1 2 3 5 8 ... 20 | def fib(index): 21 | if index <= 2: 22 | return 1 23 | else: 24 | return fib(index-1) + fib(index-2) 25 | 26 | def func(): 27 | return 1 28 | 29 | if __name__ == '__main__': 30 | # 返回为生成器对象,python编译字节码的时候产生 31 | gen = gen_func() 32 | 33 | # 生成器对象也是实现了迭代协议的,可以for循环 34 | for value in gen: 35 | print(value) 36 | 37 | ret = func() 38 | 39 | - 执行生成器函数得到生成器对象,可for循环取值 40 | - 生成器函数可以多次返回值,流程的变化 41 | 42 | .. code-block:: py 43 | 44 | # 获取对应位置的值 45 | def fib(index): 46 | if index <= 2: 47 | return 1 48 | else: 49 | return fib(index-1) + fib(index-2) 50 | 51 | 52 | # 获取整个过程 53 | def fib2(index): 54 | ret_list = [] 55 | n, a, b = 0, 0, 1 56 | while n < index: 57 | ret_list.append(b) 58 | a, b = b, a + b 59 | n += 1 60 | return ret_list 61 | 62 | 63 | # yield 64 | def gen_fib(index): 65 | n, a, b = 0, 0, 1 66 | while n < index: 67 | yield b 68 | a, b = b, a + b 69 | n += 1 70 | 71 | 72 | print(fib(10)) 73 | print(fib2(10)) 74 | for value in gen_fib(10): 75 | print(value) 76 | 77 | 78 | 斐波拉契 1 1 2 3 5 8 ... 79 | 80 | - 根据位置获取对应值 81 | - 根据位置获取所有值 82 | -------------------------------------------------------------------------------- /source/c09/p04_build_generator.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 9.4 python是如何实现生成器的 3 | =============================== 4 | 5 | - 什么场景下运用生成器 6 | - 生成器内部实现原理 7 | - 生成器函数与普通函数区别 8 | 9 | 10 | ------------------------------- 11 | python中函数工作原理 12 | ------------------------------- 13 | python.exe会用一个叫做PyEval_EvalFrameEx(c函数)去执行foo函数 首先会创建一个栈帧(stack_frame),一个上下文 14 | 15 | .. code-block:: py 16 | 17 | import inspect 18 | frame = None 19 | 20 | def foo(): 21 | bar() 22 | 23 | def bar(): 24 | global frame 25 | frame = inspect.currentframe() 26 | 27 | # 查看函数实现原理 28 | # import dis 29 | # print(dis.dis(foo)) 30 | 31 | foo() 32 | print(frame.f_code.co_name) # 函数名 bar 33 | 34 | caller_frame = frame.f_back 35 | print(caller_frame.f_code.co_name) # 函数名 foo 36 | 37 | 38 | python中一切皆对象,栈帧对象中运行foo函数字节码对象 39 | 当foo调用子函数bar,又会创建一个栈帧对象,在此栈帧对象中运行bar函数字节码对象 40 | 41 | 所有的栈帧都是分配再堆内存上(不会自动释放),这就对定了栈帧可以独立于调用者存在;不用于静态语言的调用,静态语言是栈的形式,调用完就自动释放 42 | 43 | .. image:: function.jpg 44 | 45 | ------------------------------- 46 | python中生成器函数工作原理 47 | ------------------------------- 48 | 49 | .. code-block:: py 50 | 51 | def gen_func(): 52 | address = 'China' 53 | yield 1 54 | name = 'linda' 55 | yield 2 56 | age = 20 57 | return 'done' 58 | 59 | 60 | gen = gen_func() 61 | 62 | import dis 63 | print(dis.dis(gen)) 64 | 65 | print(gen.gi_frame.f_lasti) 66 | print(gen.gi_frame.f_locals) 67 | 68 | print('\nfirst value: %s' % next(gen)) 69 | print(gen.gi_frame.f_lasti) 70 | print(gen.gi_frame.f_locals) 71 | 72 | print('\nsecond value: %s' % next(gen)) 73 | print(gen.gi_frame.f_lasti) 74 | print(gen.gi_frame.f_locals) 75 | 76 | 77 | .. image:: generator.jpg 78 | 79 | - 控制整个生成器函数暂定和继续前进 gen.gi_frame.f_lasti 80 | - 整个生成器函数作用域逐渐变化 gen.gi_frame.f_locals 81 | -------------------------------------------------------------------------------- /source/c09/p05_userlist_generator.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 9.5 生成器在UserList中的应用 3 | =============================== 4 | 5 | - from collections import UserList 6 | 7 | .. code-block:: py 8 | 9 | class MyList: 10 | def __init__(self): 11 | self.data = [] 12 | 13 | def __getitem__(self, index): 14 | return self.data[index] 15 | 16 | def __setitem__(self, index, value): 17 | self.data[index] = value 18 | 19 | def insert(self, index, item): 20 | self.data.insert(index, item) 21 | 22 | 23 | ll = MyList() 24 | ll.insert(0, 1) 25 | ll.insert(0, 2) 26 | ll.insert(0, 3) 27 | print(ll.data) 28 | 29 | 30 | - from collections import UserDict 31 | 32 | .. code-block:: py 33 | 34 | class MyDict: 35 | def __init__(self): 36 | self.data = {} 37 | 38 | def __getitem__(self, item): 39 | return self.data[item] 40 | 41 | def __setitem__(self, key, value): 42 | self.data[key] = value 43 | 44 | def update(self, **kw): 45 | for key, value in kw.items(): 46 | self[key] = value 47 | 48 | dd = MyDict() 49 | print(dd.data) 50 | 51 | dd.update(key1='value1', key2='value2') 52 | print(dd['key1']) 53 | print(dd.data) 54 | 55 | 56 | 具体源码分析参考模块 collections 57 | -------------------------------------------------------------------------------- /source/c09/p06_generator_file.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 9.6 生成器如何读取大文件 3 | =============================== 4 | 5 | 场景:500G 文件 特殊只有一行,特殊分割符号 {|} 6 | 7 | .. code-block:: py 8 | 9 | def my_readline(f, newline): 10 | buf = '' 11 | while True: 12 | while newline in buf: 13 | pos = buf.index(newline) 14 | yield buf[:pos] 15 | buf = buf[pos + len(newline):] 16 | chunk = f.read(4096 * 10) 17 | if not chunk: 18 | yield buf 19 | break 20 | buf += chunk 21 | 22 | with open('input') as f: 23 | for line in my_readline(f, '{|}'): 24 | print(line) 25 | -------------------------------------------------------------------------------- /source/c09/p07_conclusion.rst: -------------------------------------------------------------------------------- 1 | =============================== 2 | 9.7 本章小结 3 | =============================== 4 | -------------------------------------------------------------------------------- /source/chapters/p01_introduce.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | 第一章:导论 3 | ============================= 4 | 5 | Introduce 6 | 7 | 8 | .. toctree:: 9 | :maxdepth: 1 10 | :glob: 11 | 12 | ../c01/* 13 | -------------------------------------------------------------------------------- /source/chapters/p02_all_is_object.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | 第二章:Python 一切皆对象 3 | ============================= 4 | 5 | Introduce 6 | 7 | 8 | .. toctree:: 9 | :maxdepth: 1 10 | :glob: 11 | 12 | ../c02/* 13 | -------------------------------------------------------------------------------- /source/chapters/p03_magic_function.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | 第三章:魔法函数 3 | ============================= 4 | 5 | Introduce 6 | 7 | 8 | .. toctree:: 9 | :maxdepth: 1 10 | :glob: 11 | 12 | ../c03/* 13 | -------------------------------------------------------------------------------- /source/chapters/p04_class_object.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | 第四章:深入类和对象 3 | ============================= 4 | 5 | Introduce 6 | 7 | 8 | .. toctree:: 9 | :maxdepth: 1 10 | :glob: 11 | 12 | ../c04/* 13 | -------------------------------------------------------------------------------- /source/chapters/p05_sequeue_class.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | 第五章:自定义序列类 3 | ============================= 4 | 5 | Introduce 6 | 7 | 8 | .. toctree:: 9 | :maxdepth: 1 10 | :glob: 11 | 12 | ../c05/* 13 | -------------------------------------------------------------------------------- /source/chapters/p06_dict_and_set.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | 第六章:深入Python的set和dict 3 | ============================= 4 | 5 | Introduce 6 | 7 | 8 | .. toctree:: 9 | :maxdepth: 1 10 | :glob: 11 | 12 | ../c06/* 13 | -------------------------------------------------------------------------------- /source/chapters/p07_reference_del.rst: -------------------------------------------------------------------------------- 1 | ===================================== 2 | 第七章:对象引用、可变性和垃圾回收 3 | ===================================== 4 | 5 | Introduce 6 | 7 | 8 | .. toctree:: 9 | :maxdepth: 1 10 | :glob: 11 | 12 | ../c07/* 13 | -------------------------------------------------------------------------------- /source/chapters/p08_meta_class.rst: -------------------------------------------------------------------------------- 1 | ===================================== 2 | 第八章:元类编程 3 | ===================================== 4 | 5 | Introduce 6 | 7 | 8 | .. toctree:: 9 | :maxdepth: 1 10 | :glob: 11 | 12 | ../c08/* 13 | -------------------------------------------------------------------------------- /source/chapters/p09_iterator_generator.rst: -------------------------------------------------------------------------------- 1 | ===================================== 2 | 第九章:迭代器和生成器 3 | ===================================== 4 | 5 | Introduce 6 | 7 | 8 | .. toctree:: 9 | :maxdepth: 1 10 | :glob: 11 | 12 | ../c09/* 13 | -------------------------------------------------------------------------------- /source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | import sphinx_rtd_theme 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'AdvancePython' 21 | copyright = '2019, ni-ning' 22 | author = 'ni-ning' 23 | 24 | # The full version, including alpha/beta/rc tags 25 | release = '0.0.1' 26 | 27 | 28 | # -- General configuration --------------------------------------------------- 29 | 30 | # Add any Sphinx extension module names here, as strings. They can be 31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 32 | # ones. 33 | extensions = [ 34 | ] 35 | 36 | # Add any paths that contain templates here, relative to this directory. 37 | templates_path = ['_templates'] 38 | 39 | 40 | # The suffix of source filenames. 41 | source_suffix = '.rst' 42 | 43 | # The master toctree document. 44 | master_doc = 'index' 45 | 46 | # The language for content autogenerated by Sphinx. Refer to documentation 47 | # for a list of supported languages. 48 | # 49 | # This is also used if you do content translation via gettext catalogs. 50 | # Usually you set "language" from the command line for these cases. 51 | language = 'zh_CN' 52 | 53 | # List of patterns, relative to source directory, that match files and 54 | # directories to ignore when looking for source files. 55 | # This pattern also affects html_static_path and html_extra_path. 56 | exclude_patterns = [] 57 | 58 | 59 | # -- Options for HTML output ------------------------------------------------- 60 | 61 | # The theme to use for HTML and HTML Help pages. See the documentation for 62 | # a list of builtin themes. 63 | # 64 | html_theme = "sphinx_rtd_theme" 65 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 66 | 67 | # Add any paths that contain custom static files (such as style sheets) here, 68 | # relative to this directory. They are copied after the builtin static files, 69 | # so a file named "default.css" will overwrite the builtin "default.css". 70 | html_static_path = ['_static'] 71 | -------------------------------------------------------------------------------- /source/index.rst: -------------------------------------------------------------------------------- 1 | .. python3-cookbook documentation master file, created by 2 | sphinx-quickstart on Tue Aug 19 03:21:45 2014. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | ================================================ 7 | Python 高级编程 8 | ================================================ 9 | 10 | Contents 11 | 12 | .. toctree:: 13 | :maxdepth: 2 14 | :glob: 15 | 16 | chapters/* 17 | aboutme 18 | roadmap 19 | -------------------------------------------------------------------------------- /source/roadmap.rst: -------------------------------------------------------------------------------- 1 | =========== 2 | Roadmap 3 | =========== 4 | 5 | 2019/12/02 - 2019/12/31: 6 | 7 | :: 8 | 9 | | github项目搭建,readthedocs文档生成。 10 | | 整个项目的框架完成 11 | 12 | 13 | 14 | --------------------------------------------------------------------------------