持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情
语法
def 函数名(参数列表):
函数体
实例
def max(a, b):
if a > b:
return a
else:
return b
if __name__ == '__main__':
print(max(3, 4))
参数传递
这个其实和java一样,只是细节上不一样,都是分为两种:
- 不可更改-strings、tuples和numbers。如fun(a),传递的只是a的值,没有影响a对象本身。如果在fun(a)内部修改a的值,则是新生成一个a的对象。
java的不可更改的有:基础类型及基础类型对应的封装类型、String。
- 可更改-list、dict等
java的可更改的有:把不可更改的进行封装的广大类对象。
传不可变对象实例
通过id()函数来查看内存地址变化:
def change(a):
# 通过id()函数来查看内存地址变化
print(id(a))
a = 10
print(id(a))
if __name__ == '__main__':
a = 1
print(id(a))
change(a)
输出:
4379320568
4379320568
4379320856
传可变对象实例
def listAdd(list):
list.append(5)
if __name__ == '__main__':
list = [1, 2, 3, 4]
listAdd(list)
print(list)
调用参数的类型
必须参数
必须以正确的顺序传入函数。调用时的数量必须和声明时的一样。
def printme(a1, a2):
a1 = a1 + "ddd"
a2 = a2 + 1
print(a1, a2)
if __name__ == '__main__':
a1 = "谢谢"
a2 = 1
printme(a2, a1)
输出:
Traceback (most recent call last):
File "/Users/wanghaifeng/PycharmProjects/study/basic/flow/def.py", line 32, in <module>
printme(a2, a1)
File "/Users/wanghaifeng/PycharmProjects/study/basic/flow/def.py", line 24, in printme
a1 = a1 + "ddd"
TypeError: unsupported operand type(s) for +: 'int' and 'str'
这个让我感受到了动态类型的缺点,可读性和出错。
关键字参数
def printme(a1, a2):
a1 = a1 + "ddd"
a2 = a2 + 1
print(a1, a2)
if __name__ == '__main__':
a1 = "谢谢"
a2 = 1
printme(a1=a1, a2=a2)
这样就很明确了,这就是py的聪明之处,很灵活
默认参数
def printinfo(name, age=35):
print("名字:", name)
print("年龄:", age)
if __name__ == '__main__':
printinfo(age=50, name="hf")
print("____________")
printinfo(name="ff")
看到默认参数方法的调用可以省略掉默认参数,让我想到了java的重载,下面我们来看看py支不支持重载:
def printinfo(name, age=35):
print("名字:", name)
print("年龄:", age)
def printinfo(name):
print("名字:", name)
if __name__ == '__main__':
printinfo(age=50, name="hf")
print("____________")
printinfo(name="ff")
输出:
Traceback (most recent call last):
File "/Users/wanghaifeng/PycharmProjects/study/function/def.py", line 39, in <module>
printinfo(age=50, name="hf")
TypeError: printinfo() got an unexpected keyword argument 'age'
可以发现报错了,其实是被下面的覆盖了。至于不同类型,因为py是弱类型,所以不可能存在,但是函数对应的是一个“动作”,动作可能会因为类型不一样导致“动作”内容(方法体)不一样,所以这点笔者认为就算有默认参数也是没有java的重载来的灵活的。
不定长参数
加了*的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数:
笔者有点乱了,go中*表示指针参数。
def printinfo(arg1, *vartuple):
print(arg1, vartuple)
if __name__ == '__main__':
printinfo(10)
printinfo(70, 60, 50)
输出:
10 ()
70 (60, 50)
**的参数会以字典的形式导入:
def printinfo(arg1, **vardict):
print(arg1, vardict)
printinfo(1, a=2, b=3)
输出:
1 {'a': 2, 'b': 3}
还是一样的感觉:灵活
单独出现*,则*后面的参数必须用关键字传入:
def f(a, b, *, c):
return a + b + c
f(1, 2, 3)
输出:
Traceback (most recent call last):
File "/Users/wanghaifeng/PycharmProjects/study/function/def.py", line 52, in <module>
f(1, 2, 3)
TypeError: f() takes 2 positional arguments but 3 were given
必须这样:
def f(a, b, *, c):
return a + b + c
# f(1, 2, 3)
f(1, 2, c=4)
匿名函数
Python使用lambda来创建匿名函数:
sum = lambda arg1, arg2: arg1 + arg2
print("相加后的值为:", sum(10, 20))
print("相加后的值为:", sum(20, 20))
我们可以将匿名函数封装在一个函数内,这样可以使用同样的代码来创建多个匿名函数:
def myfunc(n):
return lambda a: a * n
mydoubler = myfunc(2)
mytripler = myfunc(3)
print(mydoubler(11))
print(mytripler(11))