【问题标题】:Learn Python the Hard way ex25 - Want to check my understandingLearn Python the Hard way ex25 - 想检查我的理解
【发布时间】:2016-10-19 16:06:40
【问题描述】:

这里的所有菜鸟都对“艰难地学习 Python”中的某些内容感到困惑。抱歉,如果这已被涵盖;我搜索并只能找到有关未从代码中获得所需结果的帖子。

我的问题与exercise 25中两个函数的交互有关:

def break_words(stuff):
    words = stuff.split(' ')
    return words

def sort_sentence(sentence):
    words = break_words(sentence)
    return sort_words(words)

所以,在练习快结束时,Zed 让你在终端中运行这个:

>>> sorted_words = ex25.sort_sentence(sentence)
>>> sorted_words
['All', 'come', ’good’, ’things’, ’those’, ’to’, ’wait.’, ’who’]

现在我假设“sort_sentence”中的参数来自以下内容,在练习开始时在终端中输入:

>>> sentence = "All good things come to those who wait."

虽然我们现在知道上面是'sort_sentence'的参数,'sort_sentence'如果不运行'break_words'就无法完成,'sentence'再次作为它的参数。这就是我感到困惑的地方:“break_words”的参数被标记为“stuff”。这有关系吗?无论 'break_words' 的参数是什么标签,'sentence' 都可以从 'sorted_words' 传递到 'break_words' 吗?

所以假设我假设-参数标签无关紧要-'break_words'应该以'sentence'作为参数运行并返回'words',这是包含的函数'stuff.split'的输出其中。这就是我真正感到困惑的地方 - 从“break_words”返回的“words”与定义为“sort_sentence”一部分的变量“words”有什么关系?我根本无法弄清楚这些功能是如何协同工作的。提前感谢您的帮助!

【问题讨论】:

  • 您指定的参数将映射到函数使用的参数。因此,在类似def break_words(stuff) 的情况下,您传递给它的任何参数都会在方法主体中以stuff 的形式可见。这里的行话可能太多了,但是 Python 教程部分 Defining Functions describes it better.
  • "从break_words 返回的words 与定义为sort_sentence 一部分的变量'words' 有什么关系?"基本上,什么都没有。 sort_sentence 中的 words 独立于 break_words 中的 words。每个函数都有自己的作用域:在sort_sentence 内部,words 指的是调用break_words(sentence)返回 的任何,但不依赖于任何break_words 中使用的变量名。我想它是为了让你迷惑。

标签: python


【解决方案1】:

Python 函数或多或少的工作方式如下:

def function_name(parameter_name_used_locally_within_function_name):
    #do stuff with parameter_name_used_locally_within_function_name

    some_new_value = parameter_name_used_locally_within_function_name
    return some_new_value

请注意参数仅在函数function_name 的范围内。因为该变量只会在该函数中使用,而不是在它之外。当我们从函数返回一个变量时,我们可以将它分配给另一个调用该函数的变量:

my_variable = function_name("hello")

my_variable 现在有 "hello" 作为它的值,因为我们调用了函数,传入值 "hello"。注意我没有用指定的变量名调用函数?我们不关心参数名称是什么,我们只知道函数需要一个输入。该参数名称仅在函数中使用。请注意我们在调用函数时如何在不知道该变量名称的情况下接收到 some_new_value 的值?

让我举一个更广泛的例子来说明正在发生的事情。函数可以被认为是你交给某人去做的任务。可以说功能或任务是他们为我们做饭。厨师或任务需要食材来烹饪(这是我们的输入),我们希望取回食物(我们的输出返回)。假设我想要一个煎蛋,我知道我必须给厨师鸡蛋才能让我做一个,我不在乎他是怎么做的或者他对它做了什么,只要我能拿回我的输出/煎蛋。他可以随心所欲地叫鸡蛋,他可以把鸡蛋打碎,他可以随心所欲地在锅里煎,但只要我得到我的煎蛋,我就很开心。

回到我们的编程世界,函数应该是这样的:

def cook_me_something(ingredients):
    #I don't know how the chef makes things for us nor do I care
    if ingredients == "eggs":
        food = "omelette"
    elif ingredients == "water":
        food = "boiled water"
    return food

