python基础--函数

函数 function

1. 函数定义

函数是可以重复执行的语句块

  • 作用:
可以重复使用,提高代码的重用性, 定义用户级别的函数
  • 函数定义的def 语句的语法:
def 函数名(参数列表):
    语句块(也叫代码块)
  • 语法说明:
1、函数的名字是语句块的名称
2、函数名必须是标识符(和变量的命名规则相同)
3、函数名是一个变量(不要轻易对其赋值),函数与变量一样,需要先定义再调用
4、函数有自己的名字空间,要让函数处理外部数据,需要用参数对此函数传入一些数据
5、函数如果不需要传入参数,则参数列表可以为空
6、语句部分不能为空,如果为空则需要填充pass语句
# 定义了一个叫myfun的函数
def myfun():  #(def需要顶格写)
    print("hello world!")
# 调用myfun函数
myfun()
hello world!
  • 函数要先创建再使用
def f1():    # 相当与创建函数再绑定变量
    pass
f1()   # 正确的调用

# ----------------------
f2()   # 错误的调用,因为此时f2变量还没有绑定函数
def f2():
    pass
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

 in 
      4 
      5 # ----------------------
----> 6 f2()   # 错误的调用,因为此时f2变量还没有绑定函数
      7 def f2():
      8     pass


TypeError: f2() missing 2 required keyword-only arguments: 'a' and 'b'

2. 函数调用

  • 语法:
函数名(实际调用传递参数)  

注:实际调用传递参数称为实参

练习:写一个函数,def mysum(a, b): ,调用时传入两个数,把两数之和打印出来

def mysum(a, b):
    print("a的值是:", a)
    print("b的值是:", b)
    print("两个数的和值:", a + b)

mysum(2, 5)
a的值是: 2
b的值是: 5
两个数的和值: 7
  • 函数变量:
函数名即变量,此变量在创建时绑定一个函数
def fn():
    print("hello world!")

f1 = fn   # 这里没有括号,相当于给fn绑定的这个函数起了一个别名
f1()    # 调用函数fn
fn()    # 调用函数fn
hello world!
hello world!

3. return 语句:

  • 语法:
return [表达式]

注:[]  代表可以省略
  • 作用:
用于函数中,结束当前函数的执行,返回到调用该函数的地方,同时返回一个值对象的引用关系
  • 说明:
1、return 语句后跟的表达式可以省略,省略后相当于return None
2、如果函数内没有return语句,则函数执行完最后一条语句后返回None,相当于在最后加了一条return None语句
3、函数的调用能够用return 语句返回一个对象的引用

练习: 写一个函数mymax,实现返回两个数的最大值

def mymax2(a, b):
    return a if a > b else b

print(mymax2(100, 200))
200

练习: 假设有一个列表有很多数据,还有重复的,打印出列表中的数据,要求重复的只打印一次,打印的顺序要以列表中第一次出现的顺序为准

L = [1, 1, 2, 3, 4, 8, 6, 6, 5, 4, 3]


def remove_duplicates_1(L):
    l1 = []
    s = set()

    for x in L:
        if x in s:
            continue
        s.add(x)
        l1.append(x)
    return l1


print(remove_duplicates_1(L))


def remove_duplicates_2(L):
    s = set(L)
    l1 = []
    for x in L:
        if x in s:
            s.remove(x)
            l1.append(x)
    return l1


print(remove_duplicates_2(L))


def remove_duplicates_3(L):
    l1 = []
    for x in L:
        if x not in l1:
            l1.append(x)
    return l1


print(remove_duplicates_3(L))
[1, 2, 3, 4, 8, 6, 5]
[1, 2, 3, 4, 8, 6, 5]
[1, 2, 3, 4, 8, 6, 5]

