前面介绍了如何使用函数,这一节我们就来学习怎么创建自己的函数!

自定义函数

创建函数非常简单,它使用关键字 “def”,下面的代码创建了一个带有一个参数的函数,并使用不同的参数调用

def hello(name):
print('hello', name) hello('feather') # 调用函数,传入参数 'feather'
hello('csdn') # 调用函数,传入参数 'csdn'

运行程序可以得到下面输出:

hello feather
hello csdn

可以看到,传入的参数被赋值给变量name,然后执行函数内的代码块,对!这也是一种代码块,注意后面的冒号

函数并非一定要有参数,我们完全可以定义一个不带参数的函数,比如这个

def hello():
print('hello world!')

像获取输入的函数input,返回用户的输入,我们也可以在函数中使用return语句来返回数据,下面是一个计算斐波那契数列第n项的函数

def fibs(num):
if num == 1:
return 0
elif num == 2:
return 1
elif num > 2:
previous = 0 # 前一项
current = 1 # 当前项
for i in range(num-2):
temp = current
current = previous + current # 当前项等于前两项和
previous = temp
return current
else:
# num < 1
return None num = int(input('计算第几项:'))
print(fibs(num))

简单说下斐波那契数列,除了第一和第二个数,后面的数等于前两个数相加,这样的一组数可以叫做斐波那契数列。

就算不懂斐波那契数列也没关系,只需要知道当函数内的代码执行到return语句时,马上结束函数,并把return后面的值(如果有)返回给调用者,上面把返回值马上又做为参数去调用print函数输出了。

函数的末尾无论是否有return,都会返回到调用处,其实相当于函数的末尾有一个隐含的没有返回值的return语句(前面提到过,所谓的“没有返回值”,其实返回了一个None,None是“空”的意思,这很好理解)

默认情况下,参数值和参数名称是按函数中定义的顺序匹配起来的。

下面总结函数的定义的基本格式:

def 函数名(参数1,参数2,参数3):
函数体

参数可以改变吗?

看看下面的代码,有没有一点出乎意料?

>>> def change(n):
... n = 'abc'
...
>>> name = 'feather'
>>> change(name)
>>> name
'feather'
>>>

可以看到,函数内的操作并没有改变函数外的变量,实际上,函数的调用类似于下面代码

>>> name = 'feather'
>>> n = name # 相当于传递参数
>>> n = 'abc' # 函数内部的代码
>>> name
'feather'
>>>

显然,变量n和变量name是完全不同的变量,变量n的改变并不影响到变量name,就算是定义函数时,函数名后的变量名和name一样,此name也并非彼name,如下:

>>> def change(name):
... name = 'abc'
...
>>> name = 'feather'
>>> change(name)
>>> name
'feather'
>>>

通常来说,函数名后面的变量叫做形参,而调用函数时提供的值叫做实参(或者叫做参数),形参是实参的一份拷贝。

既然形参是实参的一份拷贝,那么形参的改变不影响实参咯

这么理解的同学要注意下面这段代码:

>>> lst =[1, 2, 3]
>>> def change(a):
... a[0] = 100
...
>>> change(lst)
>>> lst
[100, 2, 3]
>>>

嗯?不是说“形参是实参的一份拷贝”吗?

其实,上面传入了一个列表类型的参数,形参a拷贝的是实参lst这个变量本身,a[0]=100是通过变量a改变列表里的元素,而不是改变a这个形参本身,而像a=123a+=1这种对变量操作的才叫做改变a参数,可以对比下面的代码来理解

>>> lst =[1, 2, 3]
>>> def change(a):
... a = 123
...
>>> change(lst)
>>> lst
[1, 2, 3]
>>>

作用域

变量都有一定的使用范围,这个范围称为作用域,在执行赋值语句x=1后,名字x就对应到数值1,变量引用值,这其实就是个不可见的字典,这个字典叫做命名空间也是我们的作用域,python内置的vars函数可以返回当前作用域的字典

>>> def func():
... x = 1
... y = 2
... print(vars())
...
>>> vars()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'func': <function func at 0x7f7e191e70d0>}
>>> func()
{'x': 1, 'y': 2}
>>>

可以看到,函数内外获得的字典不一样,也就是说函数内外的作用域不一样,最外面的作用域称为全局作用域,每个函数调用都会创建一个新的作用域。

看下面代码

>>> def func():
... x=123
...
>>> x = 1
>>> func()
>>> x
1
>>>

这里的func函数里面为x变量赋值,但并为影响外面的x变量,不难想到,当调用func函数时,创建了一个新的命名空间,语句x=123只是在这个新的命名空间中起作用,所以它不影响外部的x。

