2018.6.11 Python第六课

今天主要讲了python函数


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

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


1.定义一个函数

def test(形参):  ##函数名,形参可任意
    pass    ##函数体
    return  ##返回值,默认为none

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


2.可变对象与不可变对象

在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。在函数中对不可变参数重新赋值后,函数的输出结果则会输出新赋值,而对可变参数中的某个元素重新赋值后,可变参数本身没有动,只是将内部元素进行了修改。


python传不可变对象实例

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 指向它。


python传可变对象实例

def changeme( mylist ):
       #修改传入的列表
   mylist.append([1,2,3,4])
   print("函数内取值: ", mylist)
   return mylist
     #调用changeme函数
mylist = [10,20,30]
changeme( mylist )
print("函数外取值: ", mylist)

以上实例输出结果为:
函数内取值: [10, 20, 30, [1, 2, 3, 4]]
函数外取值: [10, 20, 30, [1, 2, 3, 4]]

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


函数的参数主要分为五个类型:必需参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用,除了可变参数无法和命名关键字参数混合。但是请注意,参数定义的顺序必须是:必需参数、默认参数、可变参数/命名关键字参数和关键字参数。
3.必备参数

必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。
调用printme()函数,你必须传入一个参数,不然会出现语法错误:


#这里的str就是必备参数

def printme( str ):
   #"打印任何传入的字符串"
   print(str)
   return

#调用printme函数的时候,括号内如果没有传入参数会报错

printme()    

4.默认参数

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

def printinfo( name, age = 35 ):
   #"打印任何传入的字符串"
   print("Name: ", name)
   print("Age ", age)
   return

#调用printinfo函数

printinfo(age=50, name="miki")
printinfo(name="miki")

以上实例输出结果为:
`Name: miki
Age 50
Name: miki
设置默认参数时,一定要注意两点:
第一:必选参数在前,默认参数在后,否则python解释器会报错。
第二:默认参数一定要指向不变对象!指向不变对象!指向不变对象!
(注意:python中的字符串,数字,元组都可以看做对象。)
为什么要设计str、None这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象


5.不定长参数(也就是可变参数)

定义:可变参数就是传入的参数个数是可变的,可以是0个,1个,2个,……很多个。
作用:就是可以一次给函数传很多的参数
特征:*args

def power(*args):
    result=0
    for n in args:
        result=result+n*n
    return result

# 调用函数
tupleArray=(1,2,3)
# *tupleArray这种方式很常见,很重要
print(power(*tupleArray))

listArray=[1,2,3]
# *listArray这种方式很常见,很重要
# *listArray表示把listArray这个list中所有元素作为可变参数传进去
print(power(*listArray))

以上实例输出结果为:
14
14


6.关键字参数

定义:可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。
而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。在调用函数时,可以只传入必选参数:
作用:扩展函数的功能
特征:**kw
代码如下:

def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)

#案例一:

person('Michael', 30)
#输出结果为  name: Michael age: 30 other: {}

#案例二:

#定义一个字典数据
dictArray = {'city': 'Beijing', 'job': 'Engineer'}
#调用函数
person('Jack', 24, **dictArray )
#输出结果
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}

解释说明:
**dictArray表示把dictArray这个dict的所有key-value用关键字参数传入到函数的**kw参数,kw将获得一个dict。注意kw获得的dict是dictArray的一份拷贝,对kw的改动不会影响到函数外的dictArray。


7.命名关键字参数

对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些,就需要在函数内部通过kw检查。

仍以person()函数为例,我们希望检查是否有city和job参数:

def person(name, age, **kw):
    if 'city' in kw:
        # 有city参数
        pass
    if 'job' in kw:
        # 有job参数
        pass
    print('name:', name, 'age:', age, 'other:', kw)

但是调用者仍可以传入不受限制的关键字参数:

person('Jack', 24, city='Beijing', addr='Chaoyang', zipcode=123456)
如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。这种方式定义的函数如下:

def person(name, age, *, city, job):
    print(name, age, city, job)

和关键字参数*kw不同,命名关键字参数需要一个特殊分隔符,*后面的参数被视为命名关键字参数。

调用方式如下:

 person('Jack', 24, city='Beijing', job='Engineer')

其输出结果为Jack 24 Beijing Engineer

如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:

def person(name, age, *args, city, job):
    print(name, age, args, city, job)

命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错:

person('Jack', 24, 'Beijing', 'Engineer')

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: person() takes 2 positional arguments but 4 were given

由于调用时缺少参数名city和job,Python解释器把这4个参数均视为位置参数,但person()函数仅接受2个位置参数。

命名关键字参数可以有缺省值,从而简化调用:

def person(name, age, *, city='Beijing', job):
    print(name, age, city, job)

由于命名关键字参数city具有默认值,调用时,可不传入city参数:

 person('Jack', 24, job='Engineer')

以上输出结果为Jack 24 Beijing Engineer
使用命名关键字参数时,要特别注意,如果没有可变参数,就必须加一个*作为特殊分隔符。如果缺少*,Python解释器将无法识别位置参数和命名关键字参数:

def person(name, age, city, job):
    # 缺少 *,city和job被视为位置参数
    pass

8.由函数引申出的变量作用域

一个程序的所有的变量并不是在哪个位置都可以访问的。访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序你可以访问哪个特定的变量名称。两种最基本的变量作用域如下:
全局变量
局部变量


全局变量和局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。如下实例:

total = 0; # 这是一个全局变量
# 可写函数说明
def sum( arg1, arg2 ):
   #返回2个参数的和."
   total = arg1 + arg2; # total在这里是局部变量.
   print ("函数内是局部变量 : ", total)
   return total;

#调用sum函数
sum( 10, 20 );
print ("函数外是全局变量 : ", total )

以上实例输出结果为:
函数内是局部变量 : 30
函数外是全局变量 : 0


全局变量想作用于函数内,需加 global

globvar = 0

def set_globvar_to_one():
    global globvar    # 使用 global 声明全局变量
    globvar = 1       #globvar全局变量的那个0在这里已经变成了1

def print_globvar():
    print(globvar)     # 没有使用 global

set_globvar_to_one()
print(globvar)        # 输出 1
print_globvar()       # 输出 1,函数内的 globvar 已经是全局变量

1、global---将变量定义为全局变量。可以通过定义为全局变量,实现在函数内部改变变量值。
2、一个global语句可以同时定义多个变量,如 global x, y, z。

猜你喜欢

转载自blog.csdn.net/weixin_40313627/article/details/80672496