练习: 定义两个函数:sum3(a, b, c)用于返回三个数的和,pow(x) 用于返回x的三次方(立方

(1)、用以上函数计算 1 的三次方加 2 的三次方加 3 的三次方的和
(2)、计算1+2+3的立方
def sum3(a, b, c):
    return (a + b + c)


def pow(x):
    return x ** 3


print(sum3(pow(1), pow(2), pow(3)))
print(pow(sum3(1, 2, 3)))
36
216

4. 函数调用时的参数传递方式:(调用函数)

位置传参
序列传参
关键字传参
字典关键字传参
  • 位置传参:
实际参数(实参)的对应关系与形式参数(形参)对应关系是按位置依次对应的实参的个数和形参的个数要严格一致
def myfun1(a, b, c):  # 形参
    print(a)
    print(b)
    print(c)

    
# 调用
myfun1(1, 2, 3)  # 实参
1
2
3
  • 序列传参
序列传参是指在函数调用过程中,用*将序列拆解后按位置进行传递的方式
序列传参时,序列拆解的位置将与形参一一对应
序列的位置信息对应相应的参数
L1 = [11,22,33]
T1 = (4.4,5.5,6.6)
S1 = "ABC"
myfun1(*L1)
myfun1(*T1)
myfun1(*S1)
11
22
33
4.4
5.5
6.6
A
B
C
  • 关键字传参:
关键字传参是指传参时,按形参的名称给形参赋值
实参和形参按形参名进行匹配(可以不按位置顺序进行匹配)
# 关键字传参
myfun1(c = 33, b = 22, a = 11)
11
22
33
  • 字典关键字传参:
是指实参为字典,将字典用**拆解后进行关键字传参

字典的键名和形参名必须一致
字典的键名必须为字符串,并符合关键字的命名
字典的键名要在形参中存在
d1 = {"c":33, "b":22, "a":11}
myfun1(**d1)
11
22
33
  • 函数的综合传参
在能确定每个形参否能唯一匹配一个实参的情况也可以任意传参
传参时,位置传参和序列传参要先于关键字传参和字典关键子传参
myfun1(100, *[200, 300])
myfun1(*[10,20],30)
myfun1(*[10], 20, *[30])
myfun1(100, **{"c":300, "b":200})
myfun1(**{"c":300, "b":200}, a = 100)
100
200
300
10
20
30
10
20
30
100
200
300
100
200
300
myfun1(b = 200, c = 300, 100)   # 错的
  File "", line 1
    myfun1(b = 200, c = 300, 100)   # 错的
                            ^
SyntaxError: positional argument follows keyword argument
  • 注意传参时:
1、不可变类型的数据作为函数参数传入时,函数内部不会改变变量的原数据的值
2、可变类型的数据作为函数参数传递时,函数内部可以改变原数据,多用与返回更多函数执行结果

练习:写一个函数:def mymin(x, y, z): 这个函数传入三个参数,返回三个中最小值,尝试使用四种传参方式?

def mymin(a, b, c):
    t = a
    if t > b:
        t = b
    if t > c:
        t = c
    return t

print(mymin(1, 2, 3))
print(mymin(*[1, 2, 3]))
print(mymin(a=1, b=2, c=3))
print(mymin(**{'a': 1, 'b': 2, 'c': 3}))
1
1
1
1
  • 函数参数为可变类型的对象,传参问题
L = []

def fn(x):
    # 创建一个局部变量,但不会修改全局的L变量
    L = [x]
    print(L, id(L))

def fn2(l):
    # 全局的L变量已经改变
    l.append(1)
    print(l, id(l))

print(L, id(L))

fn(10)
print(L, id(L))

fn2(L)
print(L, id(L))
[] 4389963400
[10] 4389737928
[] 4389963400
[1] 4389963400
[1] 4389963400

练习: 写一个函数,在函数内输入一些整数,把所有奇数放入全局列表odds中, 把所有的偶数放入全局的列表evens中

odds = []
evens = []


def input_number(o, e):
    while True:
        n = int(input("请输入整数:"))
        if n < 0:
            break
        # 如果n为奇数则添加列表odds中
        if n % 2 == 1:
            o.append(n)
        else: # 如果n为偶数则添加到列表evens中
            e.append(n)


input_number(odds, evens)
print(odds)   # 此列表将被修改
print(evens)    # 此列表也将被修改
请输入整数:5
请输入整数:8
请输入整数:1
请输入整数:-1
[5, 1]
[8]

5. 函数的参数定义方式(创建函数):

位置形参
星号元组形参
命名关键字形参
双星号字典形参
  • 位置形参语法:
def 函数名(形参名1, 形参名2, 形参名3,......):
    语句块
  • 星号元组形参语法:(收集多余的位置传参)
def 函数名(*元组形参名):
    语句块
def funs(*args):
    # args绑定一个元组,此元组内的元素是为了剩余的位置传参
    print("实参个数是:", len(args))
    print("args绑定", args)

funs()  # 以无参调用
funs(1, 2, 3, 4)
funs("ABC", 1, 2.3, 4+5J)
实参个数是: 0
args绑定 ()
实参个数是: 4
args绑定 (1, 2, 3, 4)
实参个数是: 4
args绑定 ('ABC', 1, 2.3, (4+5j))

练习:写一个函数mysum2,实参可以传入任意个,返回所有实参的和

def mysum2(*args):
    s = 0
    for x in args:
        s += x
    return s

print(mysum2(1, 2, 3, 4))
print(mysum2(1, 2.2, 3+4J))
10
(6.2+4j)
  • 命名关键字形参语法:

所有的命名关键字形参,必须用关键字传参或字典关键字传参进行参数传递

def 函数名(*, 命名关键字形参):  # 不允许传位置参数
    语句块
或:
def 函数名(*args, 命名关键字形参):
    语句块
def fn(*, a, b):
    print("a的值为:", a)
    print("b的值为:", b)

# fn(1, 2)  # 错的,a和b 必须是用关键字传参
fn(a = 1, b = 2)  #必须这么传
fn(b = 0, a = 20)
fn(**{"b":200, "a":100})

def f2(*args, a, b):
    print("args=", args)
    print("a=", a)
    print("b=", b)

f2(1, 2, 3, 4, a=100, b=200)
f2(a=100, b=200)
a的值为: 1
b的值为: 2
a的值为: 20
b的值为: 0
a的值为: 100
b的值为: 200
args= (1, 2, 3, 4)
a= 100
b= 200
args= ()
a= 100
b= 200
  • 双星号字典形参语法:

作用:收集多余的关键字传参(例如:dict()),通常只有一个

def 函数名(**字典形参名):
   语句块
def func(**kwagrs):  # kwagrs绑定一个字典
    print("参数个数:", len(kwagrs))
    print("kwagrs的值为:", kwagrs)

func(name="zhuang", age=25, address="dgas")
func(**{"name": "zhuang", "age": 25, "address": "dgas"})
func()
参数个数: 3
kwagrs的值为: {'name': 'zhuang', 'age': 25, 'address': 'dgas'}
参数个数: 3
kwagrs的值为: {'name': 'zhuang', 'age': 25, 'address': 'dgas'}
参数个数: 0
kwagrs的值为: {}
  • 函数的缺省参数:
def 函数名(形参名1 = 默认实参1, 形参名2 = 默认实参2, ....):
    语句块

说明:

1. 缺省参数必须自右至左依次存在,如果一个参数有缺省参数,则其右侧的所有参数都必须有缺省参数, 如:
def test_fn(a, b = 10, c):    # 是错的

2. 缺省参数可以有0个或多个,甚至全部都有缺省参数

3. 位置形参和命名关键字形参可以使用缺省参数
def info(name, age=1, address="未填写"):
    print(name, "住在:", address, "今年:", age, "岁")

info("庄AC", 23,  "北京")
info("庄AC", 23)
庄AC 住在: 北京 今年: 23 岁
庄AC 住在: 未填写 今年: 23 岁

练习:写一个函数myadd有三个参数,此函数可以计算两个数的和,也可以计算三个数的和

def myadd(a, b, c=0):
    return a + b + c

print(myadd(10, 20))
print(myadd(10, 20, 30))
30
60
  • 函数参数自左至右的顺序为:
位置形参, 星号元组形参, 命名关键字形参, 双星号字典形参
def fn(a, b="b", *args, c, f="f", **kwargs):
    print(a, b, args, c, f, kwargs)

fn(100,200,300,400,c=5.5,d=6.6,e=7.7, f=8.8)
fn(10,*"AB",20,**{"d": 11, "e": 33, "c":300})

# ----------以下函数可以接受任意的位置传参和关键字传参------------
def fn(*args, **kwargs):
    pass
100 200 (300, 400) 5.5 8.8 {'d': 6.6, 'e': 7.7}
10 A ('B', 20) 300 f {'d': 11, 'e': 33}

6. 函数的完整格式

  • 文档字符串:
def 函数名(形参列表)
    函数文档字符串
    语句块
  • 说明:
1、函数的定义语句(def 语句)的第一次出现的没有赋值给任何变量的字符串为文档字符串
2、文档字符串通常用来说明本函数的功能和使用方法
3、在交互模式下,输入>>>help(函数名) 可以查看文档字符串
def myfun():
    """我是文档字符串"""

help(myfun)
Help on function myfun in module __main__:

myfun()
    我是文档字符串
  • 函数的参数注释:

只能用在python3.5 之后的版本

def fn(a:"第一个参数", b:"第二个参数", c:int) -> str:
    return str(a + b + c)

fn(1, 2, 3)
'6'
  • 函数定义的完整语法

详见:>>> help(“def”)

[装饰器]
def 函数名([位置形参], [*元组形参], [命名关键字形参], [**字典形参]) [-> 注释表达式]:
    """文档字符串"""
    语句块
help("def")

7. 函数属性 attribute(部分)

  • __name__属性
作用:用来记录函数名
说明:1、通常属性是指对象(实例)的变量
     2、以双下划线开头,以双下划线结尾的标识符代表Python的特殊变量
def abc():
    pass

fn = abc
print("fn绑定的函数名是:", fn.__name__)
fn绑定的函数名是: abc
  • __doc__属性:
作用:用于记录文档字符串
def cba():
    "这是一块文档字符串"
    pass

print(cba.__doc__)
这是一块文档字符串
  • __code__属性
Python创造了一个新的函数对象。在这个函数对象里,可以看到字节码,元数(也就是参数数量)和一些与函数相关的其他东西。大多数这些东西存在于函数对象的__code__属性里。事实上,研究__code__是了解Python函数如何运行的最好办法。
def foo():
      return "I'm foo!"

# 函数foo的元数是由foo.__code__.co_argcount获得,而字码节存在于foo.__code__.co_code中。
print(foo.__code__.co_argcount, foo.__code__.co_code)

def bar():
      return "I'm bar!"

# __code__对象的属性是只读,但是__code__属性本身不是
foo.__code__ = bar.__code__

foo()
0 b'd\x01S\x00'





"I'm bar!"

练习:仿造max,写一个mymax函数,功能与max完全相同(要求,不允许调用max函数)

def mymax(a, *args):
    if len(args) != 0:
        m = a
        for x in args:
            if x > m:
                m = x
    else:
        m = a[0]
        for i in range(1, len(a)):
            if a[i] > m:
                m = a[i]
    return m


print(mymax([6, 8, 3, 5]))
print(mymax(100, 200))
8
200

练习:写一个myrange函数,参数可以传入1-3个,实际含义同range函数规则相同, 此函数返回符合range(....) 函数规则的列表

如:
L = myrange(4)   # L = [0, 1, 2, 3]
L = myrange(4, 6)   # L = [4, 5]
L = myrange(1, 10, 3)   # L = [1, 4, 7]
print(L)   # [1, 4, 7]
def myrange(*args, x=1):
    L = []
    if len(args) == 1:
        i = 0
        while i < args[0]:
            L.append(i)
            i += x
    elif len(args) == 2:
        if args[0] > args[1]:
            return L
        i = args[0]
        while i < args[1]:
            L.append(i)
            i += x
    elif len(args) == 3:
        i = args[0]
        x = args[2]
        while i < args[1]:
            L.append(i)
            i += x
    else:
        return ("TypeError: range expected at most 3 arguments")
    return L

print(myrange(5))
print(myrange(2, 6))
print(myrange(5, 10, 2))
print(myrange(5, 5))
[0, 1, 2, 3, 4]
[2, 3, 4, 5]
[5, 7, 9]
[]

练习: 写一个函数isprime(x),判断x是否为素数,如果为素数返回True,否则返回False

def isprime(x):
    if x <= 1:
        return False
    for i in range(2, x):
        if x % i == 0:
            return False
    return True

isprime(3)
True

练习: 写一个函数prime_m2n(m, n)返回从m开始,到n结束内所有的素数的列表

def primes(start, stop):
    L = []
    for a in range(start, stop):
        if isprime(a):
            L.append(a)
    print(L)

primes(100, 200)
[101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199]

同名公众号:庄AC

你可能感兴趣的:(Python,基础,python)