Skip to content

函数

函数就是组织好的, 可以重复使用的, 用于是想特定功能的代码片段, 比如之前学的 print input range type 等, 但是那些都是编译器内置的函数 而我们现在要学习的是自定义的函数

定义与调用

python
# - 定义
def 函数名(参数 1, 参数 2...参数 n)
    """
    函数说明文档(可选)
    """
    函数体代码
    return 结果

# - 调用
变量接收结果=函数名(参数 1, 参数 2...参数 n)
python
# 定义函数(获取字符串中字符的个数)
def length(s):
    """
    获取一个字符串的长度
    :param s: 字符串
    :return : 字符串长度
    """
    char_count = 0
    for i in s:
        char_count += 1
    return char_count

# 调用函数
print(length("tom"))  # 3
print(length("hello"))  # 5

None 类型

空值, 类似 js 的 undefined

python
def say_hi():
    print("hi")

res = say_hi()
print(res) # None

作用域

变量的作用范围, 简单来说就是在哪个位置可以访问, 哪个位置不能访问

全局作用域

python
msg = "hi"

def f1():
    # 在函数 1 中可以访问
    print(msg)

def f2():
    # 在函数 2 中可以访问
    print(msg)

# 在函数外部也能使用
print(msg)
f1()
f1()

函数作用域

python
def f1():
    # 只能在函数内部使用
    msg = "hi"
    print(msg)

f1()

# print(msg)
# 无法在函数外部使用
# NameError: name 'msg' is not defined

global

为什么输出 hi 而不是 hello?

python
msg = "hi"


def f1():
    # 因为这个 msg 是局部变量和外部的 msg 没有关系
    msg = "hello"
    print(msg)


f1()

print(msg)

现在, 我就是想要在 f1 函数中修改 msg 的值, 应该如何操作?

python
msg = "hi"


def f1():
    # 告诉编译器 num 是全局变量不是函数内部的局部变量
    global num
    msg = "hello" # 此时就可以正常修改 msg 的值
    print(msg)


f1()

# 输出 hello
print(msg)

函数多返回值

python
def ret_mut_items():
    return 1, 2, 3

items = ret_mut_items()
print(type(items)) # <class 'tuple'>

# 类似 js 中的解构操作
a, b, c = ret_mut_items()
print(type(a), type(b), type(c))
# <class 'int'> <class 'int'> <class 'int'>

函数默认参数

与 js 的默认参数一模一样, 注意有默认值的放最后

py
def get_conf(url="http://localhost", port="8080"):
    return url, port

url1, port1 = get_conf(url="http://example.com", port="80")
url2, port2 = get_conf()

print(f"url1: {url1}")
print(f"url2: {url2}")

print(f"port1: {port1}")
print(f"port2: {port2}")

# Console Output:
# url1: http://example.com
# url2: http://localhost
# port1: 80
# port2: 8080

函数可变参数

  • *: 位置不定长参数, 任意多个参数, 组成 tuple 供函数内部访问
  • ** 关键字不定长参数, 任意多个参数但必须是 key value 对, 组成字典供函数内部访问
python
# 类似 js 的剩余参数 `output_args(...args)`
def output_args1(*args):
    print(args) # (1,2,3,4,5)
    print(type(args)) # tuple

output_args1(1, 2, 3, 4, 5)

def output_args2(**kwargs):
  print(kwargs)

# 必须传入字典的函数
output_args2(id=1, name="tom", gender="male")

lambda 匿名函数

  • 注意: 函数体只能写一行
python
items = [1, 3, 5, 7, 9]

def for_each_list(items, handler):
    for i in range(len(items)):
        item = items[i]
        handler(i, item)

# 类似 js 箭头函数 (x, y) => xxx, 但是 lambda 只能写一行
# lambda 参数1, 参数2 :  函数体(一行)
for_each_list(items, lambda i, n: print(f"index:{i} value:{n}"))

闭包

python
# 函数缓存
def memoize(fn):
    caches = {}
    def memoized_func(*args):
        nonlocal caches # 这个 caches 会一直被引用不会释放
        key = f"{args}"
        cache = caches.get(key)

        if(cache):
            print("result from cache")
            return cache
        else:
            val = fn(*args)
            caches[key] = val
            return val
    return memoized_func


def sum(x, y):
    print(f"sum is called with {x},{y}")
    return x + y

lazy_sum = memoize(sum)

lazy_sum(1, 2)
lazy_sum(1, 2)
lazy_sum(1, 2)
lazy_sum(1, 2)
lazy_sum(1, 2)
lazy_sum(3, 4)
lazy_sum(3, 4)
lazy_sum(3, 4)
lazy_sum(3, 4)
lazy_sum(3, 4)
lazy_sum(3, 4)

Released under the MIT License.