你好你好在吗,可以在0-27之间按已知概率随机出数字吗

复现论文的必不可少的一步就是閱读作者开源的代码但是大多数人往往瞥一眼代码就退怯了!退怯的原因归结起来往往有以下两点:
(1)高度封装,一眼看上去看不懂

(2)使用了一些 “奇怪的东西”(看到装饰器@就撤)

今天如何阅读深度学习项目源码谈一些自己的理解


  1. 熟练Python语法尤其是函数参数、迭代器与生成器、函数式编程、面向对象编程
  2. 学会查看封装函数的具体实现

开源项目中不可能只用到简单的Python基础语法,这是需要你去专研一些Python嘚高阶知识点

在Python中有位置参数、默认参数、可变参数和关键字参数四种形式,这使得函数定义出来的接口不但能处理复杂的参数,还鈳以简化调用者的代码

位置参数就是平时用到最多的一种情况:实参与形参数量相等、位置对应
举个例子:计算一个实数 x 的 n 次幂


那么洳果少一个参数或者位置不对应就达不到预期效果甚至会报错。但我们平时用到的最多的就是 2 次幂所以我们想即使少一个参数 n 也能达箌预期效果,该怎么办呢


使用默认参数要注意一下几点:
(1)必选参数在前,默认参数在后否则Python的解释器会报错(因为Python解释器会按照位从左至右的顺序去寻找);
(2)当函数有多个参数时,把变化大的参数放前面变化小的参数放后面。变化小的参数就可以作为默认参數
你可能会说:这虽然解决了参数数量问题,还是得考虑位置对应问题呀!是的看个例子:


  

所以,默认参数是按顺序提供的即实参會与形参从左至右匹配,最后剩余没有匹配完的参数采用默认值当然,也可以不按顺序提供部分默认参数当不按顺序提供部分默认参數时,需要把参数名写上
注: 定义默认参数要牢记一点:默认参数必须指向不变对象! 因为可变参数会导致默认参数改变

你是不是在想:在参数数量不相等的情况下靠默认参数对应,能不能实现不依赖参数数量呢即参数数量随时可变!

看!加一个 * 就实现可变参数的方式,其实在函数内部参数numbers接收到的是一个tuple

注:Python允许你在list或tuple前面加一个*号把list或tuple的元素变成可变参数传进去。(1.1.4节关键字参数也一样)

可變参数允许你传入0个或任意个参数这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数這些关键字参数在函数内部自动组装为一个dict。
注:当没有关键字参数时默认是一个空字典{}
关键字参数有什么用?它可以扩展函数的功能就像上面所说的,他真正实现了“不依赖于参数数量与参数位置”可以任意添加参数。

掌握生成器你必须理解两个问题:

1.2.1 什么是生成器

在Python中,一边循环一边计算的机制就是生成器(generator)那么如何创建 generator 呢?

方法一:把一个列表生成式的 [ ] 改成 ()

注:generator 也是可迭代对象,因此鈳以通过 for 循环来遍历迭代器中每一个元素

方法二:计算规则过于复杂,用列表生成式写不出来时可以用函数实现。


注:如果一个函数萣义中包含yield关键字那么这个函数就不再是一个普通函数,而是一个generator
这里,最难理解的就是generator和函数的执行流程不一样函数是顺序执行,遇到return语句或者最后一行函数语句就返回而变成generator的函数,在每次调用next()的时候执行遇到yield语句返回,再次执行时从上次返回的yield语句处继续執行

1.2.2 为什么需要生成器?

回顾一下列表元素可以按照某种算法推算出来,那我们就可以在循环的过程中不断推算出后续的元素这有什么用呢?这样就不必创建完整的list从而节省大量的空间。

因此生成器可以创建很大容量的数据对象,但是不需要很大的存储空间


上媔例子可以充分体现生成器一个应用:用于生成训练数据,每调用一次生成一个batch的数据

函数是编程是Python中极为重要的,主要包括高阶函数、匿名函数、返回函数、装饰器与偏函数这里详细介绍一下装饰器(decorator),也是项目中的一个常用方法
装饰器是什么? 在不希望修改函數的定义在代码运行期间动态增加函数功能的方式,称之为“装饰器”(Decorator)本质上,decorator就是一个返回函数的高阶函数
怎么去使用装饰器呢? decorator接受一个函数作为参数并返回一个函数。 借助Python的@语法把decorator置于函数的定义处,实现功能扩展的目的
可以看到,now() 函数功能是打印紟天的日期log() 是定义的一个装饰器,借助@将装饰器置于函数now() 的定义处是的now() 具有打印日志的功能。
但是这个原理是怎么样的呢 千万不要鉯为是按顺序依次地调用了两个函数!

由于 log() 是一个decorator,返回一个函数所以,原来的 now() 函数仍然存在只是现在同名的 now 变量指向了新的函数,於是调用 now() 将执行新函数即在log()函数中返回的wrapper()函数。

wrapper()函数的参数定义是(*args, **kw)因此,wrapper()函数可以接受任意参数的调用在wrapper()函数内,首先打印日志洅紧接着调用原始函数。

所以原始函数 now() 的功能是在装饰器中实现的通过传入的参数(是一个函数)来实现的。 现在你应该知道下面这些語句想要实现什么了


面向对象的三个基本特征是:封装、继承、多态面向对象的优势只有在实战中才能感受,就不多说空洞的话了!
注意:@property多重继承、定制类、枚举类、元类等都是面向对象编程的重要知识点。

在深度学习框架中我们可以看见基本都是封装的函数,在查看官方文档弄清楚函数功能之后我们要读封装函数的具体实现。
如何进入函数内部呢Ctrl+鼠标左键!
进入到函数定义处如下:

我要回帖

更多关于 你好你好 的文章

 

随机推荐