python隐式调用_python 的隐式指针特征与class inheritance
python的隐式指针特征
pointer是C/C++的里非常熟悉也容易令人困惑的一个功能点,python里的变量赋值一般表现也和指针类似,但是没有显式地语法指出,·在这里我用自己的理解做一个比喻来帮助大家理解。
当我们写下一行语句,比如a=1 (python)或者int a=1(C++),电脑内存到底做了什么呢?这里的数据“1”在电脑内存里实际上是一个二级制序列,任何数据最终都以这种形式存储。而序列储存的位置,则是这份数据的地址,这个地址在内存中,通过“a”这个代号来获取。
所以,如果把地址比作是一栋房子,数据就像是房子里装的家具,而房子门口的门牌号,就是地址的名字。只不过在程序里,一个房子可以有多个门牌号,共同指向同一个房子,但是不能有多个房子,共享同一个门牌号。
a=1,a=2,是更改了a对应房子里存储的东西(数据)
a=1,b=a,是赋予“1”这个数据所在的房子两块门牌号(a,b)
此时修改a,b任意变量名的值,a、b的值均被修改,换句话说,python赋值默认是指针赋值,但是在class内赋值、copy赋值例外。
python class及inheritance
为什么需要class?
答案是我们需要用数据结构来存储数据的关系,而不是记在脑子里,或者是靠修改变量名称。比如我们需要程序计算,高中生的各科成绩求和。显然,一个简单的sum函数可以完成这样的运算,再来一个for循环,对所有的学生都算一遍。但是这样做之后,我们无法知道把学生的名字、单科成绩、各科成绩对应起来,虽然他们在循环中的次序是对应的。如果代码里稍有不慎修改了成绩的原始排序,就会出现驴唇对马嘴的情况。
class 作为一种复杂的数据结构,能够帮我们记录下一个综合体及其各个属性的关系,以支持更复杂的操作。
此外还能够提高代码可读性,减少重复代码块粘贴,提高效率。
class 数据结构还能继承,不断延展功能的同时,不干扰旧的代码功能,用尽量少的代码支持更多操作。
基本语法
class A(object):
def __init__(self):
print('A init called')
self.num=1
class B(A):
def __init__(self):
print('B init called')
A.__init__(self)
a=A()
b=B()
b.num
首先我们定了一个class 结构A,它的初始化/构造函数(类似于C++里的constructor)打印一句话,并且给自己多了一个成员 num,值为1
然后定义了一个class 结构B,B继承了A,B的构造函数打印了一句话,然后调用了A的构造函数,这里的调用,等同于把A的_init_函数完全复制到B里,并且执行,也就是继承了A的init
结果是
A init called #a=A()
B init called#b=B()的构造函数print
A init called#b的init里 call A的init,并且给B增加了一个成员self.num
1 #b.num
更规范的继承写法
上边的例子中,在B的init我们指定继承A的init,形如baseclass._init_(self),这种写法在一层继承中没有问题,但是在多层继承中,会丧失灵活性,因为此时,parent class被hard-coded,而不是按照继承链自动追溯,丧失了灵活性。
参考这篇文章的例子What is the difference between old style and new style classes in Python?stackoverflow.com
class SomeBaseClass(object):
def __init__(self):
print('SomeBaseClass.__init__(self) called')
class UnsuperChild(SomeBaseClass):
def __init__(self):
print('UnsuperChild.__init__(self) called')
SomeBaseClass.__init__(self)
class SuperChild(SomeBaseClass):
def __init__(self):
print('SuperChild.__init__(self) called')
super(SuperChild, self).__init__()
上边的代码中,Unsuperchild class的继承写法是固定的,和上边的class B一样。而superchild class的继承方法是使用了super(括号可以省略)关键词,两者都继承自somebaseclass。那么到底有什么后果呢?我们再加入一层继承
class InjectMe(SomeBaseClass):
def __init__(self):
print('InjectMe.__init__(self) called')
super(InjectMe, self).__init__()
class UnsuperInjector(UnsuperChild, InjectMe): pass
class SuperInjector(SuperChild, InjectMe): pass
InjectMe class 也继承自somebaseclass。同时UnsuperInjector继承UnsuperChild,和InjectMe,SuperInjector继承SuperChild,和InjectMe
现在的继承关系有三级
somebaseclass (grandparent)
unsuperchild superchild InjectMe (parent)
unsuperinjector superinjector (child)
根据Method Resolution Order (MRO)法则,当我生成一个第三级class 的实例时,会按照“先左后右再向上”的顺序调用super
比如我创建一个UnsuperInjector的实例,它的左边parent是UnsuperChild,先调用了UnsuperChild的init,UnsuperChild的init里写了,固定调用sombaseclass 的init,因此,不用super()关键字继承时,会受到固定parent class的限制,不会再调用injectme class
o = UnsuperInjector()
# 打印 UnsuperChild.__init__(self) called
#打印 SomeBaseClass.__init__(self) called
而如果run下边一句结果就不同
o2 = SuperInjector()
SuperChild.__init__(self) called
InjectMe.__init__(self) called
SomeBaseClass.__init__(self) called
SuperInjector上一级左边是SuperChild,SuperChild的init里有super().init,,右边是InjectMe,也有super().init,因此SuperChild的super 指向InjectMe,InjectMe的super指向SomeBaseClass,因此打印结果如上边代码块所示。
总结
在multiple inheritance模式下,super().继承方法能够避免固定继承导致其他parent class继承失效的问题,增加了代码灵活性。同时注意继承的顺序由MRO决定,遵循同级先左后右,再增加深度的原则。
python隐式调用_python 的隐式指针特征与class inheritance相关推荐
- python pointer_python 的隐式指针特征与class inheritance
python的隐式指针特征 pointer是C/C++的里非常熟悉也容易令人困惑的一个功能点,python里的变量赋值一般表现也和指针类似,但是没有显式地语法指出,·在这里我用自己的理解做一个比喻来帮 ...
- python html模块调用_Python html 模块简介
1 html.entities HTML 实体 name2codepoint 将 HTML 实体名称映射到 Unicode 代码点: html5 将 HTML5 命名字符引用映射到等效的 Unicod ...
- python竖式计算_Python 模拟竖式大数乘法
python内置了大数运算,非常方便, 无聊写了个模拟竖式乘法的小程序,可以计算任意位数乘法. python爱好者,欢迎交流: http://goo.gl/tzvOu 1.[代码]运行结果及时间 12 ...
- python列表推导式格式_Python列表推导式(for表达式)及用法
for 表达式(列表推导式)用于利用其他区间.元组.列表等可迭代对象创建新的列表. for 表达式的语法格式如下:[表达式 for 循环计数器 in 可迭代对象] 从上面的语法格式可以看出,for 表 ...
- python if else用法_python列表推导式中使用if-else
今天在处理自动化邮件数据时碰到数据行中包含字符串后,从hive中拿到的整数型数据自动转化成了浮点数,严重影响美观性.因此想到了用列表推导式来做转化,将其中的数字型数据全部转化为整型,而字符型数据保留原 ...
- python列表生成器语法_python列表生产式和生成器
1.列表生成式:通过简洁的语法可以对一组元素进行过滤 格式:[exp for val in collection if condition] 例子1: a = [x*xforxinxrange(1,1 ...
- python 阴阳师 识别图像_Python采集阴阳师式神全图鉴图片
https://yys.res.netease.com/pc/zt/20161108171335/data/shishen_big_beforeAwake/201.png https://yys.re ...
- python滑动验证码处理_python+selenium滑动式验证码解决办法
from selenium importwebdriverfrom selenium.webdriver.support.ui import WebDriverWait #等待元素加载的 from s ...
- python怎么学精_python笔记 对比式学习
适合java.js都学过的 -常用 1.计算长度使用len(值) 2.在字符串前加r可以忽略字符串内的转义字符 3.区间范围为左闭右开,包含左边不包含右边 -判断 1.else if为elif 2.w ...
- python什么是调用_Python中包(package)的调用方式
一.什么是Python Package 如何区分你看到的目录是一个Python Package包呢?其实很简单,你只要看这个名录下是否有"__init__.py"这个文件就好了,如 ...
最新文章
- ireport如何给static text加边框_html amp;amp; css 解决li浮动边框为2的问题
- [register]-ARMV8系统中通用寄存器和系统寄存器的介绍和总结
- [C#] 连接数据库并验证用户名和密码
- 【机器学习基础】数学推导+纯Python实现机器学习算法15:GBDT
- CSS各种选择符的优先级
- 多兼容的JS获取鼠标坐标
- CSS教程:实例讲解定位Position
- 从master-worker模型看团队管理
- 俄罗斯方块(C/C++)
- java 改变字体大小_java – 根据屏幕大小更改字体大小
- 让电脑死机c语言,秘技:如何悄无声息的让一台电脑死机
- 关于重装系统后部分文件呈绿色的原因
- 【spring_Cloud】java.lang.IllegalStateException: Failed to introspect Class [org.springframework.cloud
- Node.js(三)路由器、中间件、MySQL模块、RESTful接口
- golang 实现时间差
- 【资源总结】前端资源收集
- LoRa 节点侧学习笔记_汇总
- 域名到期怎么办?【企业邮箱申请】
- aws服务器使用root+密码登陆
- 第三代英特尔 至强 可扩展处理器(Ice Lake)和英特尔 深度学习加速助力阿里巴巴 Transformer 模型性能提升