函数内的变量(包括定义的参数)称为局部变量,最外层的变量称为全局变量,如果函数内想访问全局变量,如果只是想读取全局变量的值,一般来说是没什么问题的:

>>> x = 1
>>> def func():
... print(x)
...
>>> func()
1
>>>

但是想要在函数里存在和全局变量同名的局部变量就不能像这样访问了,全局变量会被同名的局部变量屏蔽,直接访问到的是局部变量,如果需要的话,可以使用globals函数获取全局变量,这个函数返回一个全局变量的字典,可以直接操作这个字典进行访问全局变量,比如下面代码

>>> x = 123
>>> def func():
... x = 1
... print('局部变量x', x)
... print('全局变量x', globals()['x'])
...
>>> func()
局部变量x 1
全局变量x 123
>>>

在函数内部将值赋给一个变量,这个变量就会自动成为局部变量,那么怎么才能在函数里给全局变量重新赋值呢?

这个时候可以是用关键字global声明变量为全局变量:

>>> x = 1
>>> def func():
... global x
... x = 2
...
>>> func()
>>> x
2
>>>

关键字参数和默认参数

在上面,我们使用的参数都叫做 “位置参数”,函数定义时参数的位置决定了调用时参数的位置,有时候,调用函数弄乱了参数的位置可不是间好事,下面介绍的 “关键字参数”可以忽略这种位置的问题。

关键字参数其实是对于函数调用来说的,而不是函数的定义,怎么说呢,还是看看下面的代码吧

>>> def hello(greeting, name):
... print(greeting, name) # greeting是问候语,name是名字
...
>>> hello('hello', 'feather') # 参数位置一一对应
hello feather
>>> hello(name='feather',greeting='hello') # 关键字参数
hello feather
>>>

虽然第二种调用传递的参数的位置不同与函数定义时的位置,但仍能正常的工作,像第二种这样,使用参数名提供的参数叫做 “关键字参数”,它可以明确参数的作用,就算弄乱了参数的位置也无妨。


默认参数可以在函数的定义时给参数提供默认值

>>> def hello(greeting='hello',name='feather'):
... print(greeting, name)
...
>>> hello() # 不提供参数,使用默认值
hello feather
>>> hello('bye') # 提供第一个参数
bye feather
>>> hello('bye', 'Lee') # 提供两个参数
bye Lee
>>> hello(name='Lee') # 只提供name参数
hello Lee
>>>

提示:关键字参数和默认参数其实就是分别针对函数的调用和函数的定义同类事物两种说法(至少本人这么理解 ( ̄_, ̄ )),它们可以和位置参数联合使用,不过要注意的是,对于关键字参数,也就是调用的时候,位置参数应该在关键字参数的前面,不然python解释器会不知道哪个是哪个,不信你可以这样调用上面的函数:hello(name='feather', hello);而对于默认参数,也就是定义的时候,和关键字参数一样,位置参数要放在默认参数的前面,同理︿( ̄︶ ̄)︿

下面给个例子自己感受\( ̄ˇ ̄)>:

>>> def hello(name, greeting='hello', end='bye~'):
... print(greeting, name)
... print("I'm fine")
... print(end)
...
>>> hello('feather')
hello feather
I'm fine
bye~
>>> hello('feather', 'nice to meet you,')
nice to meet you, feather
I'm fine
bye~
>>> hello('feather', end='bye bye!')
hello feather
I'm fine
bye bye!
>>>> hello() # 这句报错,因为name没有默认值
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: hello() missing 1 required positional argument: 'name'
>>>

提示 :上面输出的是英语常用社交语句,赶紧记下!!! (❍ᴥ❍ʋ)


不写不知道,一写吓一跳,发现函数的内容挺多的,还有部分内容要留到下一篇文章再讲了,先消化吧 。

ヾ( ̄▽ ̄)Bye~Bye~

