xml地图|网站地图|网站标签 [设为首页] [加入收藏]
Python编程核心内容之一,读取Word脚注尾注
分类:编程

 

本节来介绍一下使用 RNN 的 LSTM 来做 MNIST 分类的方法,RNN 相比 CNN 来说,速度可能会慢,但可以节省更多的内存空间。

  Python版本:3.6.2  操作系统:Windows  作者:SmallWZQ

 

初始化 首先我们可以先初始化一些变量,如学习率、节点单元数、RNN 层数等:

  截至上篇随笔《Python数据结构之四——set(集合)》,Python基础知识也介绍好了。接下来准备干件“大事”。

脚注和尾注是对文本的补充说明。脚注一般位于页面的底部,可以作为文档某处内容的注释;尾注一般位于文档的末尾,列出引文 的出处等。在本示例中将介绍如何来添加或读取Word脚注尾注。

learning_rate = 1e-3
num_units = 256
num_layer = 3
input_size = 28
time_step = 28
total_steps = 2000
category_num = 10
steps_per_validate = 100
steps_per_test = 500
batch_size = tf.placeholder(tf.int32, [])
keep_prob = tf.placeholder(tf.float32, [])

  什么“大事”呢?下面将要介绍Python编程的核心内容之一——函数。

工具使用:Free Spire. Doc for .NET(免费版)

 

  对于Python编程,函数的重要性不言而喻。重要的事情讲三遍:函数实在是太重要,太关键了。

第一步 :dll引用

图片 1

然后还需要声明一下 MNIST 数据生成器:

引入函数

  之前,我们编写程序遵循的原则:根据业务逻辑从上到下实现功能,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,也就是将之前实现的代码块复制到现需功能处。这种编程方式虽然可以应付一般性问题,但是不能对付大多数问题。这不,下面就来个例子。

1 r1 = 12.3
2 r2 = 9.1
3 r3 = 64.21
4 s1 = 2 * 3.14 * r15 s2 = 2 * 3.14 * r26 s3 = 2 * 3.14 * r3

  圆是个神奇的图形。特别是π,它让人类陷入无限的遐想。OK,回归正题。为了求圆的周长,我们需要引入公式:周长 = 2 * π * r(半径)。看到这儿,某些读者可能会有疑惑:这跟函数有什么关系,之前的方式依然适用。是的,这的确是可以的,但这很麻烦,太重复啦。那如果现在需要把 π 更改为3.1415926535,那该怎么办呢?难道我们要一个一个地去改???Oh,my god!!!这时,我嗅到了函数的味道。

  有了函数,我们就不再每次写c = 2 * 3.14 * x,而是写成更有意义的函数调用c = perimeter_of_circle(x),而函数perimeter_of_circle本身只需要写一次,就可以多次调用。

  Python不但能非常灵活地定义函数,而且本身内置了很多有用的函数,可以直接调用。

  是的,函数最大的优点:增强代码的重用性和可读性。Python中,函数就是最基本的一种代码抽象的方式。

第二步: 添加Word脚注、尾注

【C#】

using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;
using System.Drawing;

