Capítulo 6: Usando Funções e Módulos

Capítulo 6: Usando Funções e Módulos

Consulte os artigos anteriores:
Capítulo 1: Python inicial
Capítulo 2: Elementos da linguagem
Capítulo 3: Estrutura de ramificação
Capítulo 4: Estrutura de loop
Capítulo 5: Construindo a lógica do programa
Ou vá para a coluna "Tutorial Python" para visualizar


Diretório de recursos: Código (6)
Download de recursos do artigo: (1-15 capítulos)
Link: https://pan.baidu.com/s/1Mh1knjT4Wwt__7A9eqHmng?pwd=t2j3
Código de extração: t2j3

Antes de explicar o conteúdo deste capítulo, vamos primeiro estudar um problema matemático. Por favor, diga quantos conjuntos de soluções inteiras positivas a seguinte equação tem.

insira a descrição da imagem aqui

Na verdade, o problema acima é equivalente a quantas maneiras existem de dividir 8 maçãs em quatro grupos com pelo menos uma maçã em cada grupo. A resposta a esta pergunta é iminente.

insira a descrição da imagem aqui

Este valor pode ser calculado com um programa Python, o código é o seguinte.

"""
输入M和N计算C(M,N)

Version: 0.1
Author: 骆昊
"""
m = int(input('m = '))
n = int(input('n = '))
fm = 1
for num in range(1, m + 1):
    fm *= num
fn = 1
for num in range(1, n + 1):
    fn *= num
fm_n = 1
for num in range(1, m - n + 1):
    fm_n *= num
