1. 空函数

如果想定义一个什么事也不做的空函数,可以用pass语句:

def nop():
    pass

pass语句什么都不做,那有什么用?实际上pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。

2. 容易混肴的函数使用方式

函数的赋值其实就是将函数名指向函数体。

2.1 函数名其实也是一个变量

例如,

def func():
    return "Python"

print (func())
print (func)
func = 100
print (func)
print (func())

输出结果

Python
<function func at 0x7f4aa8a66f28>
100
Traceback (most recent call last):
  File "test.py", line 27, in <module>
    print (func())
TypeError: 'int' object is not callable

第一次输出是调用函数的输出结果

第二次输出是函数所在的物理存储位置

第三次输出是将函数名(变量)重新绑定一个值后的输出结果

第四次输出是因为“整型不能函数调用”,因为将func绑定100后,func已经成为整型变量,func()是进行的函数调用,所以报错!

2.2 函数的绑定规则

情形1

def func(a):
    return a

b = func(6)
print(b)

输出结果

6

情形2

def func(a):
    return a

b = func
print(b(6))

输出结果

6

情形3(该情况类似情形1)

def func(a=[100,200]):
    return a

x = func()

x.append(1)
print("x:", x)

输出结果

X: [100, 200, 1]

情形4(该情况类似情形2)

def func(a=[100,200]):
    return a

x = func

x().append(1)
print("x:", x())

输出结果

x: [100, 200, 1]

情形5

def func(a=[100,200]):
    return a

x = func

x().append(1)
print("x:", x)

输出结果

x: <function func at 0x7f818e8d5f28>

该输出结果为函数所在的位置

情形6

def func(a=[100,200]):
    return a

x = func

x.append(1)
print("x:", x)

输出结果

Traceback (most recent call last):
  File "test.py", line 24, in <module>
    x.append(1)
AttributeError: 'function' object has no attribute 'append'

错误的原因是:函数“function”对象没有“append”属性

2.3 函数的绑定方式

def func(a=[100,200]):
    return a

x = func()
y = func()

print(func)
print(id(x))
print(id(y))

x.append(1)
print("y:", y)

y.append(2)
print("x:", x)

x.append(3)
print("x:", x)
print("y:", y)

输出结果

<function func at 0x7feed4d4ef28>
140663724970760
140663724970760
y: [100, 200, 1]
x: [100, 200, 1, 2]
x: [100, 200, 1, 2, 3]
y: [100, 200, 1, 2, 3]

我们发现,x和y绑定的函数为一个地址,也即当x绑定值改变时,y值也随之也改变。

但是函数 func 与函数 x 、 y 的地址是不一样的;将140663724970760转成16进制时,得到

>>> hex(140098127414024)
'0x7f6b231e4308'

所以地址是有区别的!

2.4 序列传参(元组传参)

代码片段1

def func(a,b):
    print(a+b)

func(1,2)
func(*(1,2))

输出结果

3
3

形参是与实参不一致时

def func(a,b):
    print(a+b)

func(*(1))

运行结果

Traceback (most recent call last):
  File "test01.py", line 4, in <module>
    func(*(1))
TypeError: func() argument after * must be an iterable, not int

本段代码产生错误的原因是元组形式错误导致的。在*后面必须是可迭代的,而不是整数

执行错误后,没有向下执行。

代码片段2

def func(a,b):
    print(a+b)

func(*(1,))

运行结果

Traceback (most recent call last):
  File "test01.py", line 4, in <module>
    func(*(1,))
TypeError: func() missing 1 required positional argument: 'b'

该段代码运行错误是因为实参少于形参个数

代码片段3

def func(a,b):
    print(a+b)

func(*(1,2,3))

运算结果

Traceback (most recent call last):
  File "test01.py", line 4, in <module>
    func(*(1,2,3))
TypeError: func() takes 2 positional arguments but 3 were given

该段代码运行错误的原因是因为实参多于形参个数

总结:当仅有元组传参时,实参个数必须与实参个数一致

代码片段4

def info(*var):
    print(var)
    for a in var:
        print(a)

info(*(1,2,3))

print("------------")

info(1,2,3)

输出结果

(1, 2, 3)
1
2
3
------------
(1, 2, 3)
1
2
3

2.4 序列传参(列表传参)

def func(a,b):
    print(a+b)

func(*[1,2])

输出结果

3

其实列表传参与元组传参在功能上没有明显区别

2.5 关键字传参

关键字传参只要关键字匹配就可以,顺序可以改变。

def func(a,b):
    print(a+b)
func(b=1,a=2)
func(a=1,b=2)

输出结果

33

当改变一下

def func(a,b):
    print(a+b)

func(a=1,2)

输出结果

  File "test01.py", line 4
    func(a=1,2)
            ^
SyntaxError: positional argument follows keyword argument