python教程(三)·自定义函数的更多相关文章

  1. python的三个函数(eval、exec、complie)和python版RMI

    一.python的三个函数: 1.eval函数: 之前已经讲过了这个函数,该函数也类似于php的eval,例如下边这个例子 eval("os.system('id')") 但是有个 ...

  2. python学习之--自定义函数:

    Python之--自定义函数: 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. 以下自定义 ...

  3. 新手Python第三天(函数)

    Python 函数的创建 def func2(): print('haha') # 函数的返回值 # 函数的返回值,没有定义返回None, # 有一个返回值返回这个object(可以返回一个函数对象) ...

  4. SQL强化(三) 自定义函数

    ---恢复内容开始--- Oracle中我们可以通过自定义函数去做一些逻辑判断,这样可以减少查询语句,提高开发效率 create  -- 创建自定义函数 or replace -- 有同名函数就替换, ...

  5. Python第三周 函数详解

    def 函数名(): """注释说明"""" 执行逻辑体 return 返回值 定义不带参数的函数 带参数的函数 默认参数 这个是 ...

  6. 简明python教程三-----函数

    函数通过def关键字定义.def关键字后跟一个函数的表标识符名称,然后跟一对圆括号. 圆括号之中可以包括一些变量名,该行以冒号结尾.接下来是一块语句,它们是函数体. def sayHello(): p ...

  7. Python 基础三 文件 函数

    今天回顾一下之前学的文件操作相关知识点,对于文件的操作,主要有一下几部分构成: 一.文件的基础知识 1.文件操作的基本流程 文件操作其实可以分成三大部分: 1.打开文件,获取文件句柄并赋予一个变量 2 ...

  8. 人生苦短我用Python 第三周 函数周

    函数的定义: 1,def 函数名(参数1,参数2......): "注释:函数的作用和参数,增加可读性", 2,函数体 3,返回值 最简单的函数: def func(): prin ...

  9. python怎么导入自定义函数

    python 编程中经常需要调用自己定义的函数,在大型程序中自定义的函数一般会和main函数分开,这么主要讲下在不同文件下定义的函数怎么调用: 首先在有文件夹test_python文件夹下有main. ...

  10. python第三课--函数

    函数的作用 编程大师Martin Fowler先生曾经说过:“代码有很多种坏味道,重复是最坏的一种!”,要写出高质量的代码首先要解决的就是重复代码的问题.例如3次求阶乘: m = int(input( ...

随机推荐

  1. Oracle案例08——xx.xx.xx.xx,表空间 SYSAUX 使用率>95%%

    本实例主要针对Oracle表空间饱满问题处理方法做个步骤分享.  一.告警信息 收到zabbix告警信息,表空间 SYSAUX 使用率>95%%,系统表空间sysaux使用率超过了95%. 二. ...

  2. 译文 [ROM][多国语言][2015.06.11] Lenovo S750 (MTK6589) - andrea_d86-lenovos750-4.2.2

    ************************************************** andrea_d86-lenovos750-4.2.2-150530 ************** ...

  3. 定义类/实例(Class)

    # -*- coding: UTF-8 -*- class pp(): '''Description'''   def __init__(self,name): #初始化函数     self.nam ...

  4. Python初学者第十六天 文件处理操作练习

    16day 练习:模拟登陆 1.用户输入账号密码进行登陆: 2.用户信息保存在文件内: 3.用户密码输入错误三次后,锁定用户,下次登陆,检测到这个用户再也登陆不了 #获取用户名及密码f_user = ...

  5. [COGS 0107][NOIP 2003] 传染病控制

    107. [NOIP2003] 传染病控制 ★★★   输入文件:epidemic.in   输出文件:epidemic.out   简单对比时间限制:1 s   内存限制:128 MB [问题背景] ...

  6. Vue中$refs的用法

    说明:vm.$refs 一个对象,持有已注册过 ref 的所有子组件(或HTML元素) 使用:在 HTML元素 中,添加ref属性,然后在JS中通过vm.$refs.属性来获取 注意:如果获取的是一个 ...

  7. jquery cookie插件

    jquery-cookie下载地址:http://www.bootcdn.cn/jquery-cookie/ 使用方法: 1.引入jQuery.Cookie.js插件. <script src= ...

  8. Codeforces Round #441 (Div. 2)【A、B、C、D】

    Codeforces Round #441 (Div. 2) codeforces 876 A. Trip For Meal(水题) 题意:R.O.E三点互连,给出任意两点间距离,你在R点,每次只能去 ...

  9. svn .externals 属性

    问:如下自定下载关联模块呢? 答:第一步: 编辑svn.externals文本,如下所示 dir/moduel_name URL/module dir/moduel_name URL/module 第 ...

  10. ./redis-trib.rb 报错:/usr/local/rvm/gems/ruby-2.4.2/gems/redis-4.0.1/lib/redis/client.rb:119:in `call': ERR Slot 0 is already busy (Redis::CommandError)

    错误提示是 slot插槽被占用了(这是 搭建集群前时,以前redis的旧数据和配置信息没有清理干净.) 解决方案是 用redis-cli 登录到每个节点执行  flushall  和 cluster ...