《Beginning Python From Novice to Professional》学习笔记八:Abstraction

来源:互联网 发布:扫雷c语言代码 编辑:程序博客网 时间:2024/04/25 13:09

Laziness Is a Virtue --- Real programmers are lazy. Not lazy in a bad way, but in the sense that they don’t do unnecessary work.

1.创建函数

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

2.Documenting Functions - 方便他人理解
可以用#加以注释,但也可以在函数名后直接加上String,即可成为函数的一部分(docstring),可以用__doc__访问(此机制有点类似于Matlab)


square.__doc__
---> 'Calculates the square of the number x.'
help (square)
---> Help on function square in module __main__:
---> square(x)
        Calculates the square of the number x.

3.参数的可更改性
不可更改的(immutable)元素,如Strings、numbers和tuples作为参数传入时,在函数内部改变其形参值不会影响实参的值。

try_to_change(name)
name   ---> 'Mrs. Entity'

但是可更改的(mutable)元素,如List、Dictionary

change(names)
names   ---> ['Mr. Gumby', 'Mrs. Thing']

如果想让List元素传入而不受函数内部的影响,可以做一份拷贝,接上例
change(names[:])   #name[:]会返回一份name的拷贝
names   ---> ['Mrs. Entity', 'Mrs. Thing']
最后,如果参数是不可更改的,则函数内部的更改无法(Sorry, but it can’t be done.)解决方案有二:
一、将在内部更改过的参数全部返回(超过一个的话可以用Tuple)
def inc(x): return x + 1
foo = 10
foo = inc(foo)
foo   ---> 11
二、将参数打包在一个List中作为参数传入
def inc(x): x[0] = x[0] + 1
foo = [10]
inc(foo)
foo   ---> [11]

4.带关键字的参数(Keyword Parameters)和参数默认值
前面所述的参数均为位置性参数(positional parameters),即参数的顺序位置是重要的。
通过在传入参数时带上参数的关键字可以忽略这种顺序位置(但尽量不要这样写

hello_4('Mars', punctuation='.')  
#'Mars'没有带上关键字name,但因为它在第一个,因此被认为是传给name的
---> Hello, Mars.

5.参数Collection(参数个数的不确定化)
如下的例子很好地说明了这一概念:

但是此时参数不可以使用Keyword了:
print_params_2('Hmm...', something=42)   #解释器会将会报错unexpected keyword argument 'something'

若想使用Keyboard,可以使用以下版本:
def print_params_3(**params):   #此时参数前加了两个*,说明这之后的参数将被看成一个Dictionary
    print params

print_params_3(name='thy', age=30)   #但此时参数不可以像Dictionary一样用number作key
---> {'age': 30, 'name': 'thy'}
最后看一个综合示例:


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

6.参数解包(5的逆过程)
Tuple的解包:
def add(x, y): return x + y
params = (1, 2)
add(*params)   ---> 3

Dictionary的解包:(接5中的print_params_3函数)
params = {'name': 'Sir Robin', 'greeting': 'Well met'}
print_params_3(**params)
---> {'name': 'Sir Robin', 'greeting': 'Well met'}

两段对比函数代码:


7.作用域Scoping
内置函数vars()可返回作用域,其结构为Dictionary。
x = 1
scope = vars()   #scope为Dictionary,其中包含'x':1这一项
scope['x']   ---> 1
scope['x'] += 1   #仅作为示例,实际中不建议使用
x   ---> 2

除了全局作用域之外,每一个函数均会构建自己的一个作用域。
在函数中可以访问全局变量,但不可以更改全局变量
def combine(parameter):
    external = 'mark'
    print parameter + external

external = 'berry'
combine('Shrub')
---> Shrubmark
external
---> 'berry'   #external的全局值未受影响
作者的提醒:■Caution Referencing global variables like this is a source of many bugs. Use global variables with care.


如果在某个作用域中有变量与全局的某变量重名,可以用全局引用的方法,而且此时可以更改全局变量

以下代码可实现同样的效果:

《Python技术参考大全》:LGB规则,名字引用搜寻顺序为Local->Global->Built-in。

8.递归(书上都是说的递归的原理,也没讲什么新的内容,直接贴一点关键内容吧)
A useful recursive function usually consists of the following parts:
A base case (for the smallest possible problem) when the function returns a value directly
A recursive case, which contains one or more recursive calls on smaller parts of the problem
再来个最经典的阶乘示例:

更经典的二分查找示例(^_^

#测试
seq = [34, 67, 8, 123, 4, 100, 95]
seq.sort()   #bisect模块中有标准的二分查找法实现
search(seq, 34)   ---> 2

 

原创粉丝点击