语法错误:位置参数在关键字参数后

有位置参数的,位置参数必须写在关键参数前面;换句话说,一旦出现关键字参数,其后不能出现位置参数

def func(a,b):
    print(a+b)

func(1,a=2)

输出结果

Traceback (most recent call last):
  File "test01.py", line 4, in <module>
    func(1,a=2)
TypeError: func() got multiple values for argument 'a'

错误类型:函数的参数a得到了多个值。

很明显,当形参和实参位置赋值完毕后,再按照关键字参数再赋值,最后发现形参a有多个值,而没有报形参b值缺少。可以说明实参向形参传值时不存在形同形参覆盖问题。

2.6 字典传参

代码片段1

def print_str(a, b):
    print(b)
    print(a)

d = {"b":2,"a":1}
print_str(**d)

输出结果

2
1

代码片段2

def print_str(a, b):
    print(b)
    print(a)

print_str("b":1,"a":2)

输出结果

  File "test01.py", line 5
    print_str("b":1,"a":2)
                 ^
SyntaxError: invalid syntax

语法错误,这样写不是字典所要求的输入形式

代码片段3

def print_str(a, b):
    print(b)
    print(a)

print_str({"b":1,"a":2})

输出结果

Traceback (most recent call last):
  File "test01.py", line 5, in <module>
    print_str({"b":1,"a":2})
TypeError: print_str() missing 1 required positional argument: 'b'

因为缺少参数 b  而报错,该段代码中将字典 {"b":1,"a":2} 作为一个参数传给了 a  ;将其进行修改

代码片段4

def print_str(a, b):
    print(a)
    print(b)

print_str({"b":1,"a":2},1)

输出结果

{'b': 1, 'a': 2}
1

不难看出,该段代码中将字典当作一个参数传给形参 a  ,将实参 1  传给形参 b  ,其实,这就是位置传参

其实字典传参的输入形式如代码5所示

代码片段5

def print_str(a, b):
    print(a)
    print(b)

print_str(**{"b":1,"a":2})

输出结果

2
1

代码片段6

def print_str(**dict):
    print(dict)

print_str(**{"b":1,"a":2})

输出结果

{'a': 2, 'b': 1}

代码片段7

def print_str(**dict):
    print(dict)

print_str({"b":1,"a":2})

输出结果

Traceback (most recent call last):
  File "test01.py", line 4, in <module>
    print_str({"b":1,"a":2})
TypeError: print_str() takes 0 positional arguments but 1 was given

函数有0个位置参数,但是实参却有一个别给定

如果按照这个错误提示,当没有任何实参时,应该也不会报错

代码片段8

def print_str(**dict):
    print(dict)
    ")

print_str( )

输出结果

{}
123

代码片段9

def print_str(**dict):
    print(dict)
    ")

print_str("b":1,"a":2)

输出结果

  File "test01.py", line 5
    print_str("b":1,"a":2)
                 ^
SyntaxError: invalid syntax

说明代码述写的时候已经出错

代码片段10

def print_str(**dict):
    print(dict)

print_str(b=1,a=2)

输出结果

{'a': 2, 'b': 1}

代码片段11

def func(**kwargs):

    print(kwargs)

    print("参数个数:", len(kwargs))
    for k,v in kwargs.items():
        print(k, "->", v)

func(x = 10, y = 20, z = 30)

d = {"x":10, "y":20, "z":30}
func(**d)

func(**{"a":30, "b":40, "c":50, "d":60})

func(**{"a":"你好", "b":40, "c":50, "d":60})

输出结果

{'y': 20, 'z': 30, 'x': 10}
参数个数: 3
y -> 20
z -> 30
x -> 10
{'y': 20, 'z': 30, 'x': 10}
参数个数: 3
y -> 20
z -> 30
x -> 10
{'a': 30, 'c': 50, 'b': 40, 'd': 60}
参数个数: 4
a -> 30
c -> 50
b -> 40
d -> 60
{'a': '你好', 'c': 50, 'b': 40, 'd': 60}
参数个数: 4
a -> 你好
c -> 50
b -> 40
d -> 60

3 混合传参

混合传参形式是将位置传参、关键字传参、序列传参(元组传参、列表传参)、字典传参结合使用。

3.1 位置传参+序列传参

序列传参中的元组传参与列表传参没明显区别,本处仅以元组传参为例。

代码片段1

def print_info(arg1, *var):
    print(" 参数1:", arg1)
    print(" 其他参数:")
    print(var)
    for a in var:
        print(a)

print_info(100,)
print("------------")

print_info(100)
print("------------")

输出结果

 参数1: 100
 其他参数:
()
------------
 参数1: 100
 其他参数:
()
------------

当实参满足第一个位置形参后,即使后面的元组参数是空也不报错

代码片段2