namespace InsertFootnote_Doc
{
    class Program
    {
        static void Main(string[] args)
        {
            //新建一个word文档对象并加载需要添加脚注尾注的word文档
            Document document = new Document();
            document.LoadFromFile("sample.docx", FileFormat.Docx2010);

            //获取第3个段落
            Paragraph paragraph = document.Sections[0].Paragraphs[2];

            //添加脚注
            Footnote footnote = paragraph.AppendFootnote(FootnoteType.Footnote);

            //在第一段里查找指定字符串,并添加脚注
            DocumentObject obj = null;

            for (int i = 0; i < paragraph.ChildObjects.Count; i++)
            {
                obj = paragraph.ChildObjects[i];
                if (obj.DocumentObjectType == DocumentObjectType.TextRange)
                {
                    TextRange textRange = obj as TextRange;

                    if (textRange.Text == "中国——东盟自贸区框架")
                    {
                        //为添加脚注的字符串设置加粗格式
                        textRange.CharacterFormat.Bold = true;
                        //插入脚注
                        paragraph.ChildObjects.Insert(i + 1, footnote);
                        break;
                    }
                }
            }

            //添加脚注内容被设置字体格式
            TextRange text = footnote.TextBody.AddParagraph().AppendText("2002年11月4日,朱镕基总理和东盟10国领导人共同签署了《中国-东盟全面经济合作框架协议》,这标志着中国与东盟的经贸合作进入了一个新的历史阶段。");
            text.CharacterFormat.FontName = "Arial Black";
            text.CharacterFormat.FontSize = 9;
            text.CharacterFormat.TextColor = Color.DarkGray;
            footnote.MarkerCharacterFormat.FontName = "Calibri";
            footnote.MarkerCharacterFormat.FontSize = 12;
            footnote.MarkerCharacterFormat.Bold = true;
            footnote.MarkerCharacterFormat.TextColor = Color.DarkGreen;


            //获取第5段落
            Paragraph paragraph2 = document.Sections[0].Paragraphs[4];

            //添加尾注并设置尾注和格式
            Footnote endnote = paragraph2.AppendFootnote(FootnoteType.Endnote);

            TextRange text2 = endnote.TextBody.AddParagraph().AppendText("党的十七大报告明确指出:"
                +"“坚持对外开放的基本国策,把‘引进来’和‘走出去’更好地结合起来,"
                +"扩大开放领域,优化开放结构,提高开放质量,完善内外联动,"
                +"互利共赢、安全高效的开放型经济体系,形成经济全球化条件下参与国际经济合作和竞争的新优势。");
            text2.CharacterFormat.FontName = "Arial Black";
            text2.CharacterFormat.FontSize = 9;
            text2.CharacterFormat.TextColor = Color.Black;
            endnote.MarkerCharacterFormat.FontName = "Calibri";
            endnote.MarkerCharacterFormat.FontSize = 12;
            endnote.MarkerCharacterFormat.Bold = false;
            endnote.MarkerCharacterFormat.TextColor = Color.DarkGreen;

            //保存并打开文档
            document.SaveToFile("添加脚注尾注.docx", FileFormat.Docx2010);
            System.Diagnostics.Process.Start("添加脚注尾注.docx");
        }
    }
}

测试结果:

图片 2

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data/', one_hot=True)

 函数定义

  在Python中,函数有五大要点,分别是def、函数名、函数体、参数、返回值,以及两个英文版符号,分别是括号(括号内为参数)和冒号(:)。

  def:函数的关键字,没它可不行。

  函数名:函数的名称,根据函数名调用函数。

  函数体:函数中进行一系列的具体操作。

  参数:为函数体提供数据。

  返回值:当函数执行完毕后,可以给调用者返回数据。

  上述函数的要点中,最重要的是参数和返回值。

第三步 :读取脚注/尾注

 【C#】

//创建Document类对象,加载需要测试的文档
            Document document = new Document();
            document.LoadFromFile("添加脚注尾注.docx");
            //获取文档第一个section
            Section section = document.Sections[0];

            //实例化StringBuilder类 
            StringBuilder sb = new StringBuilder();

            //遍历文档中所有段落
            foreach (Paragraph paragraph in section.Paragraphs)
            {
                for (int i = 0, cnt = paragraph.ChildObjects.Count; i < cnt; i++)
                {
                    ParagraphBase pBase = paragraph.ChildObjects[i] as ParagraphBase;
                    if (pBase is Footnote)
                    {
                        //若需要读取尾注,将此处FootnoteType.Footnote改成 FootnoteType.Endnote即可
                        if ((pBase as Footnote).FootnoteType == FootnoteType.Footnote)
                        {
                            foreach (Paragraph footPara in (pBase as Footnote).TextBody.Paragraphs)
                            {
                                sb.Append(footPara.Text);
                            }
                        }
                    }
                }
            }
            //将读取内容写入文本并保存
            File.WriteAllText("FootNotes.txt", sb.ToString());
            //打开文档
            System.Diagnostics.Process.Start("FootNotes.txt");

 

