基于tensorflow __init__、build 和call的使用小结


Posted in Python onFebruary 26, 2021

1.介绍

在使用tf构建网络框架的时候,经常会遇到__init__、build 和call这三个互相搭配着使用,那么它们的区别主要在哪里呢?

1)__init__主要用来做参数初始化用,比如我们要初始化卷积的一些参数,就可以放到这里面

2)call可以把类型的对象当做函数来使用,这个对象可以是在__init__里面也可以是在build里面

3)build一般是和call搭配使用,这个时候,它的功能和__init__很相似,当build中存放本层需要初始化的变量,当call被第一次调用的时候,会先执行build()方法初始化变量,但后面再调用到call的时候,是不会再去执行build()方法初始化变量

2.代码

class RB(tf.keras.layers.Layer): 
 def __init__(self, num_filters, *args, **kwargs):
 self.num_filters = num_filters
 super(RB, self).__init__(*args, **kwargs)
 #按需求添加卷积
 def build(self, input_shape):
 #按需求添加卷积
 self._layers = [
 ]
 super(RB, self).build(input_shape)
 
 def call(self, tensor):
 for layer in self._layers:
  tensor = layer(tensor) 
class DecodeNet(tf.keras.layers.Layer):
 
 def __init__(self, num_filters, *args, **kwargs):
 self.num_filters = num_filters
 super(DecodeNet, self).__init__(*args, **kwargs)
 self.rb_block0 = RB(self.num_filters)
 self.rb_block1 = RB(self.num_filters)
 self.rb_block2 = RB(self.num_filters)
 
 def build(self, input_shape):
 self._layers = [
  RB(self.num_filters),
  RB(self.num_filters),
  RB(self.num_filters),
 ]
 super(DecodeNet, self).build(input_shape)
 
 def call(self, tensor):
 tensor = self.rb_block0(tensor)
 tensor = self.rb_block1(tensor)
 for layer in self._layers:
  tensor = layer(tensor)
 tensor = self.rb_block2(tensor)
 return tensor

补充:Python类中的__init__() 和 self 的解析

1、Python中self的含义

self,英文单词意思很明显,表示自己,本身。

此处有几种潜在含义:

1.这里的自己,指的是,实例Instance本身。

2.同时, 由于说到“自己”这个词,都是和相对而言的“其他”而说的;而此处的其他,指的是,类Class,和其他变量,比如局部变量,全局变量等。

此处的self,是个对象(Object),是当前类的实例。

因此,对应的self.valueName 和 self.function()中的valueName:表示self对象,即实例的变量。与其他的,Class的变量,全局的变量,局部的变量,是相对应的。

function:表示是调用的是self对象,即实例的函数。与其他的全局的函数,是相对应的。

2、Python中为何要有self

那就是:

在类的代码(函数)中,需要访问当前的实例中的变量和函数的,即,访问Instance中的:

对应的变量(属性,property):Instance.ProperyNam,去读取之前的值和写入新的值

调用对应函数(function):Instance.function(),即执行对应的动作

-> 而需要访问实例的变量和调用实例的函数,当然需要对应的实例Instance对象本身

-> 而Python中就规定好了,函数的第一个参数,就必须是实例对象本身,并且建议,约定俗成,把其名字写为self

-> 所以,我们需要self(需要用到self)

而如果没有用到self,即代码中,去掉self后,那种写法所使用到的变量,实际上不是你所希望的,不是真正的实例中的变量和函数,而是的访问到了其他部分的变量和函数了。甚至会由于没有合适的初始化实例变量,而导致后续无法访问的错误。

下面,就通过代码,来演示,如果去掉self,或者没有合理的使用self,会出现哪些错误。

3、首先来看一下__init__()和self对象

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: antcolonies 
class Person(object):
 def __init__(self, name, lang, website):
  self.name = name
  self.lang = lang
  self.website = website
 
  print('self: ', self)
  print('type of self: ', type(self))
'''
未实例化时,运行程序,构造方法没有运行
''' 
p = Person('Tim', 'English', 'www.universal.com') 
'''实例化后运行的结果
self: <__main__.Person object at 0x00000000021EAF98>
type of self: <class '__main__.Person'>
'''

可以看出self为实例变量p,是一个Person类型的对象。

class Dog(object):  
 def __init__(self,name,dog_type):
  self.name = name
  self.type = dog_type 
 def sayhi(self):
  print("hello,I am a dog, my name is ",self.name) 
 
d = Dog('LiChuang',"京巴")   # 实例化
d.sayhi()

以下是d = Dog('LiChuang',"京巴")实例化的示意图:

基于tensorflow __init__、build 和call的使用小结

4、如果没有在__init__中初始化对应的实例变量的话,导致后续引用实例变量会出错