我们这样称呼它:

my_food_to_eat = cook_me_something("eggs")

请注意,我给了他“鸡蛋”,我得到了一些“煎蛋”。我没有说鸡蛋是配料,也不知道他给我的食物叫什么。他只是返回包含omelettesfood

现在让我们一起讨论链接函数。

所以我们得到了关于我给厨师一些东西的基本信息,他根据我给他的东西给我食物。那么如果我们给他一些他需要在烹饪之前处理的东西呢?假设他不知道如何研磨咖啡豆怎么办。但他的副厨师长也知道怎么做。他会把咖啡豆递给那个人,把咖啡豆磨碎,然后用返回过程做饭。

def cook_me_something(ingredients):
    #I don't know how the chef makes things for us nor do I care
    if ingredients == "eggs":
        food = "omelette"
    elif ingredients == "water":
        food = "boiled water"
    elif ingredients == "coffee beans"
        co_worker_finished_product = help_me_co_worker(ingredients)
        #makes coffee with the co_worker_finished_product which would be coffee grindings
        food = "coffee"
    return food

#we have to define that function of the co worker helping:

help_me_co_worker(chef_passed_ingredients):
    if chef_passed_ingredients == "coffee beans"
        ingredients = "coffee grinding"
    return ingredients

注意到同事如何有一个局部变量ingredients?它与厨师的不同,因为厨师有自己的食材,而同事有自己的食材。请注意厨师如何不在乎同事如何称呼他的食材或他如何处理这些物品。厨师给了同事一些东西,并期待成品。

它或多或少是这样工作的。只要函数得到它们的输入,它们就会工作并可能给出输出。我们不在乎他们在函数中如何称呼他们的变量,因为这是他们自己的项目。

让我们回到你的例子:

def break_words(stuff):
    words = stuff.split(' ')
    return words

def sort_sentence(sentence):
    words = break_words(sentence)
    return sort_words(words)

>>> sentence = "All good things come to those who wait."
>>> sorted_words = ex25.sort_sentence(sentence)
>>> sorted_words
['All', 'come', ’good’, ’things’, ’those’, ’to’, ’wait.’, ’who’]

让我们看看我们是否可以将其分解以供您理解。

您调用了sorted_words = ex25.sort_sentence(sentence) 并将sorted_words 设置为函数sort_sentence() 的输出,即['All', 'come', ’good’, ’things’, ’those’, ’to’, ’wait.’, ’who’]。你传入了输入sentence

sort_sentence(sentence) 被执行。您传入的字符串现在在变量内称为sentence。请注意,您可以像这样调用该函数,它仍然可以工作:

sorted_words = ex25.sort_sentence("All good things come to those who wait.")

而函数sort_sentence() 仍将调用该字符串sentence。该函数基本上说明了我的输入是什么,我称之为句子。您可以将您的对象命名为 sentence 传递给我,我将在使用它时将其重命名为 sentence。

堆栈上的下一个是:

words = break_words(sentence)

现在调用函数 break_words,函数 sort_sentence 将其输入为 sentence。所以如果你跟踪它基本上是在做的:

words = break_words("All good things come to those who wait.")

堆栈上的下一个是:

words = stuff.split(' ')
return words

请注意,函数调用它的输入为stuff。因此,sort_sentence 的输入被称为sentence,而函数break_words 现在将其称为stuff

它将“句子”拆分为单词并将其存储在列表中并返回列表“单词”

注意函数sort_sentence 是如何将break_words 的输出存储在变量words 中的。请注意函数break_words 如何返回一个名为words 的变量?在这种情况下它们是相同的,但如果一个人叫它不同也没关系。 sort_sentence 可以将输出存储为foo,它仍然可以工作。我们正在谈论不同的变量范围。在函数break_words 之外,变量words 可以是任何东西,break_words 不会在意。但在break_words 内部,该变量是函数的输出。

在我家我的规则?在我家外面你可以做任何你想做的事情。

同样处理sort_sentence 返回变量,以及我们如何存储从它返回的内容。我们如何存储它或我们如何称呼它并不重要。

