【问题标题】:(Python 3.4) - How come a variable, that has a function assigned to it, can be used in ways that the function itself cannot?(Python 3.4) - 一个分配了函数的变量怎么能以函数本身不能使用的方式使用?
【发布时间】:2015-01-13 17:38:30
【问题描述】:

在我开始之前,我只是不想澄清一下我知道变量显然使编程更容易;这只是一个关于 foo() 如何分配给 var_bar 的性质的问题,而不是为什么。

例如,假设我有一个想要阅读的文件,我会执行以下操作:

>>> r=open('Foobar.py')
>>> r.readline()
'Foo'
>>> r.readline()
'bar'
>>> r.readline()
'\n'

我以前做过的,没用的,是这样的:

>>> open('Foobar.py').readline()
 'Foo'
>>> open('Foobar.py').readline()
 'Foo'

当时我只是用alt+p调出上一行,顺便用的是IDLE。

无论如何,同样,如果我在 itertools 模块中使用 count(),我必须将函数 count 分配给这样的变量:

c = itertools.count(10,1)

>>> for i in range(0,50):
       next(c)
10
12
14
...

如果我只是做了以下事情:

for i in range(0,50):
    next(itertools.count(10,1))
10
10
10
10
...

那么为什么,当我(看似)使用完全相同的代码时,会根据代码的表达方式产生不同的输出(当然,它与幕后发生的事情不同) .

我知道如果 list1=list2,并且 list2 被修改,那么 list1 也被修改为它们的别名,因为第二个不仅指第一个,而且是第一个(list2 是 list1 返回 True),所以当变量 c 和 l 引用的表达式单独使用时,我会期望相同的行为。

感谢您的帮助,我们将不胜感激,因为您知道,这对于像我这样的初学者来说是一个巨大的障碍,所以一些关于这方面的阅读材料,无论是什么,都会得到很好的利用。

【问题讨论】:

  • r = open('Foobar.py') 不会将函数分配给变量 - 它调用函数并将该函数的返回值分配给变量。对open 的每次调用都会为您提供一个新的文件对象(它们引用磁盘上的同一个文件并不重要)。如果在r = open('Foobar.py') 之后,您将r 分配给另一个变量:a = r,那么a 将引用同一个文件对象,类似于您的list1 = list2 代码。

标签: python function variables python-3.x variable-assignment


【解决方案1】:

您需要了解的是所谓的 yield 关键字。

每次在代码主体中找到关键字时,yield 都会返回 a 值。举个简单的例子:

>>> def a():
yield 1
yield 2
yield 3
>>> b=a()
>>> next (b)
1
>>> next (b)
2
>>> next (b)
3
>>> next (b)
Traceback (most recent call last):
  File "<pyshell#41>", line 1, in <module>
    next (b)
StopIteration

在这里,如果你将函数 a() 赋给变量 b,那么你也赋给它返回的值。变量保存,即记录值,就像在记事本上一样。如果变量用于执行相同的函数,则保留该值,如果函数单独使用,则变量丢失,函数退出。

打个比方,如果记事本将值存储到记事本内的便笺中,那么它可以在同一页上继续这样做,但想象一下,每次打开新页时都必须计算和重写所有值使用,因此您需要将所有值存储在同一页面上。

count方法使用了python自己教程的这个摘要中的yield关键字:

def count(start=0, step=1):
# count(10) --> 10 11 12 13 14 ...
# count(2.5, 0.5) -> 2.5 3.0 3.5 ...
n = start
while True:
    yield n
    n+=step

参考:https://docs.python.org/2/library/itertools.html#itertools.count

当yield被命中时,值被返回,很像return函数,但是当再次调用函数时,指针从它离开的地方开始,而不是回到代码的顶部,它返回到yield,然后执行 yield 之后的其余代码,如果有的话,然后重复。但是,只有当值可以分配到变量时,这才是正确的。顺便说一句,这不要与 for 循环混淆,如果只有一个 yield 语句,那么如果没有在循环中使用,函数将继续它离开的地方,如示例一,直到代码'用尽',你可以说它耗尽了资源。

所以,希望对你有帮助:)

P.S 查看 e-satis 的答案,当涉及到 count() 等函数时,您需要了解一些事情,它是一个生成器(查看链接):

What does the "yield" keyword do in Python?

【讨论】:

    【解决方案2】:

    以下是简要说明:

    当你使用这个时:

    c = itertools.count(10)
    for i in range(10):
      print next(c)
    

    你得到 10、11、12.... 19

    但是当你这样做时:

    for i in range(10):
      print next(itertools.count(10))
    

    实际上,您正在这样做:

    for i in range(10):
      c = itertools.count(10)
      print next(c)
    

    【讨论】:

      【解决方案3】:

      为什么分配了函数的变量可以以函数本身无法使用的方式使用?

      open 是一个函数。 open('Foobar.py') 不是。它是由open 返回的对象,它被调用。

      r=open('Foobar.py') 使r 引用返回的对象。
      r.readline() 修改r 指向的对象,因此它不会两次返回同一行。

      open('Foobar.py').readline() - open 调用返回对象,您立即使用和修改一次,获取文件的第一行。您不会在任何地方存储对该对象的引用,因此它会被删除。

      【讨论】:

        【解决方案4】:

        这里的术语是“副作用”。

        当你调用readline 时,你有一个返回值和一个副作用。返回值是正在读取的文件的行。副作用是光标移动到下一行。副作用会更改文件对象,因此每次调用readline 时,都会得到一个新行。计数器迭代器也有同样的概念。

        如果您不将文件保存到变量中,那么副作用就会丢失,并且您基本上会在第二次打开文件时重新开始。换句话说,即使您在操作系统上打开同一个文件,就python 而言,您正在处理两个完全不同的文件对象。你对第一个做的任何事情都与第二个无关。

        【讨论】:

        • 非常感谢您的回答^_^ 我知道,创建了一个对象,但保存在一个变量下,因此当对该对象产生副作用时,会记录该对象的值。顺便说一句,在 Google 中使用的关键术语是什么?再次感谢:)
        • 从技术上讲,创建一个对象的instance,并将副作用应用到一个实例上。这是面向对象编程的基本原则。
        猜你喜欢
        • 2021-11-16
        • 1970-01-01
        • 1970-01-01
        • 2020-06-12
        • 1970-01-01
        • 2022-08-14
        • 2011-09-13
        • 1970-01-01
        • 2019-08-03
        相关资源
        最近更新 更多