如下代码,完整的演示了,如果没有在类Class的最初的__init__函数中,正确的初始化实例变量,则会导致后续没有变量可用,因而出现AttributeError的错误:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: antcolonies 
name = 'whole global name'
'''
注:此处全局的变量名,写成name,只是为了演示而用
实际上,好的编程风格,应该写成gName之类的名字,
以表示该变量是Global的变量
''' 
class Person(object):
 def __init__(self, newPersonName):
  # self.name = newPersonName
  '''
  如果此处不写成self.name
  那么此处的name,只是__init__函数中的局部临时变量name而已
  和全局中的name,没有半毛钱关系
  '''
  name = newPersonName
  '''
  此处只是为了代码演示,而使用了局部变量name,
  不过需要注意的是,此处很明显,由于接下来的代码也没有利用到此处的局部变量name
  则就导致了,此处的name变量,实际上被浪费了,根本没有利用到
  '''
 def sayYourName(self):
  '''
  此处由于找不到实例中的name变量,所以会报错:
  AttributeError: Person instance has no attribute 'name'
  '''
  print('My name is %s' %self.name)
 
def selfAndInitDemo():
 personInstance = Person('Tim')
 personInstance.sayYourName() 
if __name__ == '__main__':
 selfAndInitDemo()
 
''' 未使用self.name时抛异常
Traceback (most recent call last):
 File "E:/python14_workspace/s14/day06/test_1.py", line 18, in <module>
 selfAndInitDemo()
 File "E:/python14_workspace/s14/day06/test_1.py", line 15, in selfAndInitDemo
 personInstance.sayYourName()
 File "E:/python14_workspace/s14/day06/test_1.py", line 11, in sayYourName
 print('My name is %s' %self.name)
AttributeError: 'Person' object has no attribute 'name'
'''

从上述代码可见,由于在类的初始化(实例化)的__init__函数中,没有给self.name设置值,使得实例中,根本没有name这个变量,导致后续再去访问self.name,就会出现AttributeError的错误了。

对应的,如果写成self.name,则意思就正确了,就是初始化的时候,给实例中新增加,并且正常设置了正确的值newPersionName了,所以后续再去通过self.name,就可以访问到,当前实例中正确的变量name了。

相应的正确写法的代码如下:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: antcolonies 
name = 'whole global name'
'''
注:此处全局的变量名,写成name,只是为了演示而用
实际上,好的编程风格,应该写成gName之类的名字,
以表示该变量是Global的变量
''' 
class Person(object):
 def __init__(self, newPersonName):
  self.name = newPersonName
  '''
  此处正确的,通过访问self.name的形式,实现了:
   1.给实例中,增加了name变量
   2.并且给name赋了初值,为newPersionName
  '''
 def sayYourName(self):
  '''
  此处由于开始正确的初始化了self对象,使得其中有了name变量,
  所以此处可以正确访问了name值了
  '''
  print('My name is %s' %self.name)
 
def selfAndInitDemo():
 personInstance = Person('Tim')
 personInstance.sayYourName()
 
if __name__ == '__main__':
 selfAndInitDemo() 
'''My name is Tim'''

5、在函数中,使用对应的变量

虽然代码是可以运行的,但是实际上却是使用的,不是实例中的变量

有时候,虽然你写的代码,可以运行,但是使用到的变量,由于没有加self,实际上是用到的不是实例的变量,而是其他的变量。

此类问题,主要和Python中的变量的作用域有关,但是此处例子中,也和是否使用self有关:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: antcolonies 
name = 'whole global name'
'''
注:此处全局的变量名,写成name,只是为了演示而用
实际上,好的编程风格,应该写成gName之类的名字,
以表示该变量是Global的变量
'''
class Person(object):
 name = 'class global name' 
 def __init__(self, newPersonName):
  # self.name = newPersonName
  '''
  此处,没有使用self.name
  而使得此处的name,实际上仍是局部变量name
  虽然此处赋值了,但是后面没有被利用到,属于被浪费了的局部变量name
  '''
  name = newPersonName
 def sayYourName(self):
  '''
  此处,之所以没有像之前一样出现:
  AttributeError: Person instance has no attribute 'name'
  那是因为,虽然当前的实例self中,没有在__init__中初始化对应的name变量,实例self中没有对应的name变量
  但是由于实例所对应的类Person,有对应的name变量,所以也是可以正常执行代码的
  对应的,此处的self.name,实际上是Person.name
  '''
  print('My name is %s' %self.name)
  print('Name within class Person is actually the global name: %s' %name)
  print("Only access Person's name via Person.name = %s" %(Person.name))
 
def selfAndInitDemo():
 personInstance = Person('Tim')
 personInstance.sayYourName()
 print('whole global name is %s' %name)
 
if __name__ == '__main__':
 selfAndInitDemo()
'''
My name is class global name
Name within class Person is actually the global name: whole global name
Only access Person's name via Person.name = class global name
whole global name is whole global name
'''

其中,可见,此处开始__init__中,没有给self实例初始化对应的name,

而后面的函数sayYourName中,虽然可以调用到self.name而没有出现AttributeError错误,

但是实际上此处的值,不是所期望的,传入的name,即"Tim",而是类中的name的值,即"class global name"。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。如有错误或未考虑完全的地方,望不吝赐教。

Python 相关文章推荐
Python中的一些陷阱与技巧小结
Jul 10 Python
python利用urllib和urllib2访问http的GET/POST详解
Sep 27 Python
Python基于lxml模块解析html获取页面内所有叶子节点xpath路径功能示例
May 16 Python
Python 加密与解密小结
Dec 06 Python
python3中类的继承以及self和super的区别详解
Jun 26 Python
tensorflow实现打印ckpt模型保存下的变量名称及变量值
Jan 04 Python
django 链接多个数据库 并使用原生sql实现
Mar 28 Python
python requests.get带header
May 05 Python
Python接口测试数据库封装实现原理
May 09 Python
keras导入weights方式
Jun 12 Python
Python HTMLTestRunner如何下载生成报告
Sep 04 Python
Python绘制分类图的方法
Apr 20 Python
python实现MySQL指定表增量同步数据到clickhouse的脚本
Feb 26 #Python
详解python的xlwings库读写excel操作总结
Feb 26 #Python
pytorch 中forward 的用法与解释说明
Feb 26 #Python
浅谈Python xlwings 读取Excel文件的正确姿势
Feb 26 #Python
pycharm Tab键设置成4个空格的操作
Feb 26 #Python
解决pycharm 格式报错tabs和space不一致问题
Feb 26 #Python
pycharm 使用tab跳出正在编辑的括号(){}{}等问题
Feb 26 #Python
You might like
用php实现的下载css文件中的图片的代码
2010/02/08 PHP
Ajax+PHP快速上手及简单应用说明
2013/07/24 PHP
完整删除ecshop中获取店铺信息的API
2014/12/24 PHP
php中文验证码实现方法
2015/06/18 PHP
JS案例分享之金额小写转大写
2014/05/15 Javascript
JS与jQuery实现隔行变色的方法
2016/09/09 Javascript
浅谈js中的变量名和函数名重名
2017/02/13 Javascript
基于vue2.0实现简单轮播图
2017/11/27 Javascript
详解Vue 全局引入bass.scss 处理方案
2018/03/26 Javascript
简单说说angular.json文件的使用
2018/10/29 Javascript
详解三种方式解决vue中v-html元素中标签样式
2018/11/22 Javascript
VUE2.0+ElementUI2.0表格el-table循环动态列渲染的写法详解
2018/11/30 Javascript
详细教你微信公众号正文页SVG交互开发技巧
2019/07/25 Javascript
vue简单练习 桌面时钟的实现代码实例
2019/09/19 Javascript
解决VUE自定义拖拽指令时 onmouseup 与 click事件冲突问题
2020/07/24 Javascript
Element InputNumber 计数器的实现示例
2020/08/03 Javascript
如何在selenium中使用js实现定位
2020/08/18 Javascript
python 自动提交和抓取网页
2009/07/13 Python
使用python 爬虫抓站的一些技巧总结
2018/01/10 Python
Python pyinotify模块实现对文档的实时监控功能方法
2018/10/13 Python
python 一篇文章搞懂装饰器所有用法(建议收藏)
2019/08/23 Python
在django中实现choices字段获取对应字段值
2020/07/12 Python
Html5新增标签有哪些
2017/04/13 HTML / CSS
Canvas 文本填充线性渐变的使用详解
2020/06/22 HTML / CSS
美国网上眼镜供应商:LEOTONY(眼镜、RX太阳镜和太阳镜)
2017/10/31 全球购物
C#如何进行LDAP用户校验
2012/11/21 面试题
怎样在 Applet 中建立自己的菜单(MenuBar/Menu)?
2012/06/20 面试题
会展策划与管理专业大学生职业生涯规划
2014/02/07 职场文书
《跨越百年的美丽》教学反思
2014/02/11 职场文书
商场主管竞聘书
2014/03/31 职场文书
公益广告标语
2014/06/19 职场文书
假期安全教育广播稿
2014/10/04 职场文书
群众路线四风自我剖析材料
2014/10/08 职场文书
2014年语文教研组工作总结
2014/12/06 职场文书
小学生交通安全寄语
2015/02/27 职场文书
仓管员岗位职责范本
2015/04/01 职场文书