希望通过博客园持续的更新,分享和记录Python基础知识到高级应用的点点滴滴!

第一波:第6章  抽象

[总览] 介绍函数、参数parameter、作用于scope概念,以及递归概念。

[6.1] 函数 - 懒惰即美德!

  将程序的具体细节抽象为函数。

[6.2] 抽象和结构

  抽象可以节省代码工作量,关键易使程序让人读懂。程序应该是非常抽象额,就像“下载网页、计算词频、打印单词频率”描述一样易懂。

page = download_page()

freqs = compute_frequencies(page)

for word,freq in freqs:

  print word,freq

[6.3] 创建函数

  函数可调用,并返回一个值。内建callable函数可判断函数是否可调用。

  函数callable在Python3.0中需要使用表达式hasattr(func.__call__)代替。

  使用def定义函数,return用来从函数中返回值。

def fibs(num):

  result = [0,1]

  for i in range(num-2):

    result.append(result[-2] + result[-1])

  return result

[6.3.1] 记录函数

  给函数写文档,除加入注释(以#开头),还可直接在函数def语句内写上字符串。在函数的开头写下的字符串,它就会作为函数的一部分进行存储,称为文档字符串。

  文档字符串可以function.__doc__方式访问。__doc__使函数属性,双下划线表示它是个特殊属性。

  或者使用内建help函数,如help(function_name),可以得到关于函数,包括文档字符串的信息。

[6.3.2] 并非真正函数的函数

  Python的有些函数并不返回任何东西,没有return语句或有return但后面没有跟任何值得函数,将不返回值。此时return语句只起到结束函数作用。

  更准确的将,所有的函数的确都返回了东西:当不需要函数返回值的时候,函数就返回None。

[6.4] 参数魔法

[6.4.1] 值从哪里来

  卸载def语句中函数名后面的变量通常叫形式参数,而调用函数的时候提供的值使实际参数,或者称为参数。

[6.4.2] 我能改变参数吗

  在函数内为参数赋予新值不会改变外部任何变量的值。

def try_to_change(n):

  n = 'Mr. New'

name = 'Mrs. Old'

try_to_change(name)

name

'Mrs. Old'

  参数n获得了新值,但是没有影响到name变量。n实际上是个完全不同的变量。当变量n改变的时候,变量name不变。即当在函数内部把参数重绑定(赋值)的时候,函数外部的变量不会受到影响。

  注意:参数存储在局部作用于local scope内。

  字符串(以及数字和元组)是不可变的,考虑一下如果将可变的数据结构如列表用作参数的情况:

def change(n):

  n[0] = 'Mr. Change_New'

names = ['Mrs.Entity','Mrs. Thing']

change(names)

names

['Mr. Change_New','Mrs. Thing']

  当两个变量同时引用一个列表的时候,它们的确是同时引用一个列表。如果避免出现这种情况,可以复制一个列表的副本,在序列中做切片,返回的切片总是一个副本。如果复制了整个列表的切片,即得到列表的一个副本。

names = ['Mrs.Entity','Mrs. Thing']

n = names[:] #现在n和name是两个不同的列表。可通过is或==理解。原列表是安全的。

  1.为什么我想要修改参数

  使用函数改变数据结构是将程序抽象画的好方法。抽象的要点就是通过函数实现隐藏繁琐的细节。

def init(data):

  data['first'] = {}

  data['middle'] = {}

storage

{'first':{},'middle':{},'last':{}}

[6.4.3] 关键字参数和默认值

  位置参数和关键字参数。慢慢习惯使用这个功能以后,就会发现程序规模越大,关键字参数的作用也越大。关键字参数主要作用在于可以明确每个参数的作用。关键词参数最厉害的地方在于可以在函数中给参数提供默认值。

  位置和关键字参数可以联合使用。把位置参数放置在前面就可以。

[6.4.4] 收集参数

  提供任意数量的参数是很有必要且重要的。

def print_params(*params):print params

('Testing',)

  结果作为元祖打印出来。参数前的星号*将所有值放置在同一个元祖中。可以说是将这些值收集起来没然后使用。还可以联合普通参数使用。*星号的意思就是“收集其余的位置参数”。注意,此处强调位置参数

def print_params(**params):print params

print_params(x=1,y=2,z=3)

{'x':1,'y':2,'z':3}  # f返回的是字典而不是元组

def print_params(x,y,z=3,*pospar,**keypar):

  print x,y,z

  print pospar

  print keypar

print_params(1,2,3,5,6,7,foo=1,bar=2)

1 2 3

(5,6,7)

{'foo':1,'bar':2}

[6.4.5] 反转过程

[6.4.6] 练习使用参数

  位置参数,关键字参数,*,**

[6.5] 作用域

  到底什么是变量?你可以把他们看作是值的名字。在执行x=1赋值语句时,名称x引用到值1。这就像用字典一样,键引用值,当然变量和所对应的值用的是个“不可见”的字典。实际上这个么说已经很接近真实情况啦。内建的vars函数可以返回这个字典:

x=1

scope = vars()

scope['x]

  这类“不可见字典”叫做命名空间或者作用域。到底有多少个命名空间?除了全局作用域外,每个函数调用都会创建一个新的作用域。

def foo():x=42

x = 1

foo()

x

1

  这里的foo函数改变了变量x,但是在最后的时候,x并没有变。这是因为当调用foo的时候,新的命名空间就被创建了,它作用于foo内的代码块。赋值语句x=42只在内部作用域(局部命名空间)起作用,所以它并不影响外部(全局)作用域中的x。

  函数内的变量被称为局部变量local variable,这是与全局变量相反的概念。参数的工作原理类似于局部变量,所以用全局变量的名字作为参数名并没有问题。

  【待深入问题:局部变量与全局变量屏蔽问题,重绑定全局变量问题,嵌套作用域问题】

[6.6] 递归

  函数可以调用自身。递归简单来说就是引用自身。

  递归函数包含以下几部分:

    当函数直接返回值时有基本实例(最小可能性问题);

    递归实例,包括一个或者多个问题最小部分的递归调用。

  这里的关键就是讲问题分解为小部分,递归不能永远继续下去,因为它总是以最小可能性问题结束,而这些问题又存在基本实例中的。每次函数被调用时没针对这个调用的新命名空间会被创建,意味着当函数调用“自身”时,实际上运行的是两个不同的函数(或者说是同一个函数具有两个不同的命名空间)。

[6.6.1] 两个经典:阶乘和幂

  n的阶乘定义为nx(n-1)x(n-2)x...x1

    1的阶乘是1;

    大于1的数n的阶乘是n乘n-1的阶乘

def factorial(n):

  if n == 1:

    return 1

  else:

    return n * factorial(n-1)

  计算幂,就像内建的pow函数或者**运算符一样。

    对于任意数字x来说,power(x,0)是1;

    对于任意大于0的数来说,power(x,n)是x乘以(x,n-1)的结果。

def power(x,n):

  if n == 0:

    return 1

  else:

    return x * power(x,n-1)

[6.6.2] 另一个经典:二元查找

  二元查找binary search。

  首先定义二元查找算法的递归:

    如果上下限相同,那么就是数字所在位置,返回;

    否则找到两者的重点(上下限的平均值),查找数字是在左侧还是在右侧,继续查找数字所在的那半部分。

def search(sequence,number,lower,upper):

  if lower == upper:

    assert number == sequence[upper]

    return upper

  else:

    middle = (lower+upper)//2

    if number > sequence[middle]:

      return search(sequence,number,middle+1,upper)

    else:

      return search(sequence,number,lower,middle)

  提示:标准库中的bisect可以非常有效地实现二元查找。

[6.6.3] 有用的函数

  map、filter、reduce函数

  map函数可将序列中的所有元素全部传递给一个函数:

map(str,range(10))  # equivalent to [str(i) for i in range(10)]

  filter函数可以基于一个返回布尔值的函数对元素进行过滤:

filter(func,seq)

  lambda表达式,可以创建短小的函数。

filter(lambda x: x.isalnum(),seq)

  reduce函数会将序列的前两个元素与给定的函数联合使用,并且将他们的返回值和第三个元素继续联合使用,直到整个序列都处理完毕,并且得到一个最终结果。

numbers = [77,102,33,45,23,62,89,201]

reduce(lambda x,y:x+y,numbers)

[6.7] 小结

  抽象:抽象是隐藏多余细节的艺术。定义处理细节的函数可以让程序更抽象。

  函数定义:函数使用def语句定义。由语句组成的块,可以从”外部“获取参数,可以返回一个或者多个结果。

  参数:即函数调用时设定的变量。python中有两类参数:位置参数和关键字参数。

  作用域:变量存储在作用(也叫命名空间)中。两类作用域:全局作用域和局部作用域,作用域可嵌套。

  递归:调用函数自身。

  函数式编程:Python有一些函数型编程的机制。包括lambda表达式以及map、filter、reduce函数。

Python基础教程【读书笔记】 - 2016/6/26的更多相关文章

  1. 《Python基础教程读书笔记》

    第1章 快速构造:基础知识 1.2交互式构造器 不强制分号,一行就是一行.可以加上分号 1.4数字和表达式 加.减.乘.除.整除.求余.指数.取反(-例如-2**2,**的优先级比-大) from _ ...

  2. Python基础教程 读书笔记(2)第二章 列表和元组

    2.1序列概览 列表和元组的主要区别在于,列表可以修改,元组则不能.也就是说如果要根据要求来添加元素,那么列表可能会更好用;而出于某些原因,序列不能修改的时候,使用元组则更为合适.使用后者的理由通常是 ...

  3. SQL Server2012 T-SQL基础教程--读书笔记(1-4章)

    SQL Server2012 T-SQL基础教程--读书笔记(1-4章) SqlServer T-SQL 示例数据库:点我 Chapter 01 T-SQL 查询和编程背景 1.3 创建表和定义数据的 ...

  4. SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章)

    SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章) 示例数据库:点我 CHAPTER 08 数据修改 8.1 插入数据 8.1.1 INSERT VALUES 语句 8.1 ...

  5. SQL Server2012 T-SQL基础教程--读书笔记(5-7章)

    SQL Server2012 T-SQL基础教程--读书笔记(5-7章) SqlServer T-SQL 示例数据库:点我 Chapter 05 表表达式 5.1 派生表 5.1.1 分配列别名 5. ...

  6. Python基础教程学习笔记:第一章 基础知识

    Python基础教程 第二版 学习笔记 1.python的每一个语句的后面可以添加分号也可以不添加分号:在一行有多条语句的时候,必须使用分号加以区分 2.查看Python版本号,在Dos窗口中输入“p ...

  7. 【学习笔记】Python基础教程学习笔记

    教程视频网盘共享:http://pan.baidu.com/s/1hrTrR5E 03-python基础.if判断 print 输出数据 print("hahahah")----- ...

  8. 【索引】Objective-C基础教程-读书笔记

    第1章 启程 http://www.cnblogs.com/duxiuxing/p/5492219.html 第2章 对C的扩展 第3章  面向对象编程的基础知识 第4章 继承 第5章 复合 第6章 ...

  9. 《python基础教程》笔记之 异常

    按自己的方式出错 使用raise语句引发一个异常,可以使用一个类(应该是Exception的子类)或者实例参数来作为raise的引发对象.使用类时,程序会自动创建实例,如 >>> r ...

  10. 《python基础教程》笔记之 序列通用操作

    索引 序列中的所有元素都是有编号的--从0开始递增.使用负数索引时,Python会从右边,也就是从最后一个元素开始计数,最后一个元素的位置编号是-1.此外,字符串是一个有字符组成的序列,字符串字面值可 ...