def print_info(arg1, *var):
    print(" 参数1:", arg1)
    print(" 其他参数:")
    print(var)
    for a in var:
        print(a)

print_info(100, 1, 3)
print("------------")

print_info(100, *(1, 3))
print("------------")

输出结果

 参数1: 100
 其他参数:
(1, 3)
1
3
------------
 参数1: 100
 其他参数:
(1, 3)
1
3
------------

当前面的实参个数满足位置参数个数后,后面的实参均默认为元组形参中的数值。

注意:以本代码为例,第一个位置参数不限于数字、字符串,也可以是元组或字典,为了更清楚地表达,见代码片段3

代码片段3

def print_info(arg1,arg2,arg3, *var):
    print(" 参数1:", arg1)
    print(" 参数1:", arg2)
    print(" 参数1:", arg3)
    print(" 其他参数:")
    print(var)
    for a in var:
        print(a)

print_info((100,200),300,{"a":400,"b":500},600,700,800,900)

输出结果

 参数1: (100, 200)
 参数1: 300
 参数1: {'b': 500, 'a': 400}
 其他参数:
(600, 700, 800, 900)
600
700
800
900

代码片段4

def print_info(arg1, *var):
    print(" 参数1:", arg1)
    print(" 其他参数:")
    print(var)
    for a in var:
        print(a)

a = (1,2)
b = [1,2]

print_info(100,a,200,300,b)
print("---------------------")
print_info(100,*a,200,300,*b)

输出结果

 参数1: 100
 其他参数:
((1, 2), 200, 300, [1, 2])
(1, 2)
200
300
[1, 2]
---------------------
 参数1: 100
 其他参数:
(1, 2, 200, 300, 1, 2)
1
2
200
300
1
2

注意述写时候的细节

3.2 位置传参+字典传参

def func(a, **kwargs):
   print (" 参数 a 是", a)

   print(kwargs)

   for key in kwargs:
       print(key, kwargs[key])

func(10, y = 100, x = 200, z = 1000)

输出结果

 参数 a 是 10
{'x': 200, 'z': 1000, 'y': 100}
x 200
z 1000
y 100

3.3 位置参数+序列参数+字典参数

函数代码均一样,如下段代码所示;该标题下的其他代码为函数调用代码,函数代码再调用代码中省略。

代码片段1

def print_args(arg1,  *targs, **kwargs):
    print(" arg1 是", arg1)
    print(" targs:")

    for t in targs:
        print (t)

    print(" kwargs:")
    for key in kwargs:
        print(key, kwargs[key]) 

代码片段2

print_args(1)

输出结果

 arg1 是 1
 targs:
 kwargs:

代码片段3

