Python函数基础

函数先定义函数,后调用

一、定义函数:

def 函数名(param1,param2……):
"""
函数功能的描述信息
:param1:描述
:param2:描述
:return:返回值
"""
code
...
return 返回值

1、无参函数

def register():
    """注册功能"""
    username = input('username: ').strip()
    pwd = input('password: ').strip()

    with open('32.txt', 'a', encoding='utf8') as fa:
        fa.write(f"{username}:{pwd}\n")
        fa.flush()

2、有参函数

def sum_self(x, y):
    """求和"""
    res = x+y
    print(res)

sum_self(1,2)  # 3

3、空函数

你只知道你需要实现某个功能,但不知道该如何用代码实现时,你可以暂时写个空函数

def func():
    pass

二、调用函数及返回值

函数名(param1、param2……)

如:

register()

1、函数运行完毕所有代码,如果函数体不写return,则会返回None。

def foo():
    pass

print(foo()) #None

2、函数可以返回一个或多个值

def func():
    name = 'nick'
    age = 19
    hobby_list = ['read', 'run']
    return name, age, hobby_list


name, age, hobby_list = func()
print(name,age,hobby_list) #('nick', 19, ['read', 'run'])

三、函数的参数

1、普通参数

(1)位置形参

在函数定义阶段,按照从左到右的顺序依次定义的形参,称之为位置形参。

特点:按照位置定义的形参,都必须被传值,多一个不行,少一个也不行。

def func(x, y):
    print(x)
    print(y)

(2)位置实参

在函数调用阶段,按照从左到右的顺序依次定义的实参,称之为位置实参。

特点:按照位置为对应的形参依次传值。

func(1, 2)

(3)关键字实参

在调用函数时,按照key=value的形式为指定的参数传值,称为关键字实参。

特点:可以打破位置的限制,但仍能为指定的形参赋值。

func(y=2, x=1)
  1. 可以混用位置实参和关键字实参,但是位置实参必须在关键字实参的左边。
  2. 可以混用位置实参和关键字实参,但不能对一个形参重复赋值。
func(x, y=2)
func(y=2, x)  # SyntaxError: positional argument follows keyword argument
func(x, x=1)  # NameError: name 'x' is not defined

(4)默认形参

在定义阶段,就已经被赋值。意味着在调用时可以不用为其赋值。位置形参必须放在默认形参的左边。

def func(x, y=10):
    print(x)
    print(y)
    
func(2)

默认形参的值只在定义阶段赋值一次,也就是说默认参数的值在函数定义阶段就已经固定了。

m = 10

def foo(x=m):
    print(x)

m = 111
foo()  # 10

默认参数的值通常应该是不可变类型。

def register(name, hobby, hobby_list=None):
    hobby_list = [hobby]
    print(f"{name} prefer {hobby_list}")


register('nick', 'read')  # ['read']
register('tank', 'zuipao')  # [ 'zuipao']
register('jason', 'piao')  # ['piao']

# 演示形参是可变类型,(列表是可变类型)
def register(name, hobby, hobby_list=None):
    hobby_list = [hobby]
    print(f"{name} prefer {hobby_list}")


register('nick', 'read')  # nick prefer ['read']
register('tank', 'zuipao')  # tank prefer ['zuipao']
register('jason', 'piao')  # jason prefer ['piao']o']

2、可变长参数

(1)、可变长形参之*

形参中的*会将溢出的位置实参全部接收,然后存储元组的形式,然后把元组赋值给*后的参数。需要注意的是:*后的参数名约定俗成为args。

def sum_self( *args):
    res = 0
    for num in args:
        res += num
    return res


res = sum_self(1, 2, 3, 4)
print(res)  # 10

(2)、可变长实参之*

实参中的*,*会将*后参数的值循环取出,打散成位置实参。以后但凡碰到实参中带*的,它就是位置实参,应该马上打散成位置实参去看。

def func(x, y, z, *args):
    print(x, y, z, args)


func(1, *(1, 2) , 3, 4)  # 1 1 2 (3, 4)

(3)、可变长形参之**

形参中的**会将溢出的关键字实参全部接收,然后存储字典的形式,然后把字典赋值给**后的参数。需要注意的是:**后的参数名约定俗成为kwargs。