随机推荐

  1. Java 简介

    前言 本文大致介绍 Java 语言 什么是 Java 语言? Java 不仅仅是一门语言,Java 是一个完整的平台,有一个庞大的库,其中包含很多可重用的代码和一个提供诸如安全性,跨操作系统的可移植性 ...

  2. Sed Regular Expression

    Today I also used Sed to do some relatively complex job. So I used regular expression. However, the ...

  3. Javascript模块化编程(二):AMD规范【转】

    作者: 阮一峰 日期: 2012年10月30日 这个系列的第一部分介绍了Javascript模块的基本写法,今天介绍如何规范地使用模块. (接上文) 七.模块的规范 先想一想,为什么模块很重要? 因为 ...

  4. bsgrid

    网址:http://bsgrid.oschina.mopaasapp.com/ var total = gridObj.options.totalRows; jquery必须放在bsgrid的前面 根 ...

  5. c#---部分;把数组或者结构体存入集合里,然后再从集合中取出之后,输出;foreach既可以用到提取数组重点额数据,也可以提取集合中的数据(前提是集合中的元素是相同数据类型)

    1.输入班级人数,统计每个人的姓名,性别,年龄:集合与数组 //Console.Write("请输入班级人数:"); //int a = int.Parse(Console.Rea ...

  6. 在线QQ客服 生成

    很简单,分为个人QQ和企业QQ: 一:企业QQ代码: http://crm2.qq.com/page/portalpage/wpa.php?uin=123456&aty=1&a=0&a ...

  7. python课程

    课程大纲 一.语言基础(5周) 数据类型 流程控制 模块 函数.迭代器.装饰器 递归.迭代.反射 面向对象编程 模拟人生游戏开发 二.网络编程(4周) Socket c/s编程.Twisted网络框架 ...

  8. (转) TensorFlow深度学习,一篇文章就够了

    TensorFlow深度学习,一篇文章就够了 2016/09/22 · IT技术 · TensorFlow, 深度学习 分享到:6   原文出处: 我爱计算机 (@tobe迪豪 )    作者: 陈迪 ...

  9. max_input_vars 的影响

    一同事,让帮忙解决问题:post了1020条数据,结果只显示250条. 判断可能是php的post设置问题,结果发现php.ini里关于post的设置没有问题. 通过 php://input 得到请求 ...

  10. 拿什么来拯救你,我的table

    分类: Html/CSS | 转载请注明: 出自 海玉的博客 本文地址: http://www.hicss.net/how-to-save-you-my-table/ table曾经在网页开发中占据着 ...