python函数相关知识和一些基本练习

 1.13 函数/方法

主要解决的问题:将那些具有**独立性功能**的,且**重复的代码**进行封装

- 这一段代码,专门用于处理某一个问题

比如素数问题:

```python
a = 10
b = 110
c = 129087
# 哨兵:监控状态变化
flag = True # 默认是素数
for n in range(2, a // 2 + 1):
    if a % n == 0:
        flag = False
        break
if flag:
    print("YES")
else:
    print("No")
    
# 哨兵:监控状态变化
flag = True # 默认是素数
for n in range(2, b // 2 + 1):
    if b % n == 0:
        flag = False
        break
if flag:
    print("YES")
else:
    print("No")

# 哨兵:监控状态变化
flag = True # 默认是素数
for n in range(2, c // 2 + 1):
    if c % n == 0:
        flag = False
        break
if flag:
    print("YES")
else:
    print("No")
```

![image-20240419192620231](https://zh-1258460726.cos.ap-nanjing.myqcloud.com/image-20240419192620231.png)

> 到底什么是函数,就是一个具有固定功能的一段代码,根据不同输入的参数,进行同样的计算,得到不同的结果

Python当中 函数的语法格式:

```
def 函数名(参数列表):
    函数体,具体的执行内容
    return 返回值   
# 如果函数不需要返回 则可以不写return
# return 它仅仅表示结束当前函数 如果有返回值则写上 没返回值可以不写return 默认返回None
# 函数必须先定义 再调用(除了面向对象在类中定义函数时)
```

素数的问题进行函数化:

```python
# 素数问题
def isSushu(num):
    for n in range(2, num // 2 + 1):
        if num % n == 0:
            return False
    return True
# TypeError: isSushu() missing 1 required positional argument: 'num'
# NameError: name 'isSushu' is not defined
# isSushu()

def isSushuNoReturn(num):
    for n in range(2, num // 2 + 1):
        if num % n == 0:
            print(False)
            return
    print(True)
    return # 其实可以不写 但是存在 (隐藏的)

# print(isSushu(11))
print(isSushuNoReturn(11))
```

**关于函数局部变量的一些问题**

```python
n = 10
def test01(n):
    # 局部变量n 用于接受外部变量的数据
    n = 20 # n是test01内部创建的一个变量
test01(n)
print(n)

arr = [1,2,3]
def test02(arr):
    # 局部变量arr 用于接受外部变量的数据
    arr[0] = 666 #arr是test02内部创建的一个变量
test02(arr)
print(arr)
```

![image-20240419195320028](https://zh-1258460726.cos.ap-nanjing.myqcloud.com/image-20240419195320028.png)

```python
n = 100
def test03():
    n = 200 # 函数内部创建的变量
    m = 300 # 函数内部创建的变量
test03()
print(n)
print(m) # NameError: name 'm' is not defined
```

在函数的外面,并不能调用函数内部创建的变量(局部变量)

> 一定要区分,在函数内部
>
> - 操作的变量是局部的还是全局的
> - = 是创建还是修改
>
> ```python
> n = 100
> def test04(n): # n 是以局部变量的形式创建的 然后在接收全局n的100
>     n = 200 # 修改
>     m = 300 # 创建
> test04(n)
> print(n)
> print(m)
> ```

如何修改外部变量,用`global`关键字去指定

```python
n = 100
m = 300
def test05():
    n = 666
    print(n)
    global n, m # 事先指定哪些变量是全局的
    n = 200
    m = 400
    print(n)
    # SyntaxError: name 'n' is used prior to global declaration
    # 在函数内部 局部变量和全局变量 不要重名
test05()
print(n)
print(m)
```

```python
n = 100
m = 300
def test06():
    global n
    n = 200 # 已经被声明为全局
    m = 400 # 局部变量
test06()
print(n, m)
```

```python
def test07(arr): # 局部变量 函数被调用时 指向[1,2,3]
    arr = [2, 3, 4] # 被修改 指向[2,3,4]
arr = [1, 2, 3]
test07(arr)
print(arr)
```

**Python主函数的问题**

函数还能将代码进行模块化,解耦,方便阅读、维护、设计

```python
# 程序的入口 看成主函数
if __name__ == "__main__":
    print("Hello World")
```

**关于函数的具体执行的流程**

> - 函数的运行 是基于栈内存的
> - 每一个函数看作是栈内存的元素
> - 哪个函数在栈顶 那么它就优先执行 直到调用别的函数 当前函数暂停执行
> - 函数但凡被调用 则加载到栈内存中 成为新的栈顶
> - 函数执行完毕(遇到return) 则弹栈 新的栈顶继续执行
>
> 具体看录屏的动画

```python
# 递归
def show():
    arr = [0] * 1000000000000000 # MemoryError 堆内存溢出
    print("show") # RecursionError: maximum recursion depth exceeded 栈内存溢出
    show()

def main():
    show()

if __name__ == "__main__":
    main()
```

> 所谓的递归 其实就是函数自身调用自身 
>
> 栈内存溢出 栈主要存函数的 函数存不下了 (主要还是因为递归)
>
> 堆内存溢出 堆主要存对象的 对象存不下了(一直在创建新的数据对象)

**递归的应用**

递归如果设计不当,容易导致占内存溢出

所以之后在写递归的时候,需要注意啥?**注意递归什么时候结束**!

> 递归,它可以将一个大型复杂的问题,进行逐层的化解,化为若干个较小的问题,同时这些较小的问题也可继续进行化解为若干个更小的问题,直到该问题不能被化解为止(终止递归)->原子问题是可以直接被求解的
>
> 所以,将所有原子问题的解,进行合并,就得到了原问题的解
>
> - 原子问题之间的求解,不能相互作用,互不影响!
> - 每一层问题的求解方式,都是一致的!
>
> 上述的内容,就是【**分治算法**】

但凡是迭代的问题,都可以被递归写,但反过来就不一定了

同样的一个问题,用迭代写的代码较多,用递归写的代码较少

递归可以用少量的代码来解决较大的问题

> 人用迭代,神用递归

```python
# (1)计算1~100之间的求和问题
"""
f(100) = 1+2+3+4+....+99+100
f(99) = 1+2+3+4+...+98+99
f(n) = f(n - 1) + n

f(100) = f(99) + 100 
f(99) = f(98) + 99      1+2+3+...+98 + 99
....
f(4) = f(3) + 4         1+2+3 + 4
f(3) = f(2) + 3         1+2 + 3
f(2) = f(1) + 2         1 + 2
f(1) = 1                # 递归的边界条件
f(100)->f(1) 递归的前进段
f(1) = 1     递归的边界条件
f(1)->f(100) 递归的返回段
        1, n = 1
f(n)
        f(n-1) + n, n > 1

"""
def nSum(n):
    if n == 1:
        return 1
    return nSum(n - 1) + n


#(2)斐波那契数列
"""
1 1 2 3 5 8 13 21 34 55 89 ...
f(n) = f(n-1) + f(n-2)
                  f(5)
            f(4)   +    f(3)
        f(3) + f(2)  f(2) + f(1) 
    f(2) + f(1)   

        1, n ∈[1,2]
f(n)
        f(n-1) + f(n-1), n > 2
"""
def fibo(n):
    if n == 1 or n == 2:
        return 1
    return fibo(n - 1) + fibo(n - 2)

#(3)二分查找
def binarySearch(arr, L, R, key):
    if L > R:
        return -1
    M = (L + R) // 2
    if arr[M] == key:
        return M
    elif arr[M] < key:
        return binarySearch(arr,M + 1, R, key)
    else:
        return binarySearch(arr,L, M - 1, key)

def main():
    print(nSum(100))
    #print(fibo(40))
    arr = [1,2,3,4,5,6,7,8,9,10]
    key = 11
    print(binarySearch(arr, 0, len(arr) - 1, key))

if __name__ == "__main__":
    main()
```

```python
#(4) 快速排序(三路快速排序)
import random
def quickSort(arr, L, R):
    if L > R:
        return
    lt = L
    gt = R + 1
    idx = random.randint(0 , R - L) + L
    arr[L], arr[idx] = arr[idx], arr[L]
    V = arr[L]
    i = L + 1
    while i < gt:
        if arr[i] < V:
            arr[lt + 1], arr[i] = arr[i], arr[lt + 1]
            lt += 1
            i += 1
        elif arr[i] > V:
            gt -= 1
            arr[gt], arr[i] = arr[i], arr[gt]
        else:
            i += 1
    arr[L], arr[lt] = arr[lt], arr[L]
    # 递归处理左边
    quickSort(arr, L, lt - 1)
    # 递归处理右边
    quickSort(arr, gt, R)

def main():
    global count
    arr = [0] * 50
    for i in range(len(arr)):
        arr[i] = random.randint(0,1000)
    quickSort(arr, 0, len(arr) - 1)
    print(arr)

if __name__ == "__main__":
    main()
```

```python
"""
(5) 汉诺塔问题
前3个 X -> Z
    前2个 X -> Y
        前1个 X -> Z
        第2个 X -> Y
        前1个 Z -> Y
    第3个 X -> Z
    前2个 Y -> Z
        前1个 Y -> X
        第2个 Y -> Z
        前1个 X -> Z
"""
def hanoi(n, begin, mid, end):
    if n == 1:
        print(begin + " -> " + end)
    else:
        hanoi(n - 1, begin, end, mid)
        print(begin + " -> " + end)
        hanoi(n - 1, mid, begin, end)
def main():
    X = "X"
    Y = "Y"
    Z = "Z"
    hanoi(3, X, Y, Z)


if __name__ == "__main__":
    main()
```

```python
"""
(6) 全排列
"ABC"
ABC
ACB
BAC
BCA
CAB
CBA
"""
result = [] # set集合适用于去重复的操作
def permutation(arr, left, right):
    if left == right:
        s = ""
        for c in arr:
            s += c
        if s not in result:
            result.append(s)
    else:
        for i in range(left, right + 1):
            arr[i], arr[left] = arr[left], arr[i]
            permutation(arr, left + 1, right)
            arr[i], arr[left] = arr[left], arr[i]

def main():
    s = input()
    arr = list(s)
    permutation(arr, 0, len(arr) - 1)
    print(result)
if __name__ == "__main__":
    main()
```

## 函数编程练习

**Demo55**

```python
def rule01(password):
    return len(password) >= 8

def isAlpha(c):
    return 'a' <= c <= 'z' or 'A' <= c <= 'Z'

def isDigit(c):
    return '0' <= c <= '9'

def rule02(password):
    for c in password:
        if not (isAlpha(c) or isDigit(c)):
            return False
    return True

def rule03(password):
    count = 0
    for c in password:
        if isDigit(c):
            count += 1
    return count >= 2

def rule04(password):
    count = 0
    for c in password:
        if 'A' <= c <= 'Z':
            count += 1
    return count >= 2

if __name__ == "__main__":
    password = input()
    if rule01(password) and rule02(password) and rule03(password) and rule04(password):
        print("YES")
    else:
        print("No")
```

**Demo56**

```python
# 判断素数
def isSuShu(num):
    for n in range(2, num // 2 + 1):
        if num % n == 0:
            return False
    return True

# 判断回文
def isHuiWen(num):
    return num == reverse(num)

# 整数翻转
"""
123 % 10 = 3
12 % 10 = 2
1 % 10 = 1

0*10 + 3 = 3
3*10 + 2 = 32
32*10 + 1 = 321
"""
def reverse(num):
    revNum = 0
    while num != 0:
        revNum = revNum * 10 + num % 10
        num //= 10
    return revNum


if __name__ == "__main__":
    num = 2
    count = 0
    while count < 100:
        if isSuShu(num) and isHuiWen(num):
            print(num, end = " ")
            count += 1
            if count % 10 == 0:
                print()
        num += 1
```

**Demo68**

```python
import random
def createPath(length):
    path = ""
    for i in range(length):
        if random.randint(0,1) == 1:      # [0,1]
            path = path + "R"
        else:
            path += "L"
    return path

def countR(path):
    count = 0
    for c in path:
        if c == "R":
            count += 1
    return count

def main():
    arr = input().split(" ") # ["5", "8"]
    balls = int(arr[0]) # 球的个数
    slots = int(arr[1]) # 槽子的个数
    box = [0] * slots   # 槽子数组
    for i in range(balls):
        path = createPath(slots - 1)
        print(path)
        index = countR(path)
        box[index] += 1
    print(box)

if __name__ == "__main__":
    main()
```

**Demo72**

```python
import random
def createPasswd(word, state):
    passwd = ""
    for i in range(len(word)):
        if state[i]:
            passwd += "#"
        else:
            passwd += word[i]
    return passwd

def isGameOver(state):
    return True not in state

def isChangeState(state, word, ch):
    for i in range(len(word)):
        if word[i] == ch:
            if state[i]:
                state[i] = False
            else:
                return False
    return True

def main():
    # 单词组
    words = ["banana", "orange", "computer", "refrigerator", "program"]
    while True:
        # 明文单词
        word = words[random.randint(0, len(words) - 1)]
        # 单词的状态
        state = [True] * len(word)
        # 制作密文
        passwd = createPasswd(word, state)
        # 错误次数
        missed = 0
        while not isGameOver(state):
            ch = input("Enter a letter in word " + passwd + " >")
            if ch in word:
                if isChangeState(state, word, ch):
                    passwd = createPasswd(word, state)
                else:
                    print(ch + " is already in the word")
            else:
                missed += 1
                print(ch + " is not in the word")
        print(f"The word is {word}. You missed {missed} time")
        choice = input("是否继续? y/n >")
        if choice == "n":
            break

if __name__ == "__main__":
    main()
```

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值