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相关推荐

  1. python pointer_python 的隐式指针特征与class inheritance

    python的隐式指针特征 pointer是C/C++的里非常熟悉也容易令人困惑的一个功能点,python里的变量赋值一般表现也和指针类似,但是没有显式地语法指出,·在这里我用自己的理解做一个比喻来帮 ...

  2. python html模块调用_Python html 模块简介

    1 html.entities HTML 实体 name2codepoint 将 HTML 实体名称映射到 Unicode 代码点: html5 将 HTML5 命名字符引用映射到等效的 Unicod ...

  3. python竖式计算_Python 模拟竖式大数乘法

    python内置了大数运算,非常方便, 无聊写了个模拟竖式乘法的小程序,可以计算任意位数乘法. python爱好者,欢迎交流: http://goo.gl/tzvOu 1.[代码]运行结果及时间 12 ...

  4. python列表推导式格式_Python列表推导式(for表达式)及用法

    for 表达式(列表推导式)用于利用其他区间.元组.列表等可迭代对象创建新的列表. for 表达式的语法格式如下:[表达式 for 循环计数器 in 可迭代对象] 从上面的语法格式可以看出,for 表 ...

  5. python if else用法_python列表推导式中使用if-else

    今天在处理自动化邮件数据时碰到数据行中包含字符串后,从hive中拿到的整数型数据自动转化成了浮点数,严重影响美观性.因此想到了用列表推导式来做转化,将其中的数字型数据全部转化为整型,而字符型数据保留原 ...

  6. python列表生成器语法_python列表生产式和生成器

    1.列表生成式:通过简洁的语法可以对一组元素进行过滤 格式:[exp for val in collection if condition] 例子1: a = [x*xforxinxrange(1,1 ...

  7. python 阴阳师 识别图像_Python采集阴阳师式神全图鉴图片

    https://yys.res.netease.com/pc/zt/20161108171335/data/shishen_big_beforeAwake/201.png https://yys.re ...

  8. python滑动验证码处理_python+selenium滑动式验证码解决办法

    from selenium importwebdriverfrom selenium.webdriver.support.ui import WebDriverWait #等待元素加载的 from s ...

  9. python怎么学精_python笔记 对比式学习

    适合java.js都学过的 -常用 1.计算长度使用len(值) 2.在字符串前加r可以忽略字符串内的转义字符 3.区间范围为左闭右开,包含左边不包含右边 -判断 1.else if为elif 2.w ...

  10. python什么是调用_Python中包(package)的调用方式

    一.什么是Python Package 如何区分你看到的目录是一个Python Package包呢?其实很简单,你只要看这个名录下是否有"__init__.py"这个文件就好了,如 ...

最新文章

  1. ireport如何给static text加边框_html amp;amp; css 解决li浮动边框为2的问题
  2. [register]-ARMV8系统中通用寄存器和系统寄存器的介绍和总结
  3. [C#] 连接数据库并验证用户名和密码
  4. 【机器学习基础】数学推导+纯Python实现机器学习算法15:GBDT
  5. CSS各种选择符的优先级
  6. 多兼容的JS获取鼠标坐标
  7. CSS教程:实例讲解定位Position
  8. 从master-worker模型看团队管理
  9. 俄罗斯方块(C/C++)
  10. java 改变字体大小_java – 根据屏幕大小更改字体大小
  11. 让电脑死机c语言,秘技:如何悄无声息的让一台电脑死机
  12. 关于重装系统后部分文件呈绿色的原因
  13. 【spring_Cloud】java.lang.IllegalStateException: Failed to introspect Class [org.springframework.cloud
  14. Node.js(三)路由器、中间件、MySQL模块、RESTful接口
  15. golang 实现时间差
  16. 【资源总结】前端资源收集
  17. LoRa 节点侧学习笔记_汇总
  18. 域名到期怎么办?【企业邮箱申请】
  19. aws服务器使用root+密码登陆
  20. 第三代英特尔 至强 可扩展处理器(Ice Lake)和英特尔 深度学习加速助力阿里巴巴 Transformer 模型性能提升

热门文章

  1. 【代码笔记】Web-JavaScript-JavaScript 运算符
  2. 九度OJ 1255:骰子点数概率 (递归、DP)
  3. javascript 函数2——对象排序
  4. VC++ 6.0 快捷键
  5. 水印代码WPF 实例下载
  6. linq to sql 语法 学习笔记(1)
  7. java垃圾收集算法、标记-清除算法、复制算法、标记-整理清除、分代收集算法
  8. necos 分布式配置中心 配置方法 动态修改值 切换生产环境
  9. spring扩展点四:SmartInitializingSingleton 补充
  10. Spring整合MyBatis之MapperFactoryBean