print_args(1, b=")

输出结果

 arg1 是 1
 targs:
 kwargs:
c 3
b 2

代码片段4

print_args(1,2,3,4,b=")

输出结果

 arg1 是 1
 targs:
2
3
4
 kwargs:
b 2
c 3

代码片段5

a = 20
b = 30
t = (20, 100, 200)

print_args(10, b, *t, 4, b = 2, c = 3)
print("-------------------------")
print_args(10, b, *t, 4, **{"b":2, "c": 3})

输出结果

 arg1 是 10
 targs:
30
20
100
200
4
 kwargs:
b 2
c 3
-------------------------
 arg1 是 10
 targs:
30
20
100
200
4
 kwargs:
b 2
c 3

代码片段6

a = 20
b = 30
t = (20, 100, 200)

print_args(10, b, b = 2, c = 3, *t, )

输出结果

 arg1 是 10
 targs:
30
20
100
200
 kwargs:
c 3
b 2

代码片段7

本段代码是将函数的形参顺序进行修改,修改后直接报错

  File "test01.py", line 1
    def print_args(arg1,  **targs, *kwargs):
                                 ^
SyntaxError: invalid syntax

可以发现,形参的顺序是固定不变的。而实参的顺序是可以改变的。

4 特殊的规则

如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收cityjob作为关键字参数。这种方式定义的函数如下:

def student(name, age, *, school, address):
    print('name:', name, 'age:', age, 'school',
          school, 'address', address)

student("zhang", 24, address = "北京海淀", school = "清华")

student("zhang", 24, **{"school": "清华", "address":"北京海淀"})

输出

name: zhang age: 24 school 清华 address 北京海淀name: zhang age: 24 school 清华 address 北京海淀

*后面的参数被视为命名关键字参数。

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

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

以上仅是联系的一部分。

也可以参考廖雪峰的本章节博客https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431752945034eb82ac80a3e64b9bb4929b16eeed1eb9000

5 函数是否可执行属性

#函数名本质是变量

>>> callable(print)
True
>>> callable(print())
False
>>> callable(a)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

>>> b = 1
>>> callable(b)
False
>>>

Python学习笔记009—函数的更多相关文章

  1. Python学习笔记之函数

    这篇文章介绍有关 Python 函数中一些常被大家忽略的知识点,帮助大家更全面的掌握 Python 中函数的使用技巧 1.函数文档 给函数添加注释,可以在 def 语句后面添加独立字符串,这样的注释被 ...

  2. 小甲鱼:Python学习笔记003_函数

    >>> # 函数>>> def myFirstFunction(params1,params2...): print("这是我的第一个函数!") ...

  3. Python学习笔记 - day6 - 函数

    函数 函数在编程语言中就是完成特定功能的一个词句组(代码块),这组语句可以作为一个单位使用,并且给它取一个名字.可以通过函数名在程序的不同地方多次执行(这叫函数的调用).函数在编程语言中有基本分为:预 ...

  4. Python学习笔记系列——函数

    今年下半年的计划主要是Python和Mysql了,公司不方便看书和视频,就照着廖雪峰的Python网站开始看了.以下纯为个人笔记记录,若是想系统学习的小伙伴还是看这里的好一些,毕竟系统.https:/ ...

  5. Python学习笔记(五)函数和代码复用

    函数能提高应用的模块性,和代码的重复利用率.在很多高级语言中,都可以使用函数实现多种功能.在之前的学习中,相信你已经知道Python提供了许多内建函数,比如print().同样,你也可以自己创建函数, ...

  6. python学习笔记(4)--函数

    1.函数 函数是指将一组语句的集合通过一个名字封装起来.要想执行这个函数,只需调用其函数名即可. 函数的特性: 1.减少重复代码 2.使程序变的课扩展 3.使程序变得易维护 语法定义: def pri ...

  7. Python学习笔记-Day3-python函数

    1.为什么要用函数? 提高代码重复利用率,减少代码冗余.封装模块化代码,便于调用 2.函数声明定义(注意:函数先声明后调用) 注意:函数的reture循环中的exit功能一样(函数不执行,终止) 函数 ...

  8. Python学习笔记11—函数

    建立第一个函数 /usr/bin/env Python #coding:utf-8 def add_function(a,b): c = a+b print c if __name__==" ...

  9. Python学习笔记7-把函数当参数传递、指定可变参数

    把函数当参数传递 # 函数参数传递 # 面向对象编程就是把对象传来传去 # 面向函数编程就是把函数传来传去 def mytest(num): return num * 2 # # 不光可以传递变量,还 ...

随机推荐

  1. [Functional Programming] Arrow contramap vs map and promap

    In previous post, Arrow Functor with contramap, we have seen how to opreating on params before we in ...

  2. HK Openstack Summit 归来有感

    4天的Icehouse openstack Summit终于结束,从香港又回到了北京,我们的产品反响相当不错,吸引了很多的注意力和商谈.可是实际上我最近过得很憋屈,心灰意冷,没有了当初那么拼命的动力. ...

  3. Python MySQLdb模块连接操作mysql数据库实例_python

    mysql是一个优秀的开源数据库,它现在的应用非常的广泛,因此很有必要简单的介绍一下用python操作mysql数据库的方法.python操作数据库需要安装一个第三方的模块,在http://mysql ...

  4. Discuz常见小问题-如何为每个板块设置不同的图标

    进入后台的论坛-版块管理,选中要修改图标的板块,点击后面的编辑 在板块图标中找到图标文件,一般是PNG或者GIF,大小为32X32,提交之后效果如下

  5. Initialization failed for Block pool <registering> (Datanode Uuid unassigned) service to IP1:8020 Invalid volume failure config value: 1

    2017-02-27 16:19:44,739 ERROR datanode.DataNode: Initialization failed for Block pool <registerin ...

  6. TOJ 3365 ZOJ 3232 It's not Floyd Algorithm / 强连通分量

    It's not Floyd Algorithm 时间限制(普通/Java):1000MS/3000MS     运行内存限制:65536KByte   描述 When a directed grap ...

  7. 微信小程序 - ios不能播放背景音乐

    由以下原因导致的 1. 未设置标题(backgroundPlayer.title)或标题为空 2. url只能英文,不能出现空格以及其它字符(中文.韩文.日文等)- iOS要求英文路径

  8. typescript - 前言介绍

    众所周知,JavaScript是弱语言(子承父业都表达不了),因此比较大的企业考虑到可维护性以及安全性来说,都不用它开发,因此Typescript诞生了,它并不是为了替换JavaScript而诞生的, ...

  9. Warning: Divide by zero.

    问题:如标题 解决方案:分母加上+eps   参考自:http://www.ilovematlab.cn/thread-43128-1-1.html

  10. MySQL 内存和CPU优化相关的参数

    mysql> SHOW GLOBAL STATUS LIKE 'innodb%read%'; +---------------------------------------+--------- ...