简体   繁体   English

了解Python中的函数

[英]Understanding Functions in Python

I'm trying to use the Turtle module in Python to draw the American flag using separate functions, first I have draw_flag which calculates all the dimensions, and then draw_rectangle which actually draws the flag shape, then ill make draw_stars, etc, to draw the stars and lines. 我正在尝试在Python中使用Turtle模块使用单独的函数绘制美国国旗,首先我使用draw_flag计算所有尺寸,然后使用draw_rectangle实际绘制国旗形状,然后生出draw_stars等,以绘制星星和线条。

But, I am having a bit of trouble understanding on how functions work..here is my code so far: 但是,我在理解函数的工作方式时遇到了一些麻烦。到目前为止,这是我的代码:

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)

I was hoping it would return by drawing a rectangle, but it keeps saying length is not defined, not sure where to place 'length' where it will recognize the variable. 我希望它会通过绘制一个矩形而返回,但是它一直说未定义长度,不确定是否将“长度”放在可以识别变量的位置。

I'm using Python 3, thanks. 我使用的是Python 3,谢谢。

You have two problems. 你有两个问题。 First, you define the function draw_flag but you don't ever call it. 首先,您定义了函数draw_flag但是您从未调用过它。

However, if you did call it, it wouldn't work, because your function draw_flag doesn't really do anything. 但是,如果您确实调用了它,它将无法正常工作,因为您的函数draw_flag并没有执行任何操作。 It just defines some variables inside itself and then throws them away when it ends. 它只是在内部定义一些变量,然后在结束时将其丢弃。 You should return the length and height with return length, height , then do length, height = draw_flag(A) and call draw_rectangle with those values. 您应该返回长度和高度,并return length, height ,然后执行length, height = draw_flag(A)并使用这些值调用draw_rectangle (Or you could do draw_rectangle(*draw_flag(A)) .) (或者您可以执行draw_rectangle(*draw_flag(A)) 。)

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

Functions don't magically communicate with one another. 函数之间无法神奇地通信。 A function takes inputs and produces a return value. 一个函数接受输入并产生一个返回值。 If you want to use that return value somewhere else, you need to call the function at the place where you want to use the value. 如果要在其他地方使用该返回值,则需要在要使用该值的位置调用该函数。

You are calling the function draw_rectangle , which expects two arguments - a length and a height. 您正在调用函数draw_rectangle ,它需要两个参数-长度和高度。 The length is being calculated by the draw_flag function; 长度是由draw_flag函数计算的; but you don't return the value. 但您不返回该值。

You have a few ways of solving this. 您有几种解决方法。 One is to simply call the draw_flag function with the user supplied height, save the return value, and then call draw_rectangle : 一种是简单地使用用户提供的高度调用draw_flag函数,保存返回值,然后调用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))

The other is to move your input to the draw_flag function, and then call the draw_rectangle function from inside the draw_flag function. 另一种是将input移至draw_flag函数,然后从draw_rectangle函数内部调用draw_flag函数。 If you do this, then the draw_flag function doesn't need any arguments at all: 如果执行此操作,那么draw_flag函数根本不需要任何参数:

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()

I think you should also go through your Python book's section on variable scopes. 我认为您还应该阅读Python书籍中有关可变范围的部分。 It will help later on when you expect some variables to print but you get strange errors - especially if you are using functions. 当您期望打印一些变量但遇到奇怪的错误时,它将在以后有所帮助-特别是在使用函数的情况下。

Try the following 尝试以下

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)

Okay, so to answer your more general question, functions in python accept arguments when you call them, these are passed by reference, which means that you end up with the same data inside the function as in the calling space. 好的,为了回答更笼统的问题,python中的函数在调用它们时会接受参数,这些参数是通过引用传递的,这意味着您最终在函数内部获得的数据与调用空间中的数据相同。 This is important for mutable types, because if they are changed inside the function, they are changed outside the function too. 这对于可变类型很重要,因为如果在函数内部更改它们,那么它们也会在函数外部更改。 (str, int, float and tuple are not mutable, dict and list are). (str,int,float和tuple不可变,dict和list可变)。 When a function returns, the value after the return token is passed back to the caller, so if you say a=input('input? ') , the function input takes an argument for the prompt to display to the user, note this is passed in by reference, it is not a copy of the string. 当函数返回时,返回令牌之后的值将被传递回调用者,因此,如果您说a=input('input? ') ,则函数输入将带有一个参数以使提示显示给用户,请注意,这是通过引用传递,它不是字符串的副本。 It returns the user generated input, which gets stored into a. 它返回用户生成的输入,并将其存储到中。 You can return multiple values from a function, they are converted automatically to a tuple; 您可以从一个函数返回多个值,它们会自动转换为元组; if you have 如果你有

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

You will get a=1 and b=2. 您将得到a = 1和b = 2。 Names used inside a function must be defined. 必须定义函数内部使用的名称。 They are first sought inside the function, then in any enclosing namespaces, finally in builtins. 首先在函数内部查找它们,然后在任何封闭的名称空间中查找它们,最后在内置函数中查找它们。 Variables defined in other functions cannot be used, because they are not in the local namespace nor any of its parents. 无法使用其他函数中定义的变量,因为它们既不在本地名称空间中,也不在其任何父级中。 To access the values of these names, you have to pass them in to the function, note that the names used inside the function don't have to match the names outside the function. 要访问这些名称的值,必须将它们传递给函数,请注意,函数内部使用的名称不必与函数外部的名称匹配。 Consider: 考虑:

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