print(fm // fn // fm_n)

O que a função faz

Não sei se você percebeu que no código acima, fizemos 3 vezes para achar o fatorial, tal código na verdade é um código repetido. O mestre de programação Sr. Martin Fowler disse uma vez: " O código tem muitos cheiros ruins, e a repetição é o pior! " Para escrever código de alta qualidade, a primeira coisa a resolver é o problema do código repetido. Para o código acima, podemos encapsular a função de cálculo fatorial em um módulo de função chamado "função". Onde precisamos calcular fatorial, precisamos apenas "chamar" essa "função".

definir função

Em Python, defpalavras-chave podem ser usadas para definir funções.Assim como as variáveis, cada função também tem um nome famoso e as regras de nomenclatura são consistentes com as regras de nomenclatura das variáveis. Os parâmetros passados ​​para a função podem ser colocados entre parênteses após o nome da função, que é muito semelhante à função em matemática. Os parâmetros da função no programa são equivalentes aos argumentos da função em matemática, e após a função é executado, podemos retornar um valor através returnda palavra-chave, que é equivalente à variável dependente da função em matemática.

Depois de entender como definir funções, podemos refatorar o código acima. A chamada refatoração é ajustar a estrutura do código sem afetar os resultados da execução do código. O código refatorado é o seguinte.

"""
输入M和N计算C(M,N)

Version: 0.1
Author: 骆昊
"""
def fac(num):
    """求阶乘"""
    result = 1
    for n in range(1, num + 1):
        result *= n
    return result


m = int(input('m = '))
n = int(input('n = '))
# 当需要计算阶乘的时候不用再写循环求阶乘而是直接调用已经定义好的函数
print(fac(m) // fac(n) // fac(m - n))

Explicação:math Na verdade, já existe uma função chamada function no módulo Python factorialque implementa a operação fatorial. Na verdade, você não precisa definir a função para calcular o fatorial. No exemplo a seguir, as funções das quais estamos falando já foram implementadas na biblioteca padrão do Python. Vamos implementá-las novamente aqui para explicar a definição e o uso das funções. No desenvolvimento real, não é recomendável fazer essas repetições de baixo nível trabalho .

parâmetros de função

Uma função é um "bloco de construção" de código suportado pela maioria das linguagens de programação, mas ainda existem muitas diferenças entre funções em Python e funções em outras linguagens. No Python, os parâmetros das funções podem ter valores padrão, e também suportam o uso de parâmetros variáveis, então o Python não precisa suportar sobrecarga de função como outras linguagens , pois quando definimos uma função, podemos fazer com que ela tenha muitos métodos diferentes uso, a seguir estão dois pequenos exemplos.

from random import randint


def roll_dice(n=2):
    """摇色子"""
    total = 0
    for _ in range(n):
        total += randint(1, 6)
    return total


def add(a=0, b=0, c=0):
    """三个数相加"""
    return a + b + c


# 如果没有指定参数那么使用默认值摇两颗色子
print(roll_dice())
# 摇三颗色子
print(roll_dice(3))
print(add())
print(add(1))
print(add(1, 2))
print(add(1, 2, 3))
# 传递参数时可以不按照设定的顺序进行传递
print(add(c=50, a=100, b=200))

Definimos valores padrão para os parâmetros das duas funções acima, o que significa que, se o valor do parâmetro correspondente não for passado ao chamar a função, o valor padrão do parâmetro será usado, portanto, no código acima As funções podem ser chamadas de várias maneiras add, o que é consistente com o efeito de sobrecarga de funções em muitas outras linguagens.

Na verdade, há uma implementação melhor da addfunção acima, porque podemos adicionar 0 ou mais parâmetros, e o número específico de parâmetros é determinado pelo chamador. Como projetista da função, não sabemos nada, portanto, quando o número de parâmetros é incerto, podemos usar parâmetros variáveis, o código é o seguinte.

# 在参数名前面的*表示args是一个可变参数
def add(*args):
    total = 0
    for val in args:
        total += val
    return total


# 在调用add函数时可以传入0个或多个参数
print(add())
print(add(1))
print(add(1, 2))
print(add(1, 2, 3))
print(add(1, 3, 5, 7, 9))

Gerenciar funções com módulos

Para qualquer linguagem de programação, nomear identificadores como variáveis ​​e funções é uma dor de cabeça, porque encontraremos a situação embaraçosa de conflitos de nomes. O cenário mais simples é definir duas funções com o mesmo nome no mesmo arquivo .py. Como o Python não possui o conceito de sobrecarga de função, a última definição substituirá a definição anterior, o que significa que duas funções com o mesmo nome são, na verdade, apenas Um existe.

def foo():
    print('hello, world!')


def foo():
    print('goodbye, world!')


# 下面的代码会输出什么呢?
foo()

Claro, podemos facilmente evitar a situação acima, mas se o projeto for desenvolvido por uma equipe de várias pessoas, pode haver vários programadores na equipe que definiram a função nomeada, então como resolver esse conflito de nomenclatura Tecido de lã foo? A resposta é realmente muito simples. Cada arquivo em Python representa um módulo. Podemos ter funções com o mesmo nome em diferentes módulos. Ao usar uma função, podemos importar o módulo especificado por palavra-chave para distinguir entre os módulos a serem usados. importQual module é fooa função in, o código é o seguinte.

module1.py

def foo():
    print('hello, world!')

module2.py

def foo():
    print('goodbye, world!')

test.py

from module1 import foo

# 输出hello, world!
foo()

from module2 import foo

# 输出goodbye, world!
foo()

Você também pode distinguir qual foofunção usar conforme mostrado abaixo.

test.py

import module1 as m1
import module2 as m2

m1.foo()
m2.foo()

Mas se o código for escrito da seguinte maneira, o último importado será chamado no programa foo, porque o foo importado posteriormente substituirá o importado anterior foo.

test.py

from module1 import foo
from module2 import foo

# 输出goodbye, world!
foo()

test.py

from module2 import foo
from module1 import foo

# 输出hello, world!
foo()

Deve-se observar que se o módulo que importamos tiver código executável além de definir funções, o interpretador Python executará esses códigos ao importar este módulo. Na verdade, podemos não querer isso, portanto, se estivermos no módulo A execução código é escrito em , é melhor colocar esses códigos de execução nas condições mostradas abaixo, de modo que, a menos que o módulo seja executado diretamente, o código sob a condição if não será executado, porque apenas o nome do módulo executado diretamente é "__principal__".

module3.py

def foo():
    pass


def bar():
    pass


# __name__是Python中一个隐含的变量它代表了模块的名字
# 只有被Python解释器直接执行的模块的名字才是__main__
if __name__ == '__main__':
    print('call foo()')
    foo()
    print('call bar()')
    bar()

test.py

import module3

# 导入module3时 不会执行模块中if条件成立时的代码 因为模块的名字是module3而不是__main__

prática

Exercício 1: Realize a função de cálculo do máximo divisor comum e mínimo múltiplo comum.

Resposta de referência:

def gcd(x, y):
    """求最大公约数"""
    (x, y) = (y, x) if x > y else (x, y)
    for factor in range(x, 0, -1):
        if x % factor == 0 and y % factor == 0:
            return factor


def lcm(x, y):
    """求最小公倍数"""
    return x * y // gcd(x, y)

Exercício 2: Realizar a função de julgar se um número é um palíndromo.

Resposta de referência:

def is_palindrome(num):
    """判断一个数是不是回文数"""
    temp = num
    total = 0
    while temp > 0:
        total = total * 10 + temp % 10
        temp //= 10
    return total == num

Exercício 3: Implemente uma função para julgar se um número é primo ou não.

Resposta de referência:

def is_prime(num):
    """判断一个数是不是素数"""
    for factor in range(2, int(num ** 0.5) + 1):
        if num % factor == 0:
            return False
    return True if num != 1 else False

Exercício 4: Escreva um programa para julgar se o inteiro positivo de entrada é um número primo palíndromo.

Resposta de referência:

if __name__ == '__main__':
    num = int(input('请输入正整数: '))
    if is_palindrome(num) and is_prime(num):
        print('%d是回文素数' % num)

Observação : como pode ser visto no programa acima, quando extraímos funções recorrentes e relativamente independentes no código para funções , podemos usar essas funções em combinação para resolver problemas mais complexos, e é por isso que definimos e usamos função para uma função muito importante razão.

escopo variável

Finalmente, vamos discutir o escopo das variáveis ​​em Python.

def foo():
    b = 'hello'

    # Python中可以在函数内部再定义函数
    def bar():
        c = True
        print(a)
        print(b)
        print(c)

    bar()
    # print(c)  # NameError: name 'c' is not defined


if __name__ == '__main__':
    a = 100
    # print(b)  # NameError: name 'b' is not defined
    foo()

O código acima pode ser executado sem problemas e imprimir 100, hello e True, mas notamos que não há duas variáveis bar​​definidas dentro da função , então de onde vem a soma. Definimos uma variável no branch do código acima , que é uma variável global (variável global) e pertence ao escopo global porque não é definida em nenhuma função. Na função acima, definimos uma variável , que é uma variável local (local variables) definida na função, que pertence ao escopo local e não pode ser acessada fora da função; mas para a função dentro da função , a variável pertence ao escopo aninhado e podemos acessá-lo na função. Variáveis ​​em funções pertencem ao escopo local e não podem ser acessadas fora da função. Na verdade, quando o Python procura por uma variável, ele buscará na ordem de "escopo local", "escopo aninhado", "escopo global" e "escopo interno". Os três primeiros vimos no código acima Chegaram , o chamado "escopo embutido" são os identificadores embutidos do Python, usamos antes , ,, etc. pertencem ao escopo embutido.ababifafoobfoofoobarbbarbarcbarinputprintint

Observe o código a seguir novamente, esperamos modificar ao valor da variável global por meio de uma chamada de função, mas na verdade o código a seguir não pode ser feito.

def foo():
    a = 200
    print(a)  # 200


if __name__ == '__main__':
    a = 100
    foo()
    print(a)  # 100

Após chamar fooa função, ao valor que encontramos ainda é 100. Isso porque quando escrevemos foona função a = 200, redefinimos uma variável local chamada , que não é a mesma variável ado escopo global , portanto, a função não pesquisa mais o escopo global . Se quisermos modificar o escopo global na função , o código é o seguinte.aafooafooa

def foo():
    global a
    a = 200
    print(a)  # 200


if __name__ == '__main__':
    a = 100
    foo()
    print(a)  # 200

Podemos usar globalpalavras-chave para indicar que fooas variáveis ​​na função avêm do escopo global.Se não houver escopo global a, a seguinte linha de código definirá a variável ae a colocará no escopo global. Da mesma forma, se quisermos que a função dentro da função seja capaz de modificar variáveis ​​no escopo aninhado, podemos usar nonlocalpalavras-chave para indicar que a variável vem do escopo aninhado, tente você mesmo.

No desenvolvimento real, devemos minimizar o uso de variáveis ​​globais, porque o escopo e a influência das variáveis ​​globais são muito amplos e podem ocorrer modificações e usos inesperados. Além disso, as variáveis ​​globais têm uma vida útil mais longa do que as variáveis ​​locais. O ciclo de vida pode fazer com que a memória ocupada pelo objeto não possa ser coletada por muito tempo . De fato, reduzir o uso de variáveis ​​globais também é uma medida importante para diminuir o acoplamento entre os códigos, sendo também uma prática da lei de Dimiter . Reduzir o uso de variáveis ​​globais significa que devemos tentar manter o escopo das variáveis ​​dentro da função, mas se quisermos estender o ciclo de vida de uma variável local para que seu valor ainda possa ser usado após o término da chamada da função que a define , você precisa usar encerramentos neste momento , o que explicaremos no conteúdo de acompanhamento.

Explicação: Muitas pessoas costumam confundir "fechamento" e "função anônima" , mas na verdade não são a mesma coisa. Se você quiser entender esse conceito, pode ler a explicação da Wikipedia ou a discussão de Zhihu sobre esse conceito .

Dito isso, a conclusão é realmente muito simples. A partir de agora, podemos escrever o código Python de acordo com o seguinte formato. Essa pequena melhoria é, na verdade, um grande passo com base em nossa compreensão de funções e escopo.

def main():
    # Todo: Add your code here
    pass


if __name__ == '__main__':
    main()

Acho que você gosta

Origin blog.csdn.net/xyx2023/article/details/129635113
Recomendado
Clasificación