自定义函数

1.1 使用函数

在Python中,函数必须先声明,然后才能调用它,使用函数时,只要按照函数定义的形式,向函数传递必需的参数,就可以调用函数完成相应的功能或者获得函数返回的处理结果。

如果函数有返回值,那么需要在函数中使用return语句返回计算结果,声明函数的一般形式如下。

  

1.1.1 声明函数并调用

def <函数名 > (参数列表):
   <函数语句>
   return <返回值>
   
其中参数列表和返回值不是必须的,return后也可以不跟返回值,甚至连return也没有。对于return后没有返回值的和没有return语句的函数都会返回None值。
有些函数可能既不需要传递参数,也没有返回值。


def tpl_sum( T ):
     result = 0
     for i in T:
        result += i
     return result



1.2深入函数

1.2.1默认值参数

声明一个参数具有默认值的函数形式如下。

  def <函数名> (参数=默认值):
   <语句>

声明了一个带默认值参数的函数,代码如下:


def hello (name='Python'):
     print ('你好,%s!' % name)
  print ('无参数调用时的输出:')
  hello()
  print ('有参数("Jonson")调用时的输出:')
  hello('Jonson')

1.2.2参数传递

调用函数提供参数时,按顺序传递的参数要位于关键字参数之前,而且不能有重复的情况。

1.2.3可变数量的参数传递

在自定义函数时,如果参数名前加上一个星号“*”,则表示该参数就是一个可变长参数。在调用该函数时,如果依次序将所有的其他变量都赋予值之后,剩下的参数将会收集在一个元组中,元组的名称就是前面带星号的参数名。


def change_para_num (*tp1):
     print (type (tp1))             #输出tp1变量的类型
     print (tp1)

  change_para_num (1)
  change_para_num (1,2,3)

当自定义函数时,参数中含有前面所介绍的三种类型的参数,则一般来说带星号的参数应放在最后。当带星号的参数放在最前面时,仍然可以正常工作,但调用时后面的参数必须以关键字参数方式提供,否则因其后的位置参数无法获取值而引发错误。


def change_para_num(*tpl,a,b=0,,**dict):
     print('tp1:',tp1)
     print("dict",dict)
     print('a:',a)
     print ('b:',b)

  change_para_num (1,2,3,a=5,c=1,d=2,e=3) #c d e 会以字典的形式储存
  change_para_num(1,2,3)             #该调用会出错,a变量没有默认值,也不能获取值

如果要收集不定数量的关键字参数可以在自定义函数时的参数前加两颗星即**valuename,可以以字典的方式被收集到变量valuename之中。


def cube (name, **nature):
        all_nature = {'x':1,
                      'y':1,
                      'z':1,
                      'color':'white',
                      'weight':1}
        all_nature.update (nature)
        print (name,"立方体的属性:")
        print ('体积:',all_nature ['x']*all_nature ['y']*all_nature ['z'])
        print ('颜色:',all_nature ['color'])
        print ('重量:',all_nature ['weight'])

cube ('first')                                    #只给出必要参数的调用
cube ('second',y=3, color='red')                  #提供部分可选参数
cube ('third', z=2, color='green', weight=10)     #提供部分可选参数

1.2.4拆解序列的函数调用

前面使用函数调用时提供的参数都是位置参数关键字参数,实际上调用函数时还可以把元组和字典进行拆解调用。

  • 拆解元组提供位置参数;
  • 拆解字典提供关键字参数。

调用时使用拆解元组的方法是在调用时提供的参数前加一个*号;要拆解字典必须在提供的调用参数前加两个*号。


