6.1 懒惰即美德

斐波那契数列:

>>> fabs = [0, 1]
>>> for i in range(8):
fabs.append(fabs[-1] + fabs[-2])

>>> fabs
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

6.2 抽象和结构

6.3 创建函数

使用def语句创建函数

>>> def fibs(num):
result = [0, 1]
for i in range(num - 2):
result.append(result[-1] + result[-2])
return result

>>> fibs(10)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

6.3.1 文档化函数

6.3.2 并非真正函数的函数

函数如果没有返回值的时候,默认函数None

6.4 参数魔法

6.4.1 值从哪里来

函数的形参

6.4.2 我能改变 参数吗

当在函数内部把参数重绑定的时候,函数外部的变量不受影响。

字符串(以及数字和元组)是不可变的。即无法修改(只能用新的值覆盖)。

可是,将可变的数据结构如列表当做参数时会发生什么?

>>> def change(n):
n[0] = 'Mr. Gumby'

>>> names = ['1','2']
>>> change(names)
>>> names
['Mr. Gumby', '2']

在上述列子中,列表发生变化,这是和前面的区别:当两个变量引用一个列表的时候,他们确实引用同一个列表。

如何避免上述情况呢?可以复制一个列表的副本:

>>> names = ['1','2','3']
>>> n = names[:]                  // 此时n和names是两个独立的列表,互相之间不影响。
>>> n == names
True
>>> n is names
False

(1)为什么要修改参数: 传递的参数是列表的话可以修改值。

(2)如果是元组,字符串或数字是不可以改变值的。可以采用返回值的方式来改变函数外面的实参的值。或者把实参改成元组。

6.4.3 关键字参数和默认值

>>> def hello_l(greeting, name):
print('%s, %s' % (greeting, name))

>>> hello_l("hello", 'world')
hello, world

>>> def hello_2(greeting = "hello", name = "world"):        // 指定参数的默认值
print('%s %s' % (greeting, name))

>>> hello_2(name= "wrold", greeting="hello")                  // 调用的时候可以指定关键字,不怕顺序颠倒
hello wrold

6.4.4 收集参数

让用户提供任意数量的参数。

>>> def print_pa(*pa):
print(pa)

>>> print_pa(1,2,3,4)
(1, 2, 3, 4)

/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*

>>> def print_(title, *pa):               //  星号的意思就是收集剩余的参数
print(title, pa)

>>> print_("fdsfsd", "a","b")
fdsfsd ('a', 'b')                               // 单个星号返回的是元组

>>> def print_2(**pa):                  // 两个星号表示可以提供关键字参数
print(pa)

>>> print_2(x = 1, y = 2, z = 3)
{'x': 1, 'y': 2, 'z': 3}                         // 双星号返回的是字典

>>> def print_3(x, y, z=3, *p1, **p2):      // 混合使用各种参数类型
print(x, y, z)
print(p1)
print(p2)

>>> print_3(1,2,3,5,6,7,foo=1,bar=2)  
1 2 3
(5, 6, 7)
{'foo': 1, 'bar': 2}

6.4.5 参数收集的逆过程

>>> def add(x,y):
return x + y

>>> params = (1,2)
>>> add(*params)
3

6.4.6 练习使用参数

有很多提供和接收参数的方法,要勤练习

总的来说,除去普通的normal args,python中比较特别的函数参数有:关键字参数、默认参数、非关键字可变长参数(元组)、关键字可变长参数(字典),下面将结合例子进行介绍。

关键字参数:调用时指定参数的名称,且与函数声明时的参数名称一致。使用关键字参数允许函数调用时参数的顺序与声明时不一致,仅根据参数的指定进行赋值。例:

# 函数定义
def foo(x, y):
print 'x is %s' % x
print 'y is %s' % y if __name__ == '__main__':
# 标准调用
foo(1, 2) # 关键字调用
foo(y = 1, x = 2)

在标准调用中,x和y依次为1和2;在关键字调用中,x和y的值根据名字指定而与顺序无关。

# 标准调用输出
x is 1
y is 2 # 关键字调用输出
x is 2
y is 1

默认参数:在函数声明时,指定形参的默认值,调用时可不传入改参数(使用默认值)。例:

def tax(cost, rate = 0.17):
print cost * (1 + rate) if __name__ == '__main__':
# rate使用默认值0.17
tax(1000) # rate指定为0.05
tax(1000, 0.05)

使用默认值时,rate为0.17,结果为1170;在指定参数rate时,rate为0.05,结果为1050。

# tax(1000)的输出
1170.0 # tax(1000, 0.05)的输出
1050.0

非关键字可变长参数(元组):“非关键字”“可变长”顾名思义是允许在调用时传入多个“非关键字”参数,python会将这些多出来的参数放入一个元组中。例:

# 定义函数,其中*theRest为非关键字可变长参数
def tupleVarArgs(arg1, arg2='defaultB', *theRest):
print 'formal arg 1: ', arg1
print 'formal arg 2: ', arg2
for eachXtrArg in theRest:
print 'another arg: ', eachXtrArg

我们采用多种调用方式来查看结果,从而理解非关键字可变长参数的使用:

>>> tupleVarArgs('abc')
formal arg 1: abc
formal arg 2: defaultB
>>> tupleVarArgs('abc', 'def')
formal arg 1: abc
formal arg 2: def

>>> tupleVarArgs('abc', 'def', 'xyz', 123.4)
formal arg 1: abc
formal arg 2: def
another arg: xyz
another arg: 123.4

关键字可变长参数(字典):“关键字”“可变长”顾名思义是允许在调用时传入多个“关键字”参数,python会将这些多出来的<参数名, 参数值>放入一个字典中。需要注意的是,关键字变量参数应该为函数定义的最后一个参数,带**。例:

# 定义函数,其中**theRest为关键字可变长参数
def dictVarArgs(arg1, arg2='defaultB', **theRest):
print 'formal arg 1: ', arg1
print 'formal arg 2: ', arg2
for eachXtrArg in theRest.keys():
print 'Xtra arg %s: %s' % (eachXtrArg, str(theRest[eachXtrArg]))

我们采用多种调用方式来查看结果,从而理解关键字可变长参数的使用:

>>> dictVarArgs('abc')
formal arg 1: abc
formal arg 2: defaultB >>> dictVarArgs('abc', 'def')
formal arg 1: abc
formal arg 2: def # a=1和b='aha'即为关键字可变参数,他们会被放入theRest字典
>>> dictVarArgs('abc', 'def', a=1, b='aha')
formal arg 1: abc
formal arg 2: def
Xtra arg a: 1
Xtra arg b: aha # 全部采用关键字参数,但只有a和b是可变的,会被放入theRest
>>> dictVarArgs(arg2='def', a=1, b='aha', arg1='put at the last')
formal arg 1: put at the last
formal arg 2: def
Xtra arg a: 1
Xtra arg b: aha # 这次使用了arg2的默认值
>>> dictVarArgs('one', a=1, b='aha', name=('yuki', 'lau'))
formal arg 1: one
formal arg 2: defaultB
Xtra arg a: 1
Xtra arg b: aha
Xtra arg name: ('yuki', 'lau')

注意

当非关键字可变长参数和关键字可变长参数出现在同一个函数中时,他们应当遵守如下的顺序约定:

def newfoo(normal_arg1, normal_arg2, *non-keywords, ** keywords):
pass

当然,你也可以直接向函数中传入元组和字典对象,如:

>>> newfoo(2, 4, *(6, 8), **{'foo': 10, 'bar': 12})

也可以来个“混搭”,孤立的可变长参数将会被放入对应的tuple或dict中,如:

>>> newfoo(2, 4, 3, x=4, y=5, *aTuple, **aDict)

在这个例子中,参数3会被放入aTuple,参数x=4和y=5会被放入aDict

当然关于Python函数的参数问题还有很多,本文仅仅介绍几种常用的情况,仅做个简单的了解和参考。

6.5 作用域

内建的vars()函数可以返回变量和所对应的值的这个字典,这个字典就是命名空间或者作用域

>>> x = 1
>>> y = 250
>>> vars()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'x': 1, 'y': 250}
>>> scope = vars()
>>> scope['x']
1

>>> def foo(): x = 42     // 改变的是局部变量,不会改变外部的X

>>> x = 1
>>> foo()
>>> x
1

>>> globals()['x']   // 获取全局变量的内建函数
1

下面看如何在函数内部重新绑定变量的值:方法是 将其声明为全局变量

>>> x = 1
>>> def change_g():
global x
x = x + 1

>>> change_g()
>>> x
2

6.6 递归

6.6.1 两个经典:阶乘和幂

>>> def factoria_(n):
result = n
for i in range(1, n):
result *= i
return result

>>> factoria_(3)
6

改成递归:

>>> def factorial(n):
if n == 1:
return 1;
else:
return n * factorial(n-1)

>>> factorial(4)
24

求x的n次幂:

>>> def power(x, n):
if n == 0:
return 1;
else:
return x*power(x, n-1)

>>> power(3, 2)
9

6.6.2 另外一个经典:二分法查找

def search(sequence, number, lower, upper):
print(lower, upper, seq)
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)

