├── setup.py ├── test.py ├── 继承法 └── __init__.py └── readme.md /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | 4 | setuptools.setup( 5 | name='inherit', 6 | version='0.0.1', 7 | author='RimoChan', 8 | author_email='the@librian.net', 9 | description='inherit', 10 | long_description=open('readme.md', encoding='utf8').read(), 11 | long_description_content_type='text/markdown', 12 | url='https://github.com/RimoChan/inherit', 13 | packages=[ 14 | '继承法', 15 | ], 16 | classifiers=[ 17 | 'Programming Language :: Python :: 3', 18 | 'Operating System :: OS Independent', 19 | ], 20 | install_requires=[ 21 | 'jieba>=0.42.1', 22 | ], 23 | ) -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | from 继承法 import 长子继承制, 分割继承制, 斯堪的纳维亚选举制 2 | 3 | 4 | 5 | for 制 in (长子继承制, 分割继承制, 斯堪的纳维亚选举制): 6 | @制 7 | class A: 8 | x = 100 9 | y = 200 10 | z = 300 11 | 12 | class B(A): 13 | x = y = z = 9 14 | 15 | class C(A): 16 | x = y = z = 0 17 | 18 | print('\n' + '='*50 + '\n' + 制.__name__ + '\n' + '='*50) 19 | 20 | print(f'{A.x=}, {A.y=}, {A.z=}') 21 | print(f'{B.x=}, {B.y=}, {B.z=}') 22 | print(f'{C.x=}, {C.y=}, {C.z=}') 23 | print('====继承====') 24 | A.__del__() 25 | print(f'{B.x=}, {B.y=}, {B.z=}') 26 | print(f'{C.x=}, {C.y=}, {C.z=}') 27 | 28 | 29 | -------------------------------------------------------------------------------- /继承法/__init__.py: -------------------------------------------------------------------------------- 1 | import gc 2 | import random 3 | 4 | 5 | class eva: 6 | ... 7 | 8 | 9 | class qtype(type): 10 | ... 11 | 12 | 13 | def _void(*li, **d): 14 | ... 15 | 16 | 17 | def _继承法添加(cls, f): 18 | class qqtype(qtype): 19 | def __del__(self): 20 | self.__del__ = _void 21 | f(self) 22 | base = cls.__bases__ 23 | if base == (object,): 24 | base = eva, 25 | return qqtype(cls.__name__, base, dict(cls.__dict__)) 26 | 27 | 28 | def _均分(继承人, 资源): 29 | n = len(继承人) 30 | kv = [(k, v) for k, v in 资源.items() if not k.startswith('_')] 31 | for i, (k, v) in enumerate(kv): 32 | setattr(继承人[i % n], k, v) 33 | 34 | 35 | def _亲戚(x): 36 | v = set() 37 | 38 | def 敌法师(x): 39 | if x in v or x is eva: 40 | return 41 | v.add(x) 42 | for i in [*x.__bases__, *x.__subclasses__()]: 43 | 敌法师(i) 44 | 敌法师(x) 45 | v.remove(x) 46 | return [i for i in v if not (isinstance(x, qtype) and '__del__' in i.__dict__ and i.__del__ is _void)] 47 | 48 | 49 | def 长子继承制(x): 50 | def f(x): 51 | sub = x.__subclasses__() 52 | if sub: 53 | 继承人 = [sub[0]] 54 | else: 55 | 继承人 = [x.__bases__[0]] 56 | _均分(继承人, x.__dict__) 57 | return _继承法添加(x, f) 58 | 59 | 60 | def 分割继承制(x): 61 | def f(x): 62 | sub = x.__subclasses__() 63 | if sub: 64 | 继承人 = sub 65 | else: 66 | 继承人 = [x.__bases__[0]] 67 | _均分(继承人, x.__dict__) 68 | return _继承法添加(x, f) 69 | 70 | 71 | def 斯堪的纳维亚选举制(x): 72 | def 喜爱度(a, b): 73 | return sum([int(i in b.__name__) for i in a.__name__]) + random.random()/10 74 | 75 | def f(x): 76 | 票数 = {x: 0 for x in _亲戚(x)} 77 | if not 票数: 78 | _均分([x.__bases__[0]], x.__dict__) 79 | return 80 | for i in gc.get_objects(): 81 | if isinstance(i, type): 82 | 投给 = max(票数, key=lambda x: 喜爱度(i, x)) 83 | # print(f'{i.__name__} 投给 {投给.__name__}') 84 | 票数[投给] += 1 85 | 继承人 = [max(票数, key=lambda k: 票数[k])] 86 | for k, v in 票数.items(): 87 | print(f'{k.__name__}: {v}票') 88 | _均分(继承人, x.__dict__) 89 | return _继承法添加(x, f) 90 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 【教程】莉沫酱教你学继承! 2 | 3 | 众所周知,类的继承就是说当一个类死亡的时候,它的子类会获得它拥有的资源。 4 | 5 | 根据类的继承法不同,各个子类能获得的资源也不同。 6 | 7 | 8 | ## 继承法的类型 9 | 10 | 在解释继承法之前,我们先定义三个类,一个父类`A`,和它的子类`B`、`C`。 11 | 12 | 它们都拥有`x`、`y`、`z`三个属性。 13 | 14 | ```python 15 | class A: 16 | x = 100 17 | y = 200 18 | z = 300 19 | class B(A): 20 | x = y = z = 9 21 | class C(A): 22 | x = y = z = 0 23 | ``` 24 | 25 | 26 | ### 长子继承制 27 | 28 | 假如父类`A`采用了`长子继承制`,那么在继承中,所有资源都会被交给其最年长的子类,其他子类什么也得不到。 29 | 30 | ```python 31 | @长子继承制 32 | class A: 33 | x = 100 34 | y = 200 35 | z = 300 36 | ``` 37 | 38 | 在使用了`长子继承制`之后,我们杀掉父类,看看子类的资源有什么变化—— 39 | 40 | ```python 41 | print(f'{A.x=}, {A.y=}, {A.z=}') 42 | print(f'{B.x=}, {B.y=}, {B.z=}') 43 | print(f'{C.x=}, {C.y=}, {C.z=}') 44 | print('====继承====') 45 | A.__del__() 46 | print(f'{B.x=}, {B.y=}, {B.z=}') 47 | print(f'{C.x=}, {C.y=}, {C.z=}') 48 | ``` 49 | 50 | 可以看到,这个时候父类的所有属性都被第一个子类——也就是`B`——继承了。 51 | 52 | ```text 53 | A.x=100, A.y=200, A.z=300 54 | B.x=9, B.y=9, B.z=9 55 | C.x=0, C.y=0, C.z=0 56 | ====继承==== 57 | B.x=100, B.y=200, B.z=300 58 | C.x=0, C.y=0, C.z=0 59 | ``` 60 | 61 | 62 | ### 分割继承制 63 | 64 | 但是在软件开发的早期,我们无法`import 长子继承制`,因此我们得考虑一些其他的继承法,比如`分割继承制`。 65 | 66 | 在`分割继承制`中,父类的所有资源都会被划分给其子类。 67 | 68 | ```python 69 | @分割继承制 70 | class A: 71 | x = 100 72 | y = 200 73 | z = 300 74 | ``` 75 | 76 | 在继承之后,子类`B`获得了属性`x`和`z`,而子类`C`获得了属性`y`。 77 | 78 | ``` 79 | A.x=100, A.y=200, A.z=300 80 | B.x=9, B.y=9, B.z=9 81 | C.x=0, C.y=0, C.z=0 82 | ====继承==== 83 | B.x=100, B.y=9, B.z=300 84 | C.x=0, C.y=200, C.z=0 85 | ``` 86 | 87 | 88 | ### 斯堪的纳维亚选举制 89 | 90 | 斯堪的纳维亚选举制是北欧的维京程序员喜欢的继承法。 91 | 92 | 在这种制度下,程序中所有没有被回收的类都可以在该类的亲戚中提名一位继承人,最终由投票得分最高的类继承所有资源。 93 | 94 | ```python 95 | @斯堪的纳维亚选举制 96 | class A: 97 | x = 100 98 | y = 200 99 | z = 300 100 | ``` 101 | 102 | 在类`A`死亡时,所有的类都会在类`B`和类`C`中投票。尽管在这个例子里`B`和`C`都是`A`的子类,实际上其他类也能投给`A`的兄弟等能DFS到的类。 103 | 104 | 通常,其他类会倾向于投给名字和自己长得比较像的类,一次典型的选举过程如下: 105 | 106 | 107 | ```text 108 | ====继承==== 109 | _OrderedDictKeysView 投给 C 110 | _OrderedDictItemsView 投给 C 111 | _OrderedDictValuesView 投给 C 112 | _Link 投给 C 113 | Counter 投给 C 114 | ChainMap 投给 C 115 | UserDict 投给 C 116 | UserList 投给 C 117 | UserString 投给 C 118 | partialmethod 投给 C 119 | CacheInfo 投给 C 120 | _HashedSeq 投给 B 121 | singledispatchmethod 投给 C 122 | cached_property 投给 B 123 | AbstractContextManager 投给 C 124 | AbstractAsyncContextManager 投给 C 125 | ContextDecorator 投给 C 126 | 127 | ... 128 | 129 | C: 142票 130 | B: 133票 131 | B.x=9, B.y=9, B.z=9 132 | C.x=100, C.y=200, C.z=300 133 | ``` 134 | 135 | 最终类`C`在选举中胜出,并继承了其父类`A`的所有属性。 136 | 137 | 138 | ## 使用方法 139 | 140 | 首先你需要1个3.6以上版本的Python,然后使用pip安装—— 141 | 142 | ```sh 143 | pip install git+https://github.com/RimoChan/inherit.git 144 | ``` 145 | 146 | 然后你就可以在你的代码里使用继承法了,耶! 147 | 148 | ```python 149 | from 继承法 import 长子继承制, 分割继承制, 斯堪的纳维亚选举制 150 | ``` 151 | 152 | 153 | ## 赞助 154 | 155 | 如果你觉得学习继承法对你的工作或学习有帮助(?),欢迎给作者介绍一些可爱的萝莉朋友。 156 | 157 | 就这样,大家88。 158 | --------------------------------------------------------------------------------