如果您愿意,可以将其重命名为:

def break_words(stuff):
    break_words_words = stuff.split(' ')
    return break_words_words

def sort_sentence(sentence):
    words = break_words(sentence)
    return sort_words(words) #not sure where this function sort_words is coming from. 
                             #return words would work normally. 

>>> sentence = "All good things come to those who wait."
>>> sorted_words = ex25.sort_sentence(sentence)
>>> sorted_words
['All', 'come', ’good’, ’things’, ’those’, ’to’, ’wait.’, ’who’]

您只需将局部变量和参数视为只是命名要使用的事物。就像我们与厨师的例子一样,厨师可能会称鸡蛋为原料,但我将其命名为我想要的任何名称,然后将其传递给“鸡蛋”。一切都与事物的范围有关,将功能视为房屋,当您在房屋中时,您可以为房屋中想要的任何物品命名,而在房屋之外,这些相同的名称可能是不同的东西,但在房屋内部,它们就是您希望它们成为的样子。而当你把东西扔出去的时候,你给那个东西起名字与外界无关,因为外界会给它起别的名字。可能会用同样的名字命名它......

如果我说得太多,请提出问题,我会尽力为您解决问题。

编辑

午饭回来,我认为变量是容器,它们保存值,但你不在乎其他人的容器叫什么名字。你只关心你的,当有人给你东西时,你把它放在一个容器里,并给它命名你关心的东西,这将帮助你知道里面有什么。当你送出一个物品时,你不给容器,因为你需要它来存储其他东西..

【讨论】:

  • 另一个(可能更简洁)的例子可能是厨师(函数)接受一个order(参数/参数)。 order 是班尼迪克蛋、火腿三明治还是凯撒沙拉都没有关系,订单交给厨师,厨师准备菜肴。当然,如果你传递了一个错误的参数(例如,“Chef,table 16 ordered an Eiffel Tower”,该函数很可能会引发错误:)
  • 这非常有帮助,谢谢!我只有两个后续问题:
  • 好吧,显然还在想办法做到这一点。我的第一个(可能是愚蠢的)问题与您的厨师示例有关-一旦将“成分”作为 coworker_finished_product 的值返回,它如何成为函数中的“食物”?或者这通常会涉及您为了简洁而遗漏的一个步骤?其他 ?也就是说,函数 sort_sentence 末尾的“return sort_words(words)”是怎么回事?当你说只使用 'words' 会起作用时,这一切都是有道理的,但现在我很好奇 Zed 通过让它返回那个函数是怎么想的。
  • “为简洁起见” 是的....我饿了,因为打字会影响我的午休时间。是的,由同事返回的成分必须经过加工并作为咖啡返回,或者厨师可以只返回咖啡研磨并称之为食物。至于你的第二个问题。我不知道sort_word 的功能是什么,因为你没有发布它,我也懒得去查找它。我假设它按字母顺序对单词列表进行排序。如果是这样的话,Zed 选择直接返回那个函数,这样你就有了一个排序的单词列表
  • 基本上 Zed 不想浪费另一个变量来获得 sort_word() 函数的输出,所以他只是将该函数的输出作为 sort_sentence 函数的输出返回.....你可以像这样链接返回另一种方法是sorted_values = sort_words(words)下一行return sorted_values
【解决方案2】:

参数标签无关紧要

重要的是它在函数定义中“本地”使用。基本上可以将其视为您在函数定义中定义的另一个局部变量,但参数的值被赋予函数。

记住这一点,你的下一个问题很容易回答:

从“break_words”返回的“words”与 变量 'words' 定义为 'sort_sentence' 的一部分?

什么都没有。如前所述,wordssort_sentence 的局部变量,因此在您离开函数时基本上会被丢弃(“超出范围”是行话)。当然,您可以在别处使用words 作为变量的名称,例如在另一个函数定义中,这就是这里发生的情况。

【讨论】:

    猜你喜欢
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    • 1970-01-01
    • 1970-01-01
    • 2014-05-26
    • 1970-01-01
    相关资源
    最近更新 更多