Pergunta

Estou tentando usar o módulo Turtle em Python para desenhar a bandeira americana usando funções separadas, primeiro tenho draw_flag que calcula todas as dimensões, e depois draw_rectangle que realmente desenha o formato da bandeira, então farei draw_stars, etc, para desenhar o estrelas e linhas.

Mas estou tendo problemas para entender como as funções funcionam. Aqui está meu código até agora:

import turtle
import time
import random

def draw_rectangle(length, height):
    turtle.up()
    x = length
    y = height

    turtle.begin_fill()
    turtle.setpos(x,y)
    turtle.down()
    turtle.forward(418)
    turtle.right(90)
    turtle.forward(220)
    turtle.right(90)
    turtle.forward(418)
    turtle.right(90)
    turtle.forward(220)
    turtle.end_fill()

    turtle.sleep(2)
    turtle.bye

def draw_flag(A):
    height = int(A)
##    length = height*1.9
##    union_height = height*(7/13)
##    union_length = length*(2/5)
##    E = F = union_height/10
##    G = H = union_length/12
##    stripe_width = height/13
##    diameter_star = stripe_width*(4/5)
    length = height*1.9
    return

A = input("Please enter the height of the flag: ")

draw_rectangle(length, height)

Eu esperava que ele retornasse desenhando um retângulo, mas continua dizendo que o comprimento não está definido, não tenho certeza de onde colocar 'comprimento' onde reconhecerá a variável.

Estou usando Python 3, obrigado.

Foi útil?

Solução

Esta é uma boa maneira de pensar sobre isso.Uma função é uma “caixa preta” que recebe um certo número de valores, chamados argumentos, em uma ordem específica e faz algo com eles para produzir algum outro valor.Quando digo “caixa preta”, quero dizer que quando você usa a função, você não precisa se preocupar como ele faz o que faz, você apenas atribui alguns valores e recebe um valor de volta.

