05. Python-抽象1

目录

1. 懒惰

2. 抽象和结构

3. 自定义函数

3.1 给函数编写文档

3.2 不是函数的函数

4. 参数魔法

4.1 值从哪里来

4.2 能修改参数吗

4.3 关键字参数和默认值

4.4 收集参数

4.5 分配参数

5. 作用域

6. 递归


1. 懒惰

斐波那契数 (一种数列,其中每个数都是前两个数的和)

fibs = [0, 1]
for i in range(8):
    fibs.append(fibs[-2] + fibs[-1])
>>> fibs
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
fibs = [0, 1]
num = int(input('How many Fibonacci numbers do you want? '))
for i in range(num-2):
    fibs.append(fibs[-2] + fibs[-1])
print(fibs)

创建一个名为fibs 的函数,并在需要计算斐波那契数时调用它。如果需要在多个地方计算斐波那契数,这样做可节省很多精力。

num = input('How many numbers do you want? ')
print(fibs(num))

2. 抽象和结构

下载网页并计算使用频率

page = download_page()
freqs = compute_frequencies(page)
for word, freq in freqs:
    print(word, freq)

3. 自定义函数

要判断某个对象是否可调用,可使用内置函数callable 

>>> import math
>>> x = 1
>>> y = math.sqrt
>>> callable(x)
False
>>> callable(y)
True

 使用def 定义函数。

def hello(name):
    return 'Hello, ' + name + '!'
>>> print(hello('world'))
Hello, world!
>>> print(hello('Gumby'))
Hello, Gumby!

编写一个函数,返回一个由斐波那契数组成的列表。

def fibs(num):
     result = [0, 1]
     for i in range(num-2):
         result.append(result[-2] + result[-1])
     return result
>>> fibs(10)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
>>> fibs(15)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]

3.1 给函数编写文档

可添加注释(以#打头的内容)。

也可以添加独立的字符串。如def 语句后面(以及模块和类的开头)。放在函数开头的字符串称为文档字符串 (docstring),将作为函数的一部分存储起来。

def square(x):
    'Calculates the square of the number x.'
    return x * x
# 访问文档字符串
# __doc__ 是函数的一个属性。
>>> square.__doc__
'Calculates the square of the number x.'
# 用help获取函数信息
>>> help(square)
Help on function square in module __main__:

square(x)
Calculates the square of the number x.

3.2 不是函数的函数

在Python中,函数就是函数,即使它严格来说并非函数。什么都不返回的函数不包含return 语句,或者包含return 语句,但没有在return 后面指定值。

def test():
    print('This is printed')
    return
    print('This is not')
# 这里使用return 语句只是为了结束函数。
>>> x = test()
This is printed
# 跳过了第二条print语句。(这有点像在循环中使用break ,但跳出的是函数。)
# 既然test什么都不返回,那么x向的是什么,什么都没有
>>> x
>>>
>>> print(x)
None

所有的函数都返回值。如果你没有告诉它们该返回什么,将返回None 。

如果在if 之类的语句中返回值,务必确保其他分支也返回值,以免在调用者期望函数返回一个序列时(举个例子),不小心返回了None 。

4. 参数魔法

4.1 值从哪里来

在def 语句中,位于函数名后面的变量通常称为形参 ,而调用函数时提供的值称为实参 。

4.2 能修改参数吗

参数不过是变量而已,行为与你预期的完全相同。在函数内部给参数赋值对外部没有任何影响。

在try_to_change内,将新值赋给了参数n ,这对变量name 没有影响。说到底,这是一个完全不同的变量。

>>> def try_to_change(n):
       n = 'Mr. Gumby'

>>> name = 'Mrs. Entity'
>>> try_to_change(name)
>>> name
'Mrs. Entity'
# 传递并修改参数的效果类似于下面这样:
>>> name = 'Mrs. Entity'
>>> n = name            # 与传递参数的效果几乎相同
>>> n = 'Mr. Gumby'     # 这是在函数内进行的
>>> name
'Mrs. Entity'

变量n 变了,但变量name 没变。同样,在函数内部重新关联参数(即给它赋值)时,函数外部的变量不受影响。

参数存储在局部作用域内。

字符串(以及数和元组)是不可变的(immutable),这意味着你不能修改它们(即只能替换为新值)。但如果参数为可变的数据结构(如列表)呢?

>>> def change(n):
        n[0] = 'Mr. Gumby'
   
>>> names = ['Mrs. Entity', 'Mrs. Thing']
>>> change(names)
>>> names
['Mr. Gumby', 'Mrs. Thing']

4.3 关键字参数和默认值

使用名称指定的参数称为关键字参数 ,主要优点是有助于澄清各个参数的作用。也可以指定默认值。

def hello_1(greeting, name):
    print('{}, {}!'.format(greeting, name))

def hello_2(name, greeting):
    print('{}, {}!'.format(name, greeting))
>>> hello_1('Hello', 'world')
Hello, world!
>>> hello_2('Hello', 'world')
Hello, world!

def hello_3(greeting='Hello', name='world'):
    print('{}, {}!'.format(greeting, name))
# 给参数指定默认值后,调用函数时可不提供它!
# 可以根据需要,一个参数值也不提供、提供部分参数值或提供全部参数值。
>>> hello_3()
Hello, world!
>>> hello_3('Greetings')
Greetings, world!
>>> hello_3('Greetings', 'universe')
Greetings, universe!

4.4 收集参数

参数前面的星号将提供的所有值都放在一个元组中,也就是将这些值收集起来。

def print_params(*params):
    print(params)
>>> print_params('Testing')
('Testing',)
>>> print_params(1, 2, 3)
(1, 2, 3)

带星号的参数也可放在其他位置(而不是最后)

>>> def in_the_middle(x, *y, z):
...     print(x, y, z)
...
>>> in_the_middle(1, 2, 3, 4, 5, z=7)
1 (2, 3, 4, 5) 7
>>> in_the_middle(1, 2, 3, 4, 5, 7)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: in_the_middle() missing 1 required keyword-only argument: 'z'

星号不会收集关键字参数。

>>> print_params_2('Hmm...', something=42)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: print_params_2() got an unexpected keyword argument 'something'

要收集关键字参数,可使用两个星号。

>>> def print_params_3(**params):
...     print(params)
...
>>> print_params_3(x=1, y=2, z=3)
{'z': 3, 'x': 1, 'y': 2}
def print_params_4(x, y, z=3, *pospar, **keypar):
    print(x, y, z)
    print(pospar)
    print(keypar)
>>> 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
()
{}

4.5 分配参数

只有在定义函数(允许可变数量的参数)或 调用函数时(拆分字典或序列)使用,星号才能发挥作用。

>>> def with_stars(**kwds):
...     print(kwds['name'], 'is', kwds['age'], 'years old')
...
>>> def without_stars(kwds):
...     print(kwds['name'], 'is', kwds['age'], 'years old')
...
>>> args = {'name': 'Mr. Gumby', 'age': 42}
>>> with_stars(**args)
Mr. Gumby is 42 years old
>>> without_stars(args)
Mr. Gumby is 42 years old

5. 作用域

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

6. 递归

函数可调用自身,这称为递归 。可使用递归完成的任何任务都可使用循环来完成,但有时使用递归函数的可读性更高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南河Aure

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值