欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python学习笔记(七)函数

程序员文章站 2024-01-07 11:40:04
...

函数

  • 可以实现信息模块化的目标。
  • 函数或方法能重复使用,便于日后的调试和维护。
  • 从面向对象的角度来看,函数提供了操作接口的方法,有数据隐藏的作用。

根据程序设计的需求,Python的函数大致分为3种:

  • 系统内置函数(Built-In Function,BIF),如获取类型的type()函数。
  • 提供的函数标准库(Standard Library)。就像导入math模块时,会使用类math提供的类方法。
  • 程序设计者使用def关键字自定义的函数。

Python内置函数

太多了,百度找

函数基础

  • 定义函数:先以def关键字定义total()函数上及函数主体,它提供的是函数执行的根据。
  • 调用程序:从程序语句中“调用函数”total()。

语法如下:

def 函数名称:
    函数主体_suite
    [return]
  • def是关键字,用来定义函数,函数程序区块的开头,尾端要有“:”
  • 函数名称:遵守标识符名称的命名规范。
  • 参数列表:成为形式参数列表(format argument list),用来接受数值,其名称也适用于标识符名称的命名规范,可以有多个参数,也可以省略参数。
  • 函数主体必须缩排,可以是单行或多行语句。
  • return:返回运算后的值,无数值返回可省略。

定义函数

下面创建一个Fibonacci序列:

def fib(n):    # write Fibonacci series up to n
    """Print a Fibonacci series up to n."""
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()

# Now call the function we just defined:
fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 

函数体的第一行可以是一个可选的字符串文本;此字符串是该函数的文档字符串,或称为docstring。

如果你使用过其他语言,你可能会反对说:fib 不是一个函数,而是一个过程(子程序),因为它并不返回任何值。事实上,没有return语句的函数也返回一个值,尽管是一个很无聊的值。此值被称为 None(它是一个内置的名称)。如果 None只是唯一的输出,解释器通常不会打印出来。

返回值

用法与其他语言相同

def total(n1, n2, n3):
    result = 0
    for item in range(n1, n2 + 1, n3):
        result += item
    return result
print('cal')
key = input('start')
while key == 'y':
    start = int(input('input init'))
    finish = int(input('input end'))
    step = int(input('input mid'))

    print('total:{0:,}'.format(total(start, finish, step)))
    key = input('start')
def answer(x, y):
    return x + y, x * y, x / y

numA = int(input('first:'))
numB = int(input('second:'))
print('answer:', answer(numA, numB))
first:146
second:63
answer: (209, 9198, 2.3174603174603177)
  • 返回单个的值或对象。
  • 多个值或对象可储存于元组对象中。
  • 未使用return语句时,默认返回None。

参数的基本机制

  • 实际参数(Actual Argument):在调用函数时,将接受的数据或对象传递给定义参数,默认为位置参数。
  • 形式参数(Formal Parameter):定义函数时,用来接收实际参数所传递的数据,进入函数主体执行语句或运算,默认以位置函数为主。

函数的传递

  • 传值(call by value):若为数值数据,则先把数据复制一份在传递,原来的参数内容不会受到影响。
  • 传址(pass-by-reference):传递的是参数的内存地址,因而会影响原有的变量内容。
//传递参数的规则

  • 不可变(Immutable)对象(如数值,字符串):使用对象引用时会先复制一份在传递。
  • 可变(Mutable)对象(如列表):使用对象引用时会直接传递内存地址。
def passFun(name, score):
    print('name', id(name))
    print('score',id(score))
na = 'Mary'; sc = [75, 68]
passFun(na, sc)
print('na', id(na))
print('sc', id(sc))
name 2142017634632
score 2142016869192
na 2142017634632
sc 2142016869192

默认参数值

默认参数值是指自定义函数时,将形参给与默认值,当某个参数没有传递数据时,自定义函数可以使用其默认值。

def ask_ok(prompt, retries=4, reminder='Please try again!'):
    while True:
        ok = input(prompt)
        if ok in ('y', 'ye', 'yes'):
            return True
        if ok in ('n', 'no', 'nop', 'nope'):
            return False
        retries = retries - 1
        if retries < 0:
            raise ValueError('invalid user response')
        print(reminder)

该函数可以通过几种方式调用:

  • 只提供必须的参数: ask_ok('Do you really want to quit?')
  • 提供可选参数中的一个: ask_ok('OK to overwrite the file?', 2)
  • 或者提供所有参数: ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')

关键字函数

函数还可以用kwarg=value形式的关键字参数调用。对于实例,具有以下功能:

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
    print("-- This parrot wouldn't", action, end=' ')
    print("if you put", voltage, "volts through it.")
    print("-- Lovely plumage, the", type)
    print("-- It's", state, "!")

接受一个必须的参数(voltage)和三个可选参数

parrot(1000)                                          # 1 positional argument
parrot(voltage=1000)                                  # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM')             # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000)             # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump')         # 3 positional arguments
parrot('a thousand', state='pushing up the daisies')  # 1 positional, 1 keyword

以下调用将无效:

parrot()                     # required argument missing
parrot(voltage=5.0, 'dead')  # non-keyword argument after a keyword argument
parrot(110, voltage=220)     # duplicate value for the same argument
parrot(actor='John Cleese')  # unknown keyword argument

  • 调用函数时,第一个参数以位置为主,第二个参数为关键字参数,能正确返回其运算结果
  • 相反的,第一个参数以关键字参数为主,第二个参数以位置为主,会发生错误。

任意参数的列表