Vamos considerar uma função muito simples que apenas subtrai os dois números dados:o primeiro menos o segundo.Em outras palavras, faremos uma função que implementa a regra "Argumento nº 1 - argumento nº 2". Agora, quando você está escrevendo o código para esta função, precisa de uma maneira de dizer ao computador quando deseja usar o argumento nº 1 e quando deseja usar o argumento nº 2.Em algumas outras linguagens de programação, você precisa fazer isso especificando explicitamente o número do argumento que deseja usar (#1 ou #2), mas é muito mais fácil escrever código se você puder dar nomes a esses valores.Portanto, Python, como a maioria das outras linguagens, permite referir-se aos argumentos de uma função usando nomes de sua escolha.Por exemplo, suponha que você queira que o argumento nº 1 fique sob o nome x, e o argumento nº 2 sob o nome y.Você poderia indicar isso escrevendo isto:

def subtract(x, y):

Isso seria seguido pelo código que constitui a função.Para o exemplo da subtração, seria

def subtract(x, y):
    return x - y

Quando o compilador Python encontra isso, ele traduz o código em sua representação interna de "Calcule o valor nº 1 - valor nº 2 e envie -o de volta ao meu chamador". Em seguida, ele empacota esse bloco de código e o salva sob o nome subtract (porque foi isso que você disse que queria nomear a função).

Esperamos que faça sentido que, uma vez que esse bloco de código termine de ser executado, não faça mais sentido referir-se ao "argumento nº 1" ou ao "argumento nº 2", porque você não pode ter argumentos sem uma função!Da mesma forma, uma vez que a função tenha feito seu trabalho, os rótulos que você deu aos argumentos, x e y, não têm mais nenhum significado.Os rótulos existem apenas enquanto durar o código da função.Isso é chamado escopo:limitar os rótulos à parte do código onde eles significam alguma coisa.

Porque os rótulos x e y são escopo local, como se poderia dizer, de certa forma nem importa o que sejam.Por exemplo, se você tivesse essa definição de subtract em seu código, você pode decidir arbitrariamente alterá-los para first e second, e tudo o que você precisaria alterar seria o código dessa função.Você apenas mudaria a definição para

def subtract(first, second):
    return first - second

e é isso - seu código é funcionalmente exatamente o mesmo.Em qualquer outro lugar do programa que x e y ocorrer, eles estão se referindo a algo diferente dos argumentos desta função, então você não precisa alterá-los ao renomear os argumentos.

O que está acontecendo no seu caso é que você tentou usar o rótulo length em algum lugar fora da função para a qual foi definida (ou seja, a função que você armazenou como draw_rectangle).Python sabe que você não pode estar se referindo ao argumento de uma função na qual você não está, então ele espera que você já tenha definido length para significar outra coisa.Mas você não fez isso.É por isso que você está recebendo um erro.(Bem, esse erro, de qualquer maneira)

Outras dicas

Você tem dois problemas.Primeiro, você define a função draw_flag mas você nunca liga para isso.

No entanto, se você chamasse, não funcionaria, porque sua função draw_flag realmente não faz nada.Ele apenas define algumas variáveis ​​dentro de si e depois as joga fora quando termina.Você deve retornar o comprimento e a altura com return length, height, então faça length, height = draw_flag(A) e ligue draw_rectangle com esses valores.(Ou você poderia fazer draw_rectangle(*draw_flag(A)).)

length, height = draw_flag(A)
draw_rectangle(length, height)

As funções não se comunicam magicamente umas com as outras.Uma função recebe entradas e produz um valor de retorno.Se quiser usar esse valor de retorno em outro lugar, você precisará chamar a função no local onde deseja usar o valor.

Você está chamando a função draw_rectangle, que espera dois argumentos - um comprimento e uma altura.O comprimento está sendo calculado pelo draw_flag função;mas você não retorna o valor.

Você tem algumas maneiras de resolver isso.Uma delas é simplesmente ligar para o draw_flag função com a altura fornecida pelo usuário, salve o valor de retorno e chame draw_rectangle:

def draw_flag(A):
    height = int(A)
##    length = height*1.9
##    union_height = height*(7/13)
##    union_length = length*(2/5)
##    E = F = union_height/10
##    G = H = union_length/12
##    stripe_width = height/13
##    diameter_star = stripe_width*(4/5)
    return height*1.9

A = input("Please enter the height of the flag: ")
length = draw_flag(A)
draw_rectangle(length, int(A))

A outra é mover seu input para o draw_flag função e, em seguida, chame o draw_rectangle funcionar de dentro do draw_flag função.Se você fizer isso, então o draw_flag função não precisa de nenhum argumento:

def draw_flag():
    A = input("Please enter the height of the flag: ")
    height = int(A)
##    length = height*1.9
##    union_height = height*(7/13)
##    union_length = length*(2/5)
##    E = F = union_height/10
##    G = H = union_length/12
##    stripe_width = height/13
##    diameter_star = stripe_width*(4/5)
    draw_rectangle(height*1.9, height)

draw_flag()

Acho que você também deveria consultar a seção do seu livro Python sobre escopos de variáveis.Isso ajudará mais tarde, quando você espera que algumas variáveis ​​sejam impressas, mas recebe erros estranhos - especialmente se estiver usando funções.

Tente o seguinte

import turtle
import time
import random

def draw_rectangle(length, height):
   turtle.up()
   x = length
   y = height

   turtle.begin_fill()
   turtle.setpos(x,y)
   turtle.down()
   turtle.forward(418)
   turtle.right(90)
   turtle.forward(220)
   turtle.right(90)
   turtle.forward(418)
   turtle.right(90)
   turtle.forward(220)
   turtle.end_fill()

   turtle.sleep(2)
   turtle.bye

 def draw_flag(A):
   height = int(A)
   length = height*1.9
   draw_rectangle(length,height)
   return

A = input("Please enter the height of the flag: ")

draw_flag(A)

Ok, então para responder sua pergunta mais geral, funções em python aceitam argumentos quando você os chama, eles são passados ​​por referência, o que significa que você acaba com os mesmos dados dentro da função e no espaço de chamada.Isso é importante para tipos mutáveis, porque se eles forem alterados dentro da função, também serão alterados fora da função.(str, int, float e tuple não são mutáveis, dict e list são).Quando uma função retorna, o valor após o token de retorno é passado de volta ao chamador, então se você disser a=input('input? '), a entrada da função recebe um argumento para o prompt ser exibido ao usuário. Observe que isso é passado por referência, não é uma cópia da string.Ele retorna a entrada gerada pelo usuário, que é armazenada em a.Você pode retornar vários valores de uma função, eles são convertidos automaticamente em uma tupla;se você tem

def test():
    return 1,2
a,b = test()

Você obterá a = 1 e b = 2.Os nomes usados ​​dentro de uma função devem ser definidos.Eles são procurados primeiro dentro da função, depois em quaisquer namespaces anexos e, finalmente, em componentes internos.Variáveis ​​definidas em outras funções não podem ser usadas porque não estão no namespace local nem em nenhum de seus pais.Para acessar os valores desses nomes, você deve passá-los para a função, observe que os nomes usados ​​dentro da função não precisam corresponder aos nomes fora da função.Considerar:

def fun1(a):
    return a * 2
def fun2():
    b = 5
    c = fun1(b)
    print c
fun2()

O valor 5 é armazenado na memória com o nome b, depois passado por referência para fun1, desta vez com o nome a, é duplicado e retornado (o retorno também é por referência), o valor de retorno é então armazenado sob o nome c, que é então impresso.

return retorna tudo o que você devolve ao chamador.Isso acontece não disponibilizar automaticamente as variáveis ​​locais dentro da função externamente (estas são local por uma razão!).Observe também que return sem nenhum argumento retornará o valor especial None (então é equivalente a return None).

Então, se você quiser retornar alguns valores, use return height, length dentro da função e height, length = draw_flag(A) fora.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top