【问题标题】:Passing value from called function from module (Python)从模块(Python)中传递被调用函数的值
【发布时间】:2018-07-17 05:42:22
【问题描述】:

我正在尝试从另一个名为“File1”的文件中调用函数passvalue 作为“主文件”的模块。我希望“主文件”中x 的值在调用函数后为 4 而不是 1,y 的值是 3 而不是 2。

问题:如何确保“File1”中模块函数的值传递到“主文件”?对于这种情况,x=4y=3

我的想法:我尝试使用全局值,但它似乎不起作用,在这种情况下 return 只会将 xy 值返回给函数本身,这可能会破坏目的。

感觉好像我错过了一些简单的东西,但似乎无法得到它。

文件1:

def passvalue(a,b)
  b=b+a
  a=b+b

主要:

import File1
x=1
y=2
File1.passvalue(x,y)
print(x)
print(y)

【问题讨论】:

  • 整数对象是不可变的,这就是更改不会传播到函数外部的原因。
  • 这很有趣!万一有人遇到这个结帐>>stackoverflow.com/q/37535694/6480676。感谢您的编辑!
  • 你不回来了

标签: python function python-module


【解决方案1】:

您需要return 类似的值:

def passvalue(a,b)
    b=b+a
    a=b+b
    return a, b

这会返回一个tupletuple 可以unpacked 喜欢:

# Main File
import File1
x=1
y=2
x, y = File1.passvalue(x,y)
print(x)
print(y)

【讨论】:

  • 嗨,斯蒂芬,非常感谢您提供的简单解决方案,真不敢相信我错过了这个。感谢您的努力和时间!干杯!如果有人遇到此检查 [stackoverflow.com/questions/354883/…
【解决方案2】:

它不起作用的原因有多种:

首先,在函数中分配的对象是在本地创建的。当您执行a=...b=... 时,ab 是您在分配给参数值的函数中创建的本地 对象。一旦函数退出,ab 就不再与立即函数范围之外的代码保持任何相关性。

其次,虽然对象在 Python 中在引用中传递,但保持不变的是不可变的。由于xy 是整数,因此它们是不可变的,即每次对它们执行任何操作时,都会为对象分配一个新值,而不是更改它。 p>

要理解这一点,请考虑以下函数:

def mod_lists(list_1, list_2, list_3):
    print("obj ID of rlst_1 = {0}\n"
          "obj ID of rlst_2 = {1}\n"
          "obj ID of rlst_3 = {2}\n".format(id(rlst_1), id(rlst_2), id(rlst_3)))
    print("Before change:\n"
          "obj ID of list_1 = {0}\n"
          "obj ID of list_2 = {1}\n"
          "obj ID of list_3 = {2}\n".format(id(list_1), id(list_2), id(list_3)))
    list_1.append("hello")
    list_2 = list_1 + ["world"]
    list_3 = list_1 + ["world"]
    print("After change:\n"
          "obj ID of list_1 = {0}\n"
          "obj ID of list_2 = {1}\n"
          "obj ID of list_3 = {2}\n".format(id(list_1), id(list_2), id(list_3)))
    return list_3

现在考虑我想通过三个lists:

rlst_1 = list()
rlst_2 = list()
rlst_3 = list()

我调用函数如下:

rlst_3 = mod_lists(rlst_1, rlst_2, rlst_3)

现在您可能会期待rlst_1 = ['hello']rlst_2 = ['hello', 'world']rlst_3 = ['hello', 'world'],但这是错误的。如果您运行它,您会注意到rlst_2 实际上是一个空的list(未更改)。

那么是什么让rlst_1rlst_3 发生了变化?让我们看一下打印出来的对象ID并进行比较:

# NOTE: You will see different numbers on your system.
obj ID of rlst_1 = 52178816
obj ID of rlst_2 = 52337240
obj ID of rlst_3 = 51607312

Before change:
obj ID of list_1 = 52178816
obj ID of list_2 = 52337240
obj ID of list_3 = 51607312

After change:
obj ID of list_1 = 52178816
obj ID of list_2 = 52336920
obj ID of list_3 = 52336840

在对函数进行任何更改之前,您可以看到对象 ID 完全相同分别相同,这意味着 list_1rlst_1 的精确引用等。现在在changes were done 是您注意到更改的地方。您可以看到 list_2list_3 现在有不同的对象 ID。这是为什么?这是因为在list_2=...list_3=... 行中,您实际上重新分配这两个对象到一个新引用,即list_1 + ['world']。您可能还想知道为什么它们都有不同的 ID,因为值应该相同。虽然list_1 是同一个引用,但每个['world'] 都是list 对象的新实例,其中包含单词"world" 作为一个项目,因此它们是不同的对象,即使它们具有相同的值。

为什么list_1 的对象引用不受影响?这是因为当您在 list_1 上调用 append 函数时,它不会重新分配,而是更改引用中的对象,将值 "hello" 附加到同一个对象中。

现在在函数调用之后,当你打印rlsts 时,你会看到:

# rlst_1
# ['hello']
# rlst_2
# []
# rlst_3
# ['hello', 'world']

rlst_1 已按预期更改,因为引用中的同一对象已被修改。 rlst_2 没有改变,因为即使 list_2 被重新分配了一个新列表,它也是一个在函数内创建的本地对象,并在函数退出后丢失。

为什么rlst_3 会更新?您可能认为它已更新,但它实际上是一个具有相同名称的 NEW 对象。注意函数的最后一部分返回本地创建的list_3,其值为list_1 + ['world']。所以函数调用的计算如下:

rlst_3 = mod_lists(rlst_1, rlst_2, rlst_3)
    (local) list_1 = ['hello']
    (local) list_3 = list_1 + ['world']
    (local) list_3 = ['hello', 'world']
rlst_3 = list_3
rlst_3 = ['hello', 'world']

如果这仍然令人困惑,请运行 id(rlst_3),您将看到 52336840,这正是本地创建的 list_3 的对象 ID(同样,您可能会看到不同的数字,但id(rlst_3) 将始终等于id(list_3))。

应用这个逻辑,现在你可以理解为什么不能在引用中传递不可变整数并希望在函数中修改它们。更改外部对象的唯一方法是将它们重新分配给函数返回的新创建的本地对象。

这个答案显然比 Stephen Rauch 的要啰嗦得多,但它提供了更多关于为什么它不起作用的背景。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-17
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    相关资源
    最近更新 更多