Python学习 Day7 Python3 函数

Posted paulzhang511

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python学习 Day7 Python3 函数相关的知识,希望对你有一定的参考价值。

 

 

Python3 函数

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。

定义一个函数

你可以定义一个由自己想要功能的函数,以下是简单的规则:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

参数传递

在 python 中,类型属于对象,变量是没有类型的:

a=[1,2,3]

a="Runoob"

以上代码中,[1,2,3] 是 List 类型,"Runoob" 是 String 类型,而变量 a 是没有类型,她仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象。

可更改(mutable)与不可更改(immutable)对象

在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象

  • 不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a。
  • 可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

python 函数的参数传递:

  • 不可变类型:类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
  • 可变类型:类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响。

python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。

python 传不可变对象实例:

#!/usr/bin/python3
 
def ChangeInt( a ):
    a = 10

b = 2
ChangeInt(b)
print( b ) # 结果是 2

实例中有 int 对象 2,指向它的变量是 b,在传递给 ChangeInt 函数时,按传值的方式复制了变量 b,a 和 b 都指向了同一个 Int 对象,在 a=10 时,则新生成一个 int 值对象 10,并让 a 指向它。

传可变对象实例:

可变对象在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了。例如:

#!/usr/bin/python3
 
# 可写函数说明
def changeme( mylist ):
   "修改传入的列表"
   mylist.append([1,2,3,4]);
   print ("函数内取值: ", mylist)
   return
 
# 调用changeme函数
mylist = [10,20,30];
changeme( mylist );
print ("函数外取值: ", mylist)

传入函数的和在末尾添加新内容的对象用的是同一个引用。故输出结果如下:

函数内取值:  [10, 20, 30, [1, 2, 3, 4]]
函数外取值:  [10, 20, 30, [1, 2, 3, 4]]

参数

以下是调用函数时可使用的正式参数类型:

  • 必需参数
  • 关键字参数
  • 默认参数
  • 不定长参数

必需参数

必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

如调用printme()函数,你必须传入一个参数,不然会出现语法错误:

#!/usr/bin/python3
 
#可写函数说明
def printme( str ):
   "打印任何传入的字符串"
   print (str);
   return;
 
#调用printme函数
printme();

以上实例输出结果:

Traceback (most recent call last):
  File "test.py", line 10, in <module>
    printme();
TypeError: printme() missing 1 required positional argument: str

关键字参数

关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。

使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值

以下实例中演示了函数参数的使用不需要使用指定顺序:

#!/usr/bin/python3
 
#可写函数说明
def printinfo( name, age ):
   "打印任何传入的字符串"
   print ("名字: ", name);
   print ("年龄: ", age);
   return;
 
#调用printinfo函数
printinfo( age=50, name="runoob" );

以上实例输出结果:

名字:  runoob
年龄:  50

默认参数

调用函数时,如果没有传递参数,则会使用默认参数。以下实例中如果没有传入 age 参数,则使用默认值:

def printinfo(name, age=35):
    print ("名字: ", name);
    print ("年龄: ", age);
    return;

printinfo(alex)

输出结果:

名字:  alex
年龄:  35

参数默认值的继承性

#! /usr/bin/env python
# -*- coding: utf-8 -*-

class demo_list:
    def __init__(self, l=[]):
        print(id(l),x=‘‘)
        self.l = l
    def add(self, ele):
        self.l.append(ele)

def appender(ele):
    obj = demo_list()
    obj.add(ele)
    print obj.l

if __name__ == "__main__":
    for i in range(5):
        appender(i)

输出结果为:

4346933688 [0] 
4346933688 [0, 1] 
4346933688 [0, 1, 2] 
4346933688 [0, 1, 2, 3] 
4346933688 [0, 1, 2, 3, 4]

可以清晰看出每次调用__init__函数时,默认参数l都是同一个对象,其id为4346933688。

关于默认参数,文档中是这样说的:

Functions in Python are first-class objects, and not only a piece of code.

我们可以这样解读:函数也是对象,因此定义的时候就被执行,默认参数是函数的属性,它的值可能会随着函数被调用而改变。其他对象不都是如此吗?

带*的参数:用来接受可变数量参数

目前为止,我们要定义一个函数的时候,必须要预先定义这个函数需要多少个参数(或者说可以接受多少个参数)。一般情况下这是没问题的,但是也有在定义函数的时候,不能知道参数个数的情况(想一想C语言里的printf函数),在Python里,带*的参数就是用来接受可变数量参数的。看一个例子:

def funcD(a, b, *c):
  print(a)
  print(b)
  print("length of c is: %d " % len(c))
  print(c)

funcD(1,2,3,4,5,6)

结果:

1
2
length of c is: 4 
(3, 4, 5, 6)

我们看到,前面两个参数被a、b接受了,剩下的4个参数,全部被c接受了,c在这里是一个tuple。我们在调用funcD的时候,至少要传递2个参数,2个以上的参数,都放到c里了,如果只有两个参数,那么c就是一个empty tuple。

func(*args) 传入的参数为以元组形式存在args中

def f(*args):
    print(args)
    print(type(args))

f(1,2,3)
f(*[4,5,6]) # 这个方式可以直接将一个列表的所有元素当作不定参数

结果:

(1, 2, 3)
<class tuple>
(4, 5, 6)
<class tuple>

func( **kwargs)传入的参数为以字典形式存在args中

def f(**args):
    print(args)
    print(type(args))

f(a=1,b=2,c=3)

f(**{d:4,e:5,f:6}) # 这个方式可以直接传入将一个字典的所有键值当作关键字参数

结果:

{a: 1, b: 2, c: 3}
<class dict>
{d: 4, e: 5, f: 6}
<class dict>

func(*args, **kwargs)

传入的顺序必须和定义顺序相同,这里是先不定参数列表,再是关键字参数字典,如:

技术分享图片

技术分享图片

带**的参数:

如果一个函数定义中的最后一个形参有 ** (双星号)前缀,所有正常形参之外的其他的关键字参数都将被放置在一个字典中传递给函数,比如:

def funcF(a, **b):
  print(a)
  for x in b:
    print(x + ": " + str(b[x]))

funcF(100, c=你好, b=200)

结果:

100
c: 你好
b: 200

可以看到,b是一个dict对象实例,它接受了关键字参数b和c。

有关*和**的最本质的意义:

在python中的函数,我们要注意两个特点,一个就关键字参数,一个就是任意参数。任意参数的本质意义是让函数能够接受任意多个参数,它的本质意义是用*args表示一个集合,等到这个参数赋值的时候,它会尽可能的接收它能接受的参数,形成一个集合。

也就是说,实际上,假设函数的形参还是与实参的个数是对应的,而*args的引入,就代表*args,表示有0到任意多个形参。同理**args(他是一个字典集合)。

 





以上是关于Python学习 Day7 Python3 函数的主要内容,如果未能解决你的问题,请参考以下文章

Python学习笔记day7

Python学习之路——Day7(面向对象)

python 学习 [day7]面向对象

python3 _笨方法学Python_日记_DAY7

python学习day7

python基础学习日志day7-类的反射