读取结果:

脚注读取结果:

图片 3

 

 尾注读取结果:

图片 4

 

 

1.返回值

  函数是一个功能块,该功能到底执行成功与否,需要通过返回值来告知调用者。

接下来常规声明一下输入的数据,输入数据用 x 表示,标注数据用 y_label 表示:

2.参数

  定义函数时,参数是一定需要考虑的。Python的函数定义非常简单,但灵活度却非常大。

  对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复杂逻辑被封装起来,调用者无需了解。

  Python中,参数类型有:必选参数、默认参数、可变参数、关键字参数和命名关键字参数。函数中,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数

x = tf.placeholder(tf.float32, [None, 784])
y_label = tf.placeholder(tf.float32, [None, 10])

3.空函数

  空函数:什么事也不做,可以用pass语句。既然“一事不做”,那空函数还有什么用处?实际上pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。如此,运行代码程序就不会出现错误了。

1 #空函数
2 def nop():
3     pass

 

函数参数

  Python中,参数是非常灵活的。掌握参数就能领悟函数的真谛了。这是真的。参数是比较难理解的,特别是参数组合。

  1.位置参数

  既然说函数,就需要展示函数:

1 #位置参数(必选参数)
2 def involution(x):
3     return x * x
4 >>>involution(3)
5 9
6 >>>involution(5)
7 25

  如代码所示,参数x就是一个位置参数。

  2.默认参数

  Python函数支持默认参数,即可以给函数的参数指定默认值。当该参数没有传入相应的值时,该参数就使用默认值。

 1 #默认参数
 2 def involution(x,n = 2):
 3     s = 1
 4     while n > 0:
 5         n = n - 1
 6         s = s * x
 7     return s
 8 >>>involution(6)
 9 36
10 >>>involution(5,3)
11 125

  如代码所示,当我们调用involution(5),就相当于调用involution(5,2)。

  注:1.设置默认参数时,必选参数在前,默认参数在后,否则Python的解释器会报错;

    2.定义默认参数要牢记:默认参数必须指向不可变对象!  

 1 >>>def add_end(L=[]):
 2 ...    L.append('END')
 3 ...    return L
 4 ...
 5 >>>add_end()
 6 ['END']
 7 >>>add_end()
 8 ['END','END']
 9 >>>add_end()
10 ['END','END','END']

  上述代码展示的是默认参数不为不可变对象的现象。因此,默认参数必须指向不可变对象【字符串、None……】。

  3.可变参数

  在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。

  我们以数学题为例子,给定一组数字a,b,c……,请计算a2 + b2 + c2 + ……。

  要定义出这个函数,我们必须确定输入的参数。由于参数个数不确定,我们首先想到可以把a,b,c……作为一个list或tuple传进来,这样,函数可以定义如下:

1 #一般性函数
2 def calc(numbers):
3     sum = 0
4     for n in numbers:
5         sum = sum + n * n
6     return sum

  如何调用calc()函数呢?需要调用时,需要为参数引入list或者tuple。

1 #函数调用
2 >>> calc([1, 2, 3])
3 14
4 >>> calc((1, 3, 5, 7))
5 84

  然而,如果我们使用可变参数,我们可以进行简化,方法如下:

1 #可变参数
2 def calc(*numbers):
3     sum = 0
4     for n in numbers:
5         sum = sum + n * n
6     return sum

  咋调用呢?这个可简单啦,再也不用list或者tuple了。参数调用只需如下所示:

1 #可变参数的魅力
2 >>> calc(1, 2, 3)
3 14
4 >>> calc(1, 3, 5, 7)
5 84
6 
7 #参数调用不用calc([1,2,3]),括号内还用写中括号,好麻烦~~~

  定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数

1 >>> calc(1, 2)
2 5
3 >>> calc()
4 0

  如果已经有一个list或者tuple,要调用一个可变参数怎么办?可以这样做:

1 >>> nums = [1, 2, 3]
2 >>> calc(nums[0], nums[1], nums[2])
3 14

  这种写法当然是可行的,问题是太繁琐,所以Python允许你在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去:

1 >>> nums = [1, 2, 3]
2 >>> calc(*nums)
3 14

  4.关键字参数

  可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。dict就是字典,它是键值对组合,益处多多~~~

1 #引入关键字参数,默认为**kw
2 def person(name, age, **kw):
3     print('name:', name, 'age:', age, 'other:', kw)

  函数person除了必选参数name和age外,还接受关键字参数kw。在调用该函数时,可以只传入必选参数(必选参数必须全部传入,否则会出错),也可以传入关键字参数。注:关键字参数可是任意个的。

 1 #调用关键字参数
 2 >>>def person(name,age,**kw):
 3 ...    print('name:',name,'age:',age,'other:',kw)
 4 ...
 5 >>>person('Jack')
 6 Traceback (most recent call last):
 7   File "<stdin>", line 1, in <module>
 8 TypeError: person() missing 1 required positional argument: 'age'
 9 >>>person('Jack',36)
10 name:Jack age:36 other:{}
11 >>>person('Jack',36,city='Hangzhou')
12 name:Jack age:36 other:{'city':'Hangzhou'}
13 >>>person('Jack',36,city='Hangzhou',job='Engineer')
14 name:Jack age:36 other:{'city':'Hangzhou','job':'Engineer'}

  关键字参数有什么用呢?其实,既然存在就有它的强大之处。就像自然界中的万物,物竞天择,适者生存。如果它能够在自然界中生存下来,那么它就有独特的生存本领。因此,关键字参数还是有用武之地的。

  它可以扩展函数的功能。比如,在person函数里,我们保证能接收到name和age这两个参数,但是,如果调用者愿意提供更多的参数,我们也能收到。试想你正在做一个用户注册的功能,除了用户名和年龄是必填项外,其他都是可选项,利用关键字参数来定义这个函数就能满足注册的需求。

  如何操作呢?我们可以先组装出一个dict,然后,把该dict转换为关键字参数传进去:

1 >>> extra = {'city': 'Hangzhou', 'job': 'Engineer'}
2 >>> person('Jack', 36, city=extra['city'], job=extra['job'])
3 name: Jack age: 36 other: {'city': 'Hangzhou', 'job': 'Engineer'}

  当然了,上面代码调用方式有点烦,通过dict键来查找值。我们可以通过关键字简化一下:

1 >>> extra = {'city': 'Hangzhou', 'job': 'Engineer'}
2 >>> person('Jack', 36, **extra)
3 name: Jack age: 36 other: {'city': 'Hangzhou', 'job': 'Engineer'}

  **extra表示把extra这个dict的所有key-value用关键字参数传入到函数的**kw参数,kw将获得一个dict。

   5.命名关键字参数

  对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些,就需要在函数内部通过kw检查。

  仍以person()函数为例,我们希望检查是否有city和job参数:

1 def person(name, age, **kw):
2     if 'city' in kw:
3         # 有city参数
4         pass
5     if 'job' in kw:
6         # 有job参数
7         pass
8     print('name:', name, 'age:', age, 'other:', kw)

  如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。这种方式定义的函数如下:

1 def person(name, age, *, city, job):
2     print(name, age, city, job)

  和关键字参数kw不同,命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数。 
  调用命名关键字参数方式如下:

1 #调用命名关键字参数
2 >>> person('Jack', 36, city='Hangzhou', job='Engineer')
3 Jack 36 Hangzhou Engineer

  那如果参数中有可变参数,那该怎么办呢?

  若可变参数后面跟着命名关键字参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了。

1 def person(name, age, *args, city, job):
2     print(name, age, args, city, job)

  命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错。而命名关键字参数可以有缺省值,从而简化调用:

1 def person(name, age, *, city='Hangzhou', job):
2     print(name, age, city, job)

  由于命名关键字参数city具有默认值,调用时,可不传入city参数:

1 >>> person('Jack', 36, job='Engineer')
2 Jack 36 Hangzhou Engineer

  6.参数组合

  目前,函数中共有5种常用的参数类型。若只传入一种类型的参数,这太简单了。难点在哪?难点就在参数组合使用,那是相当恶心。不过,平时最好不要混合使用参数,不然容易搞得“乌烟瘴气”。

  OK!言归正传,不然跑题啦。

  Python中,定义一个函数,我们可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

  下面来定义一个函数,该函数参数包含一种或几种参数。

1 def f1(a, b, c=0, *args, **kw):
2     print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
3 
4 def f2(a, b, c=0, *, d, **kw):
5     print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)

  在函数调用的时候,Python解释器自动按照参数位置和参数名把对应的参数传进去。

 1 >>> f1(1, 2)
 2 a = 1 b = 2 c = 0 args = () kw = {}
 3 >>> f1(1, 2, c=3)
 4 a = 1 b = 2 c = 3 args = () kw = {}
 5 >>> f1(1, 2, 3, 'a', 'b')
 6 a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
 7 >>> f1(1, 2, 3, 'a', 'b', x=99)
 8 a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
 9 >>> f2(1, 2, d=99, ext=None)
10 a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}

  最神奇的是通过一个tuple和dict,你也可以调用上述函数:

1 >>> args = (1, 2, 3, 4)
2 >>> kw = {'d': 99, 'x': '#'}
3 >>> f1(*args, **kw)
4 a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}
5 >>> args = (1, 2, 3)
6 >>> kw = {'d': 88, 'x': '#'}
7 >>> f2(*args, **kw)
8 a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}

  所以,对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的。

  然而,虽然函数参数类型多达5种,但不要同时使用太多的组合,否则函数接口的可理解性很差。哎,简简单单才是真啊。

  7.函数参数小结

  参数,作为函数传入值的媒介,这里有必要做一个总结。

  一、Python的函数具有非常灵活的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数;

  二、默认参数一定要用不可变对象,如果是可变对象,程序运行时会有逻辑错误;

三、*args是可变参数,args接收的是一个tuple;

四、**kw是关键字参数,kw接收的是一个dict;

  五、可变参数既可以直接传入:func(1, 2, 3),又可以先组装list或tuple,再通过*args传入:func(*(1, 2, 3))

  六、关键字参数既可以直接传入:func(a=1, b=2),又可以先组装dict,再通过**kw传入:func(**{'a': 1, 'b': 2});

  七、使用*args**kw是Python的习惯写法,当然也可以用其他参数名,但最好使用习惯用法;

  八、命名的关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值;

  九、定义命名的关键字参数在没有可变参数的情况下不要忘了写分隔符*,否则定义的将是位置参数。

  故而,为了学好Python中的函数部分,参数不容忽视。

这里输入的 x 维度是 [None, 784],代表 batch_size 不确定,输入维度 784,y_label 同理。

函数调用

  在学习了函数的定义之后,我们应该需要调用函数,获取我们想要的数据。

  如何调用函数呢?语法:函数名(参数)

  Python中,大佬们内置了许多有点用的函数,而我们只需拿来就行(这让我想起了鲁迅的“拿来主义”)。

  若要调用Python中的内置函数,我们首先要知道函数名和参数。哈哈,又是参数~~~

  比如我想要求某数的绝对值。如果你不知道Python有相关的内置函数,就只能这么做:

 1 #求取绝对值
 2 >>>def abs(num):
 3 ...    if num >= 0:
 4 ...        return num
 5 ...    else:
 6 ...        return (-num)
 7 ...
 8 >>>abs(9)
 9 9
10 >>>abs(0)
11 0
12 >>>abs(-8)
13 8

  上述代码虽然可以实现求绝对值的功能,但是太繁琐,需要敲几行代码才能实现该功能。然而,Python中有这个函数可以直接调用并输出结果。

 1 #Python内置函数:abs()
 2 >>>abs(-9)
 3 9
 4 >>>abs(9)
 5 9
 6 #获取帮助文档
 7 >>>help(abs)
 8 Help on built-in function abs in module builtins:
 9 
10 abs(x, /)
11     Return the absolute value of the argument.

  Python官方网站:

  对于函数参数,通常会遇到以下两个问题:

  1.如果函数传入参数的数量错误,会如何呢?简单,直接Error呗。比如abs():

1 #函数传入参数的数量错误
2 >>> abs(-9,89)
3 Traceback (most recent call last):
4   File "<stdin>", line 1, in <module>
5 TypeError: abs() takes exactly one argument (2 given)

  2.如果传入的参数数量是对的,但参数类型不能被函数所接受,也会报TypeError的错误,并且给出错误信息:str是错误的参数类型:

1 #传入的参数类型错误
2 >>> abs('a')
3 Traceback (most recent call last):
4   File "<stdin>", line 1, in <module>
5 TypeError: bad operand type for abs(): 'str'

接下来我们需要对输入的 x 进行 reshape 操作,因为我们需要将一张图分为多个 time_step 来输入,这样才能构建一个 RNN 序列,所以这里直接将 time_step 设成 28,这样一来 input_size 就变为了 28,batch_size 不变,所以reshape 的结果是一个三维的矩阵:

常见内置函数(Built-in Functions)

  Python 3.x版本下官方网站:。该网址内显示Python内置函数相关内容(Built-in Functions)。

  1.数据结构相关:list()、tuple()、dict()、str()……

  2.数字相关:abs()、min()、max()、len()……

  3.其他:int()、float()……

  好,不一一例举了,直接上图吧~~~

图片 5

  如果读者想知道图中函数的详细含义,请点击上述链接网址。调皮一下,这里就不附上网址啦~~~

x_shape = tf.reshape(x, [-1, time_step, input_size])

数据类型转换

  Python内置的常用函数还包括数据类型转换函数,比如int()函数可以把其他数据类型转换为整数:

 1 #Python之数据类型转换(int、float、str……)
 2 >>> int('123')
 3 123
 4 >>> int(12.34)
 5 12
 6 >>> float('12.34')
 7 12.34
 8 >>> str(1.23)
 9 '1.23'
10 >>> str(100)
11 '100'
12 >>> bool(1)
13 True
14 >>> bool('')
15 False

函数别名

  了解Linux的读者可能知道别名(alias,unalias)这个指令。Python中也有“别名”之说,比如把函数名赋给变量:

 1 #函数“别名”
 2 >>>abs(-8)
 3 8
 4 >>>a = abs
 5 >>>a(-9)
 6 9
 7 >>>a(0)
 8 0
 9 >>>a(9)
10 9

 

递归函数

  讲述递归函数之前,我想起一个东西:阶乘(n!)。举个例子,我们来计算阶乘n! = 1 x 2 x 3 x ... x n,用函数fact(n)表示,可以看出:

  fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n

  因此,递归函数:在函数内部,一个函数在内部调用自身本身。

  于是,fact(n)用递归的方式写出来就是:

 1 #递归函数
 2 >>>def fact(n):
 3 ...    if n == 1:
 4 ...        return 1
 5 ...    else:
 6 ...        return fact(n - 1) * n
 7 ...
 8 >>>fact(1)
 9 1
10 >>>fact(5)
11 120
12 #递归函数之栈溢出
13 >>>fact(1000)
14 Traceback (most recent call last):
15   File "<stdin>", line 1, in <module>
16   File "<stdin>", line 5, in x
17   File "<stdin>", line 5, in x
18   File "<stdin>", line 5, in x
19   [Previous line repeated 994 more times]
20   File "<stdin>", line 2, in x
21 RecursionError: maximum recursion depth exceeded in comparison

  如代码所示,使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。

  针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。

  Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。

  什么是尾递归?这个请读者自行查询呗,这里就不介绍啦,嘿嘿~~~

  下面来个斐波拉契数列

1 #斐波拉契数列
2 >>>def fibo(arg1,arg2):
3 ...    if arg1 == 0:
4 ...        print(arg1,arg2)
5 ...    arg3 = arg1 + arg2
6 ...    print(arg3)
7 ...    fibo(arg2, arg3)
8 ...
9 >>>fibo(0,1)    

  上述代码展示的斐波拉契数列会一直计算,直至栈溢出:

 1 #斐波拉契数列导致栈溢出
 2 488272859468887457959087733119242564077850743657661180827326798539177758919828135114407499369796465649524266755391104990099120377
 3 Traceback (most recent call last):
 4   File "<stdin>", line 1, in <module>
 5   File "<stdin>", line 6, in fibo
 6   File "<stdin>", line 6, in fibo
 7   File "<stdin>", line 6, in fibo
 8   [Previous line repeated 992 more times]
 9   File "<stdin>", line 5, in fibo
10 RecursionError: maximum recursion depth exceeded while calling a Python object
11 16602747662452097049541800472897701834948051198384828062358553091918573717701170201065510185595898605104094736918879278462233015981029522997836311232618760539199036765399799926731433239718860373345088375054249

  如何才能避免栈溢出呢?自己想呗,要不大脑会生锈的。

  对于汉罗塔问题,利用递归来解决该问题也是相当的简单,且代码清晰:

图片 6图片 7

 1 #递归解决汉罗塔问题
 2 >>>def hanrota(n,a,b,c):
 3 ...    if n == 1:
 4 ...        print(a,'-->',c)
 5 ...    else:
 6 ...        hanrota(n - 1,a,c,b)
 7 ...        hanrota(1,a,b,c)
 8 ...        hanrota(n - 1,b,a,c)
 9 ...
10 >>>hanrota(3,'A','B','C')
11 A --> C
12 A --> B
13 C --> B
14 A --> C
15 B --> A
16 B --> C
17 A --> C

汉罗塔问题

匿名函数

  定义函数真得不可多得,但有时候不需要显示地定义函数。因此,函数也需要灵活地运用。使用匿名函数可以更加方便。

  匿名函数语法:

    lambda x: x * x(关键字lambda表示匿名函数,冒号前面的x表示函数参数)

1 def f(x):
2     return x * x

  匿名函数的好处:因为函数没有名字,不必担心函数名冲突。

 

1 def is_odd(n):
2    return n % 2==1
3 
4 L = list(filter(lambda n: n%2==1,range(1,20)))
5 print(L)  

*  *1.匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数。

  2.Python中,匿名函数可以作为返回值返回并输出结果。

RNN 层 接下来我们需要构建一个 RNN 模型了,这里我们使用的 RNN Cell 是 LSTMCell,而且要搭建一个三层的 RNN,所以这里还需要用到 MultiRNNCell,它的输入参数是 LSTMCell 的列表。

所以我们可以先声明一个方法用于创建 LSTMCell,方法如下:

本文由澳门新葡亰手机版发布于编程,转载请注明出处:Python编程核心内容之一,读取Word脚注尾注

上一篇:委托和接口,设置图层可见性 下一篇:python利用heapq实现小顶堆,线程基础
猜你喜欢
热门排行
精彩图文