def mysum (a,b):
     return a+b

  print ('拆解元组调用:')
  print (mysum(* (3,4)))              #调用时拆解元组作为位置参数
  print ('拆解字典调用:')
  print (mysum(**{'a':3, 'b':4})      #调用时拆解字典作为关键字参数

1.2.5函数调用时参数的传递方法

Python中的元素有可变和不可变之分,如整数、浮点数、字符串、元组等都属于不可变的;而列表和字典都属于可变的。

列表和字典的可变也是很好理解的,即它们可以增减元素、修改元素的值。那么整数、浮点数、字符串等为什么是不可变的呢?
“=”号的作用是将对象引用与内存中某对象进行绑定,既然整数是不可变的,那么怎么改变一个指向整数的变量的值的呢?答案是直接在内存中创建一个新的整数值,然后将变量引用与其绑定,这虽然本质上的其他高级语言不同,但在使用上是看不出什么差别的,但若将其提供给函数作为参数,则效果不同。

在函数调用时,若提供的是不可变参数,那么在函数内部对其修改时,在函数外部其值是不变的;若提供是可变参数,则在函数内部对它修改时,在函数外部其值也会改变的。


def change (aint, alst):              #定义函数
        aint = 0                      #修改 aint 值
        alst[0]=0                     #修改alst第1个值为0
        alst.append (4)               #在 alst 中添加一个元素4
        print ('函数中aint:', aint)    #输出函数中的aint的值
        print ('函数中alst:', alst)    #输出函数中的alst的值

aint = 3
alst = [1,2,3]
print ('调用前aint:', aint)
print ('调用前 alst:', alst)
change(aint, alst)
print ('调用后aint:', aint)      #调用后值和调用前值相同
print ('调用后alst:', alst)      #调用后值和调用前值不同





 def myfun (lst= []):     #定义有一个默认值为空列表的参数
    lst.append('abc')
    print (lst)
#此后三次调用自定义函数
myfun()
myfun()
myfun()
#每次调用函数按默认值的理解,应该每次传入空列表,列表中只有一个元素'abc'
#在该函数的域上lst是已经存在的,在一个线程内多次执行会保留上一次执行的值。





def myfun (lst=None):       #定义有一个默认值为空列表的参数
        lst = [] if lst is None else lst
        lst.append('abc')
        print (lst)

myfun()
myfun()
myfun()
#增加一条推导语句,将lst置空,就可以达到想要的效果。

1.3变量的作用域

  • 内置作用域:Python预先定义的;
  • 全局作用域:所编写的整个程序;
  • 局部作用域:某个函数内部范围。

每次执行函数,都会创建一个新的命名空间,这个新的命名空间就是局部作用域,同一函数不同时间运行,其作用域是独立的,不同的函数也可以具有相同的参数名,其作用域也是独立的。
在函数内已经声明的变量名,在函数以外依然可以使用。并且在程序运行的过程中,其值并不相互影响。


def myfun():
        a = 0                   #函数内声明并初始化变量a为整数,局部作用域
        a += 3                  #修改a的值
        print ('函数内a:', a)    #输出函数内a的值

a = 'external'             #全局作用域内a声明并初始化

print ('全局作用域a:', a)
myfun()                    #调用函数myfun()
print('全局作用域a:', a)

#总结:函数内部声明的a和外部声明的a在各自的域上互不干扰!





#那么如何在函数内使用全局作用域的变量呢?
    def myfun():
        global a             #增加此语句
        a = 0
        a += 3
        print ('函数内a:', a)

a = 'external'
print ('全局作用域a:',a)
myfun()
print ('全局作用域a:', a)



在局部作用域内可以引用全局作用域内的变量,但不可以修改它。

比如以下代码是没有错误的:

 

 a = 3 #定义全局变量
  def myprint(): #声明函数myprint()
   print (a) #引用全局变量

运行函数myprint()时,会输出全局变量a的值3。但是若将其改为则会引发错误:

 

 a = 3 #定义全局变量
  def myprint(): #声明函数myprint()
   print (a) #引用全局变量
   a = 5

以上代码引发的错误是局部变量在分配前不能引用,原因是与Python中的变量查找有关,在此外代码中函数内声明了a变量并初始化,所以a被判为局部变量,但却之前在print(a)中引用了它。

Python中的变量查找:

clipboard.png

1.4使用匿名函数(lambda)


语法形式如下:
lambda params:expr

其中params相当于声明函数时的参数列表中用逗号分隔的参数,expr是函数要返回值的表达式,而表达式中不能包含其他语句,也可以返回元组(要用括号),还允许在表达式中调用其他函数。

lambda的示例代码:


import math
s = lambda x1, y1, x2, y2:math. sqrt( (x1-x2) **2+(y1-y2) **2)
s(1,1,0,0)
#结果:1.4142135623730951

代码的第二行定义了一个求两坐标点距离的匿名函数,并用s引用,之后调用它来求(1,1)与(0,0)坐标点的距离,结果为1.414。

lambda一般用来定义以下类型的函数:

  • 简单匿名函数 写起来快速而简单,省代码;
  • 不复用的函数 在有些时候需要一个抽象简单的功能,又不想单独定义一个函数;
  • 为了代码清晰 有些地方使用它,代码更清晰易懂。
  • 比如在某个函数中需要一个重复使用的表达式,就可以使用lambda来定义一个匿名函数,多次调用时,就可以少写代码,但条理清晰。

1.5Python常用内建函数

1.6定义和使用类

1.6.1 定义类

1.6.2 使用类

1.7类的属性和方法

来源:https://segmentfault.com/a/1190000017834627

原文地址:https://www.cnblogs.com/lalalagq/p/10250731.html