java程序员的python之路(函数)

前篇

前面的两片文章,简单的介绍了,python的数据类型,包括数字,字符串、列表、元组、集合和字典,以及判断if else和循环 while,for的使用。并且我们已经可以是用这些功能来编写一些小程序了,但是如果只有这些功能,编写一些较大的程序会非常吃力。在写程序的过程中我们难免会碰到一些公共的算法和逻辑,看下面这个小例子:

#假设我们有这么一个需求,计算两个数10和20的平方和。
a = 10
b = 20
result = a ** 2 + b ** 2
print(result)

结果为:500

现在我们要增加一个需求,计算另外两个数的平方和,那么我们只能这么办:

a = 10
b = 30
result = a ** 2 + b ** 2
print(result)

结果为:1000

比较以上上面的两段程序,我们发现其实两段程序基本上是相同的,我只不过又复制了一遍,换了两个值而已。难道每换两个值就得重写一遍程序?当然,如果是这样,程序员就就骂街了。所以函数便应运而生了。简单的说函数就是一组算法,封装了固定的逻辑。我们把常用的算法整合成一个函数,在用到这个算法的时候我们不用重新写重复的代码,这就提高了代码的利用率。比如print就是一个函数,实现了打印输出的逻辑,我们每次打印,只是调用print函数而已。

函数的结构

我们可以定义自己的函数,函数的结构如下:

def functionName(arg1,arg2,....):
    函数体
    return result
  • def:是定义函数的关键字,电脑看到这个关键字,就知道后面的内容是一个函数。
  • functionName:是我们定义函数的名字
  • 括号中的是函数的参数,参数可以为空,我们叫这里的参数为形参
  • 函数体:是函数的逻辑算法
  • return:是函数的返回值,函数默认返回None。
    定义了函数是为了使用的。怎么使用函数呢,直接使用函数名和参数(这里的参数我们叫做实参),像下面这样,我们称作函数的调用:
functionName(arg1,arg2,....)

第一个函数

现在我们写一个计算两个数平方和的函数,如下:

#定义函数
def squareSum(num1,num2):
    print(num1,num2)
    return num1 ** 2 + num2 ** 2

#函数的调用
result = squareSum(10,20)
print(result)
result = squareSum(10,30)
print(result)

结果为:
10 20
500
10 30
1000

我们使用def定义了一个函数名字叫squareSum,有两个参数num1和num2,函数体输出两个参数,并返回两个值的平方和。之后我们就可以随意调用此方法,传给函数适当的参数值,返回值就会赋给result引用。

传递参数

参数传递有两种,一种的值传递,一种是引用传递。值传递的原理是赋值当前参数的副本,然后传递给函数,引用传递是传递引用指向的内存地址,需要先讨论一下python中的可变对象和不可变对象。字符串,元组,和数字都是不可变对象,列表,集合和字典都是可变对象。
python中的参数传递,我们可以简单的认为就是值传递(这和java是一样的),如果是传递的是不可变对象,那么传递的就是对象值的副本,在函数中修改了此参数值并不会影响到原来的值。如果传递的是可变对象,那么传递的就是引用的副本,原来的引用的副本引用是指向同一个内存地址的,所以说函数内修改了可变对象的内容,会影响到原来引用的值。看下面的例子:

num = 1
def update(num):
    num = 2
    print(num)

update(num)
print(num)
结果为:
2
1

函数中的num和函数外的num并不是一个num引用,只是一个副本,所以函数中修改num的值,并不会影响函数。
再看下面这个例子:

list = [1,2,3,4]
def updateList(list):
    list = [5,6,7,8]
    print(list)

updateList(list)    
print(list)    
结果为:
[5, 6, 7, 8]
[1, 2, 3, 4]

这个例子和上面的例子道理是一样的,改变的只是副本引用的值,并不影响原来的引用。
继续看下面的例子:

list = [1,2,3,4]
def updateList(list):
    list.append(5)
    print(list)

updateList(list)    
print(list)   
结果为:
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]

从输出结果我们看到,函数里的修改影响到了原来的引用。因为这里修改的并不是引用,而是修改引用指向的对象的内容。原来的引用和副本引用都是指向同一个对象,所以肯定会影响到原来的引用。

参数

python的函数有这几种类型,固定参数,关键字参数,默认参数,变长参数,固定参数是指,必须按照参数定义的顺序来传递参数,且参数个数不能少,比如:

def myFunction(name,age,sex):
    print(name,age,sex)
myFunction("a",20,1)

关键字参数,是指在调用函数的时候用关键字指定参数的值,这样就不必完全按照参数的顺序来传递参数,但是参数的个数还是不能少,比如:

def myFunction(name,age,sex):
    print(name,age,sex)
myFunction(sex = 1, age=20, name="a")    

默认参数,是指在定义函数的时候,给参数一个默认值,这样在调用函数的时候,这个参数可以省略而使用默认值。比如:

def myFunction1(name,age,sex=1):
    print(name,age,sex)
myFunction1("a",20)

需要注意的是,默认参数使用时需要注意别产生歧义了。看下面这个函数

def myFunction2(name,age=1,sex):
    print(name,age,sex)

这个函数执行时会报错,因为这个函数在调用时存在歧义,如果你这么调用myFunction2(“a”,1),就会让计算机很迷茫,你是少传了一个参数sex呢?还是要把1传递给sex?所以非默认参数,不能出现在默认参数之后。
变长参数是指这个参数可以接受多个值,如下:

def myFunction3(name,age,sex,*str):
    print(name,age,sex)
    for s in str:
        print(s)
myFunction3("a",20,1,"a","b","c") 

匿名函数

python 使用 lambda 来创建匿名函数。所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数,结构如下:

lambda arg1,arg2,....:expression

例子如下:

sum = lambda num1,num2: num1 + num2
print(sum(1,2))
输出结果:
3

变量作用域

python变量的作用域有4中

  • L:局部作用域
  • E:闭包函数外的函数中
  • G:全局作用域
  • B:内建作用域
x = int(2.9)  # 内建作用域
g_count = 0  # 全局作用域
def outer():
    o_count = 1  # 闭包函数外的函数中
    def inner():
        i_count = 2  # 局部作用域

L小于E小于G小于B。python中会按照这个顺序来寻找变量。python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这这些语句内定义的变量,外部也可以访问,如下代码:

if 1 == 1:
    msg = "hello"
print(msg)   
输出结果:
hello

因为python没有块级的作用域,msg虽然是在if块中定义的变量,但是他依旧是个全局的变量。
再看下面这个例子:

def function1():
    name = "name"
print(name) 

运行报错:

Traceback (most recent call last):
  File "E:\workspace-python\firstpython\src\first.py", line 4, in <module>
    print(name)    
NameError: name 'name' is not defined

是因为name是一个局部变量,不能再全局中找到。
再看一个例子:

name = "name"
def function2():
    print(name)
结果:
name

函数中先在局部找name变量,没有找到,然后再继续找全局作用域,找到name变量。
继续看下面的例子:

name = "name"
def function3():
    name = "aaa"
    print(name)

function3()    
print(name)
结果:
aaa
name

函数中的name是一个局部变量,函数外的name是一个全局变量,两个名字虽然相同,单不是同一个变量,不能混淆,如果在函数中要改变全局变量的值,需要使用global,如下所示:

name = "name"
def function4():
    global name
    name = "aaa"
    print(name)
function4()   
print(name)

输出结果:

aaa
aaa

通过global指定后,函数中对name的修改,就是修改的全局变量name.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值