The value 5 is stored in memory under the name b, then passed by reference into fun1, this time under the name a, it is doubled and returned, (the return is also by reference), the return value is then stored under the name c, which is then printed. 值5以名称b存储在内存中,然后通过引用传递到fun1中,这次以名称a进行了两次加倍并返回(返回也通过引用),然后将返回值存储在名称下c,然后打印。

Here's a good way to think about it. 这是一种思考的好方法。 A function is a "black box" that takes in some number of values, called arguments , in a specific order and does something with them to produce some other value. 函数是一个“黑匣子”,它以特定顺序接收一定数量的值(称为arguments) ,并对它们执行某些操作以产生其他值。 When I say "black box," I mean that when you use the function, you don't have to care how it does what it does, you just give it some values and you get a value back. 当我说“黑盒子”,我的意思是,当你使用的功能,你不必去关心它是如何做它做什么,你只要给它一些值,你会得到一个值返回。

Let's consider a very simple function that just subtracts the two numbers it's given: the first minus the second. 让我们考虑一个非常简单的函数,该函数只减去给出的两个数字:第一个减去第二个。 In other words, we'll make a function that implements the rule "argument #1 - argument #2." 换句话说,我们将创建一个实现规则“参数1-参数2”的函数。 Now, when you're writing the code for this function, you need some way to tell the computer when you want to use argument #1 and when you want to use argument #2. 现在,当您为该函数编写代码时,需要某种方式告诉计算机何时要使用参数#1和何时要使用参数#2。 In some other programming languages, you have to do it by explicitly specifying the number of the argument you want to use (#1 or #2), but it's a lot easier to write code if you can give these values names. 在其他一些编程语言中,您必须通过显式指定要使用的参数的编号(#1或#2)来实现,但是如果可以给这些值命名,则编写代码要容易得多。 So Python, like most other languages, lets you refer to the arguments of a function using names of your choosing. 因此,Python与大多数其他语言一样,使您可以使用所选名称来引用函数的参数。 For example, suppose you want argument #1 to go under the name x , and argument #2 to go under the name y . 例如,假设您希望参数#1在名称x ,而参数#2在名称y You could indicate that by writing this: 您可以这样写来表明:

def subtract(x, y):

This would be followed by the code that constitutes the function. 然后是构成函数的代码。 For the subtraction example, it would be 对于减法示例,它将是

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

When the Python compiler encounters this, it translates the code into its internal representation of "calculate value #1 - value #2 and send that back to my caller." 当Python编译器遇到此问题时,它将代码转换为其内部表示形式“计算值#1-值#2并将其发送回我的调用者”。 It then packs up that block of code and saves it under the name subtract (because that's what you told it you wanted to name the function). 然后,它打包该代码块,并将其保存为“ subtract (因为这就是您告诉您要命名该函数的名称)。

Hopefully it makes sense that once this block of code finishes executing, it no longer makes any sense to refer to "argument #1" or "argument #2," because you can't have arguments without a function! 希望有意义的是,一旦该代码块执行完毕,再也不用引用“ argument#1”或“ argument#2”,因为没有函数就不能有参数! So similarly, once the function has done its thing, the labels that you gave to the arguments, x and y , no longer have any meaning. 同样,一旦函数完成其工作,则给参数xy赋予的标签将不再具有任何意义。 The labels only exist for the duration of the function's code. 标签仅在功能代码期间存在。 This is called scoping : limiting labels to the part of the code where they mean something. 这称为作用域 :将标签限制在代码中有意义的部分。

Because the labels x and y are locally scoped , as one might say, in a way it doesn't even matter what they are. 正如标签xy可能是局部作用域一样 ,正如人们可能会说的那样,它们甚至是什么都不重要。 For instance, if you had that definition of subtract in your code, you could arbitrarily decide to change them to first and second , and all you would have to change would be the code within that one function. 例如,如果您在代码中具有subtract定义,则可以任意决定将它们更改为firstsecond ,而您只需要更改该函数内的代码即可。 You would just change the definition to 您只需将定义更改为

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

and that's it - your code is functionally exactly the same. 就是这样-您的代码在功能上完全相同。 Anywhere else in the program that x and y occur, they're referring to something other than the arguments of this function, so you don't have to change them when you rename the arguments. 在程序中任何其他发生xy ,它们都引用了该函数的参数以外的其他东西,因此在重命名参数时不必更改它们。

What's happening in your case is that you tried to use the label length somewhere outside of the function it was defined for (namely, the function that you've stored as draw_rectangle ). 在您的情况下,您试图在标签length所定义的函数之外的地方使用标签length (即,已存储为draw_rectangle的函数)。 Python knows that you can't be referring to the argument of a function you're not in, so it expects you to have already defined length to mean something else. Python知道您不能引用您不在的函数的参数,因此它希望您已经定义了length来表示其他含义。 But you didn't. 但是你没有。 That's why you're getting an error. 这就是为什么您会遇到错误。 (Well, that one error, anyway) (好吧,还是有一个错误)

return returns whatever you give it back to the caller. return将您返回给调用者的所有内容返回。 It does not automatically make the local variables inside the function available outside (these are local for a reason!). 不会自动使可用的功能外内局部变量(这些地方是有原因的!)。 Note too that return without any arguments will return the special value None (so it's equivalent to return None ). 还要注意, return不带任何参数将返回特殊值None (所以它等同于return None )。

So, if you want to return some values, use return height, length inside the function, and height, length = draw_flag(A) outside. 因此,如果要返回一些值,请使用return height, length函数内部的return height, length以及外部height, length = draw_flag(A)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM