python123自定义幂函数_Python基础教程-第6章-函数

6.1 自定义函数

函数执行特定的操作并返回一个值1,你可以调用它。一般而言,要判断某个对象是否可调用,可使用内置函数callable。

import math

x = 1

y = math.sqrt

callable(x)

# False

callable(y)

# True

使用def来定义函数。

def hello(name):

return 'Hello, ' + name + '!'

6.1.1 给函数编写文档

在有些地方,如def语句后面(以及模块和类的开 头,这将在第7章和第10章详细介绍),添加这样的字符串很有用。放在函数开头的字符串称为 文档字符串(docstring),将作为函数的一部分存储起来。

特殊的内置函数help很有用。在交互式解释器中,可使用它获取有关函数的信息,其中包含 函数的文档字符串。

def square(x):

'Calculates the square of the number x.'

return x * x

# 访问函数文档字符串

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.

6.1.2 其实并不是函数的函数

在Python中,有些函数什么都不返回。什么都不返回的函数不包含return语句,或者包含return语句,但没 有在return后面指定值。

def test():

print('This is printed')

return

x = test()

# This is printed

print(x)

# None

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

6.2 参数魔法

在def语句中,位于函数名后面的变量通常称为形参,而调用函数时提供的值称为实参,在很重要的情况下,我会将实参称为值

6.2.1 我能修改参数吗

函数通过参数获得了一系列的值,你能对其进行修改吗?如果这样做,结果将如何?参数不过是变量而已,行为与你预期的完全相同。在函数内部给参数赋值对外部没有任何影响。

def try_to_change(n):

n = 'Mr. Gumby'

name = 'Mrs. Entity'

try_to_change(name)

name

# 'Mrs. Entity'

在try_to_change内,将新值赋给了参数n,但如你所见,这对变量name没有影响。在函数内部重新关联参数(即给它赋值)时,函数外部的变量不受影响。参数存储在局部作用域内.

但如果参数为可变的数据结构(如列表)呢?

def change(n):

n[0] = 'Mr. Gumby'

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

change(names)

names

# ['Mr. Gumby', 'Mrs. Thing']

而在这个示例中,修改了变量关联到的列表。这是因为将同一个列表赋给两个变量时,这两个变量将同时指向这个列表。 就这么简单。下面这个示例说明了这种情况。

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

n = names # 再次假装传递名字作为参数 >>>

n[0] = 'Mr. Gumby' # 修改列表

names

# ['Mr. Gumby', 'Mrs. Thing']

使用函数来修改数据结构(如列表或字典)是一种不错的方式

抽象的关键在于隐藏所有的更新细节,为此可使用函数。

def init(data):

data['first'] = {}

data['middle'] = {}

data['last'] = {}

storage = {}

init(storage)

# storage

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

6.2.3 关键字参数和默认值

有时候,参数的排列顺序可能难以记住,尤其是参数很多时。为了简化调用工作,可指定参 数的名称。 然而,关键字参数最大的优点在于,可以指定默认值。

def hello_1(greeting, name):

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

hello_1(greeting='Hello', name='world')

def hello_3(greeting='Hello', name='world'):

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

hello_3()

# Hello, world!

hello_3('Greetings', 'universe')

# Greetings, universe!

6.2.4 收集参数

有时候,允许用户提供任意数量的参数很有用。为此,应允许用户提供任意数量的姓名。实际上,这实现起来并不难。

请尝试使用下面这样的函数定义:

def print_params(*params):

print(params)

print_param('Testing')

# 'Testing',

print_param('Testing','Hello')

# 'Testing','Hello'

def print_params_2(title, *params): # 因此星号意味着收集余下的位置参数。

print(title)

print(params)

# Params:

# (1, 2, 3)

与赋值时一样,带星号的参数也可放在其他位置(而不是最后),但不同的是,在这种情况 下你需要做些额外的工作:使用名称来指定后续参数。

def in_the_middle(x,*y,z):

print(x,y,z)

in_the_middle(1,2,3,4,z=6)

# 1 (2, 3, 4) 6

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

def print_params_3(**params):

print(params)

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

# {'x': 1, 'y': 2, 'z': 3}

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}

6.2.5 分配参数

def add(x, y):

return x + y

params = (1, 2)

add(*params)

# 3

def hello_3(greeting='Hello', name='world'):

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

params = {'name': 'Sir Robin', 'greeting': 'Well met'}

hello_3(**params)

# Well met, Sir Robin!

6.3 作用域

在函数内使用的变量称为局部变量(与之相对的是全局变量)。参数类似于局部变量,因此参数与全局变量同名不会有任何问题。

如果有一个局部变量或参数与你要访问的全局变量同名,就无法直接访问全局变量,因为它被局部变量遮住了。必要时可使用globals()[‘parameter’]来访问它。

def combine(parameter):

print(parameter + globals()['parameter'])

parameter = 'berry'

combine('Shrub')

# Shrubberry

在函数内部给变量赋值时,该变量默认为 局部变量,除非你明确地告诉Python它是全局变量。那么如何将这一点告知Python呢?

x = 1

def change_global():

global x

x=x+1

change_global()

# x = 2

Python函数可以嵌套,即可将一个函数放在另一个函数内。

6.4 递归

通常递归包括两个部分:

基线条件(针对最小的问题):满足这种条件时函数将直接返回一个值。

递归条件:包含一个或多个调用,这些调用旨在解决问题的一部分。

# 阶乘的递归

def factorial(n):

if n == 1:

return 1

else:

return n * factorial(n-1)

# factorial(10) = 3628800

# 幂函数的递归

def power(x, n):

if n == 0:

return 1

else:

return x * power(x, n - 1)

# power(2,3) = 8

6.4.2 二分查找

这里的关键是,这种算法自然而然地引出了递归式定义和实现。先来回顾一下定义,确保你知道该如何做。

如果上限和下限相同,就说明它们都指向数字所在的位置,因此将这个数字返回。

否则,找出区间的中间位置(上限和下限的平均值),再确定数字在左半部分还是右半部分。然后在继续在数字所在的那部分中查找。

def search(sequence, number, lower=0, upper=None):

if upper is None:

upper = len(sequence) - 1

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)

seq = [34, 67, 8, 123, 4, 100, 95]

seq.sort()

search(seq, 34)

# 2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值