def func( **kwargw):
    print(kwargw)


func(a=5)  # {'a': 5}

(4)、可变长实参之**

实参中的**,**会将**后参数的值循环取出,打散成关键字实参。以后但凡碰到实参中带**的,它就是关键字实参,应该马上打散成关键字实参去看。

def func(x, y, z, **kwargs):
    print(x, y, z, kwargs)


func(1, 3, 4, **{'a': 1, 'b': 2} )  # 1 3 4 {'a': 1, 'b': 2}

(5)、可变长参数应用

def index(name, age, sex):
    print(f"name: {name}, age: {age}, sex: {sex}")  # name: nick, age: 19, sex: male


def wrapper(*args, **kwargs):
    print(f"args: {args}")  # args: ()
    print(f"kwargs: {kwargs}")  # kwargs: {'name': 'nick', 'sex': 'male', 'age': 19}
    index( *args, **kwargs)


wrapper(name='nick', sex='male', age=19)

(6)、命名关键字形参

命名关键字则是在「位置参数」和「命名关键字参数」中使用,*,隔开,后面的即为命名关键字

def student(name, age, *, city, gender):
    print(name, age, city, gender)


student('xiaoming', 6, city='beijing', gender='male')  # xiaoming 6 beijing male
student('xiaoming', 6, 'beijing', 'male') #TypeError: student() takes 2 positional arguments but 4 were given

特点:在传值时,必须按照key=value的方式传值,并且key必须命名关键字参数的指定的参数名。

def register(x, y, *, name, gender='male', age):
    print(x)
    print(name)
    print(age)


register(1, 2, name1='nick', age=19)  # TypeError: register() got an unexpected keyword argument 'name1'

四、函数对象

函数是第一类对象,即函数可以被当做数据处理。

def func():
    print('from func')


print(func)  # 

1、函数当作参数传给一个另一函数

def func():
    print('from func')


def foo(m):
    m()


foo(func)  # from func

2、函数当作另一函数的返回值

def func():
    print('from func')


def foo(x):
    return x


res = foo(func)
print(res)  # 

3、函数可以当作容器类型的元素

def func():
    print('from func')


function_list = [func]
function_list[0]()  # from func

五、名称空间和作用域

  1. 内置名称空间:存放内置的名字,如len/eval/enumerate/bytes/max/min/sorted/map/filter....
  2. 全局名称空间:除了内置与局部,其他的名字都存放在全局名称空间内
  3. 局部名称空间:函数内部的名字都是局部名称空间,不同函数内部的名字互不干涉
  • 查找顺序:从当前开始往上寻找,如果当前是局部名称空间,查找顺序为:局部--》全局--》内置
  • 执行顺序:先内置(Python解释器启动的时候才会生成)--》全局(文件执行的时候才会生成)--》局部(函数调用的时候才会生成)

作用域:全局名称空间和局部名称空间中可能会存在名字相同的变量,但是这两个变量互不影响。

  • 全局作用域:全局有效,全局存活,包含内置名称空间和全局名称空间。

  • 局部作用域:局部有小,临时存储,只包含局部名称空间。

x = 1


def func():
    print(x)  #10


x = 10
func()

作用域关系在函数定义阶段就固定死了,与函数的调用无关。

# 作用域注意点
x = 1


def f1():  # 定义阶段x=1
    print(x)  #1


def f2():
    x = 2
    f1()


f2()

1、引用另一函数

def f1():
    print('from inner')


f = f1
f()  # from inner

2、函数对象+作用域应用

def f1():
    def inner():
        print('from inner')
    return inner


f = f1()  # from inner   。把局部定义的函数inner()放在全局之中


def bar():
    f()


bar()

3、global关键字修改全局作用域中的变量

x = 1


def f1():
    x = 2

    def f2():
        global x  # 修改全局
        x = 3

    f2()


f1()
print(x)  # 3

4、nonlocal关键字修改局部作用域中的变量。

x = 1


def f1():
    x = 2

    def f2():
        nonlocal x
        x = 3

    f2()
    print(x)  # 3


f1()

你可能感兴趣的:(Python函数基础)