python学习(六) 抽象的更多相关文章

  1. Python学习5——抽象,涉及抽象和结构、函数的自定义、参数、作用域、递归

    此处将抽象和结构.自定义函数.参数的使用.作用域.递归放在一起学习,看起来很怪是不是? 但实际上这几者之间是有紧密联系的,不然Python基础教程(第三版)的作者为什么会把它们放在一起哪?手动滑稽 好 ...

  2. Python学习(六) Python数据类型:字典(重要)

    字典dict: 字典其实就相当于java里面的Map,用来存储键值对的.其中存储的数据时无序的. 假如有这样的数据: t1=['name','age','sex'] t2=['tom',30,'mal ...

  3. Python学习笔记-抽象

    懒惰即美德.代码量少. hasattr判断函数是否可用. 创建函数. def hello(name) return 'hello,'+name+'!' 文档化函数: 加注释(#开头) 文档字符串.函数 ...

  4. python学习笔记(六)文件夹遍历,异常处理

    python学习笔记(六) 文件夹遍历 1.递归遍历 import os allfile = [] def dirList(path): filelist = os.listdir(path) for ...

  5. Python学习笔记(六)

    Python学习笔记(六) Ubuntu重置root密码 Ubuntu 16.4 目录结构 Ubuntu 命令讲解 1. Ubuntu重置root密码 启动系统,显示GRUB选择菜单(如果默认系统启动 ...

  6. 【python学习笔记】7.更加抽象

    [python学习笔记]7.更加抽象 类的定义就是执行代码块 在内存保存一个原始实例,可以通过类名来访问 类的实例化,是创建一个原始实例的副本, 并且所有成员变量与原始实例绑定 通过修改实例变量,可以 ...

  7. 【python学习笔记】6.抽象

    [python学习笔记]6.抽象 创建函数: 使用def语句定义函数,不用声明参数类型,和返回值类型 def function_name(param1, param2): 'this is docum ...

  8. python学习第六讲,python中的数据类型,列表,元祖,字典,之列表使用与介绍

    目录 python学习第六讲,python中的数据类型,列表,元祖,字典,之列表使用与介绍. 二丶列表,其它语言称为数组 1.列表的定义,以及语法 2.列表的使用,以及常用方法. 3.列表的常用操作 ...

  9. python学习笔记4_类和更抽象

    python学习笔记4_类和更抽象 一.对象 class 对象主要有三个特性,继承.封装.多态.python的核心. 1.多态.封装.继承 多态,就算不知道变量所引用的类型,还是可以操作对象,根据类型 ...

  10. Python学习第六课

    Python学习第六课 课前回顾 列表 创建 通过 [] :写在[]里,元素之间用逗号隔开 对应操作: 查 增 append insert 改(重新赋值) 删除(remove del pop(删除后会 ...

随机推荐

  1. mongodb笔记(一) 分片 &&文档连接

    版本:mongodb3.4 ; 分片: 工作顺序:router=>config=>shards 一,配置config: 3.4中config必须为replSet.下面配置两个config. ...

  2. MVVM4

    原地址(内容更丰富):http://www.cnblogs.com/888h/category/269092.html MVVM架构的简单解析   图1 View.ViewModel.Model之间的 ...

  3. python标准日志模块logging使用

    python的标准库里的日志系统从Python2.3开始支持.只要import logging这个模块即可使用.如果你想开发一个日志系统, 既要把日志输出到控制台, 还要写入日志文件,只要这样使用: ...

  4. Win7性能选项

    1. 性能选项:只保留勾选下面的即可. 2. 隐藏explorer导航栏的“库”列表 HKEY_CLASSES_ROOT\CLSID\{031E4825-7B94-4dc3-B131-E946B44C ...

  5. Centos6.8 JDK配置

    记录一下在这个服务器配置的过程 ssh root@IP Password --------------------------------------------------------------- ...

  6. react:reducer-creator

    function createReducer(initialState, handlers) { return function reducer(state = initialState, actio ...

  7. BAT级别对照表

  8. [Hive]HiveServer2配置

    HiveServer2(HS2)是一个服务器接口,能使远程客户端执行Hive查询,并且可以检索结果.HiveServer2是HiveServer1的改进版,HiveServer1已经被废弃.HiveS ...

  9. Android 应用程序窗体显示状态操作(requestWindowFeature()的应用)

     我们在开发程序是经常会需要软件全屏显示.自定义标题(使用按钮等控件)和其他的需求,今天这一讲就是如何控制Android应用程序的窗体显示. 首先介绍一个重要方法那就是requestWindowF ...

  10. 4.CRT远程连接的使用

    目录: 1.为什么需要远程连接? 2.一般的远程连接工具有哪些? 3.远程连接的原理? 4.远程连接的软件的功能和使用相关技巧? 1.为什么选择远程连接? 因为在实际工作中,机房一般都不可能在办公室, ...