定义函数的形式参数和调用函数的实际参数一位置为主,才能按序对应。为了让形参和实参更灵活应用,可前缀*和**来搭配使用。定义函数时,以运算表达式来呈现,‘*’和元组相结合,‘**’则与字典配合收集多余的实参。调用函数时,针对实际参数,*运算符拆分可迭代对象,**运算符以映射对象为拆分对象。

形参的*表达式
def concat(*args, sep="/"):
    return sep.join(args)

concat("earth", "mars", "venus")

concat("earth", "mars", "venus", sep=".")
'earth/mars/venus'
'earth.mars.venus'

Python3.x以后的版本,还可以在‘*tuple’对象之后加入关键字参数,所以调用函数时,可直接将参数以关键字参数方式来传递。

def student(name, *score, subject = 4):
    if subject >= 1 :
        print('name:', name)
        print('total:', subject, 'subject, score:', *score)
    total = sum(score)
    print('total:', total, ', average:', '%.4f'%(total/subject))
###
student('Tomas', 78, 65, 93, 81)
student('Dick', 100, 100, 100, subject = 3)
name: Tomas
total: 4 subject, score: 78 65 93 81
total: 317 ,average: 79.2500
name: Dick
total: 3 subject, score: 100 100 100
total: 300 ,average: 100.0000
**表达式与字典配合
def score(**value):
    print('score: ', value)
score(Eng = 90, Math = 80, CHI = 70)
def student(msg, **pern):
    print(msg, '按学生名字排序')
    for key in sorted(pern):
        print('{0:8s}{1}'.format(key, pern[key]))
        print('-' * 20)
        ###
        low60 = {k : v for k, v in pern.items()
                 if v < 60}
        count = len(low60)
        print('low60', count, '人')
        print(low60)
student('2015学年', Mary = 90, Steven = 45,
        Eric = 75, John = 55, Ivy = 75,
        Tomas = 87, Ford = 41, Helen = 88)

作用域

无论是变量还是函数,对于Python而言都有作用域(Scope)。变量根据其作用域可分为下述三种:

  • 全局(Global)作用域:适用于整个文件(*.py)
  • 局部(Local)作用域:适用于所声明的函数或流程控制的程序区块,离开此范围就会结束其生命周期。
  • 内置(Built-In)作用域:由内置函数(BIF)通过builtins模块来建立所使用的范围,在该模块中使用的变量会自动被所有的模块所拥有,它可以在不同的文件中使用。

通常Python程序设计语言根据其作用域可以创建4种函数:全局函数,局部函数,lambda函数和方法。

局部函数与闭包

在Python程序设计语言中,可以在函数中定义其他函数,后者被称为内部函数,局部函数或内置函数。

def exter(x, y):
    def internal(a, b):
        return divmod(a, b) #return a//b, a%b
    return internal(x, y)
print(exter(35, 4))

lambda函数

可以使用 lambda关键字创建小的匿名函数。此函数会返回两个参数的总和: lambda a, b: a+b.。Lambda函数可用于需要函数对象的任何地方。它们在语法上限于单个表达式。语义上,它们只是用于正常函数定义的语法糖。像嵌套的函数定义,lambda 函数可以从包含它的作用域中引用变量:

lambda 参数列表, ... :表达式
  • lambda函数只会有一行语句
  • 表达式不能有return语句
def calc(x, y):
    return x ** y
calc = lambda x, y : x ** y
  • 自定义函数时,函数名称为calc,可作为调用lambda()函数的变量名称,所以自定义函数有名称,lambda函数无名称,需要借助设置的变量名称。
  • 表达式的值在calc()函数中以return形式返回,而lambda()的运算结果由变量calc存储。所以定义函数时,函数主体有多行语句,可以是语句,也可以是表达式。lambda()函数只能有一行语句。
pern = [('Mary', 1988, 'Shanghai'),
        ('Davie', 1992, 'Hangzhou'),
        ('Andy', 1999, 'Wuhan'),
        ('Monica', 1987, 'Shenzhen'),
        ('Cindy', 1996, 'Shanghai')]
st = lambda item : item[0]
pern.sort(key = st)
print('按名字排序:')
for name in pern:
    print('{:6s}, {}, {:10s}'.format(*name))

pern.sort(key = lambda item:item[2], reverse = True)
print('按出生地降序排序:')
for name in pern:
    print('{:6s}, {}, {:10s}'.format(*name))

pern.sort(key = lambda item:item[1])
print('按出生年份升序排序:')
for name in pern:
    print('{:6s}, {}, {:10s}'.format(*name))
按名字排序:
Andy  , 1999, Wuhan     
Cindy , 1996, Shanghai  
Davie , 1992, Hangzhou  
Mary  , 1988, Shanghai  
Monica, 1987, Shenzhen  
按出生地降序排序:
Andy  , 1999, Wuhan     
Monica, 1987, Shenzhen  
Cindy , 1996, Shanghai  
Mary  , 1988, Shanghai  
Davie , 1992, Hangzhou  
按出生年份升序排序:
Monica, 1987, Shenzhen  
Mary  , 1988, Shanghai  
Davie , 1992, Hangzhou  
Cindy , 1996, Shanghai  
Andy  , 1999, Wuhan     
  • 使用filter()函数
def getNums(x):
    return x > 2
lt = range(10)
list(filter(getNums, lt))

递归

一个简单的阶乘递归函数

def rec(x):
    if x > 0:
        return x * rec(x - 1)
    else:
        return 1
递归的思想与其他程序语言相同,懂得自然懂。

相关标签: Python

上一篇:

下一篇: