【问题标题】:Moving Instance attributes from module to module在模块之间移动实例属性
【发布时间】:2014-08-12 22:37:00
【问题描述】:

我遇到了很多麻烦,我相信这很容易解决。虽然,我到处寻找,但找不到我要找的东西。

我有三个模块,module1.pymodule2.pymodule3.py

例如,在 module1.py 中,我有一个这样的初始化类:

class MyClass():
    def __init__(self):
        self.name = ''
        self.age = 0

module2.py 中,我使用该类创建了一个实例,如下所示:

from module1 import MyClass
import module3 # this is where i keep my functions that i 
               # repeatedly use for better code management


me = MyClass()
me.name = "John"
me.age = module3.func_that_does_stuff()

module3.example_func(me.name, me.age)  # this function should manipulate the 
                                       # name and age lets say it turns john into 
                                       # rick, and 25 into 30

Module3.py

func_that_does_stuff():
    return 25

example_func(name, age):
    name = "rick"
    age = 30
    return name, age

就像我上面说的,在 module3 我有函数,但这里是我遇到问题的地方。我可以将那些objectsme.nameme.age)传递给另一个模块中的函数,但它似乎没有更新me.nameme.age

所以当我尝试在模块 2 中打印时

print(me.name)
print(me.age)

我明白了:

self.name = "John"
self.age = 25

如何将对象的值传递给另一个模块,按照我认为合适的方式处理它们,并能够更新 me 的原始实例的 self.nameself.age 的内容??

希望这是有道理的。

【问题讨论】:

  • 为什么不能通过“我”本身?
  • 这是因为python中的参数是通过value而不是reference传递的。如果你有一个函数def foo(x):,你不能改变x在调用上下文中引用的“东西”。

标签: python class init


【解决方案1】:

正如 jonrsharpe 在 cmets 中所说,这里的问题是你的函数中的直接赋值,它在自己的命名空间中创建了新变量。直接传递 me 实例,而不是其属性(它们是不可变对象)应该可以解决您的问题。

由于您的意图是访问和更改实例属性,请直接将 me 实例传递给函数。

module3.example_func(me)

然后将你的函数修改为如下,直接修改实例属性。

example_func(me):
    me.name = "rick"
    me.age = 30

注意,我们跳过return,因为我们直接修改对象。

【讨论】:

  • 谢谢你直接回答!我将改为使用 me 实例作为参数。
  • 事实上,例如me.name 是不可变的,虽然相关,但在这里不是关键 - 如果它是例如,这仍然会发生。 list.
  • @user3833838 我明白你想说什么,但example_func 不会尝试修改参数,它会为这些名称分配新值。
  • 你是什么意思“到问题的上下文”?我的观点是,在代码中,问题是专门针对的,可变属性也会发生同样的事情
  • 我的立场得到纠正,我的回答也得到纠正。谢谢。
【解决方案2】:

example_func 的作用如下:

def example_func(name, age): # take two arguments
    name = "rick" # ignore first argument, assign string literal to name
    age = 30 # ignore second argument, assign integer literal to name
    return name, age # return new values

module2 做了什么:

module3.example_func(me.name, me.age) # pass two objects (that get ignored)
                                      # and ignore the returned values

修改:

  1. 作为参数传递的(不可变的!)对象;或
  2. 具有这些对象属性的类实例。

您需要将这些返回值分配回实例:

me.name, me.age = module3.example_func(me.name, me.age)

或者,使 module3.example_func 将单个 MyClass 实例作为参数,并就地修改它:

def example_func(an_instance):
    an_instance.name = "rick"
    an_instance.age = 30

实际上,鉴于example_funcMyClass 的耦合程度似乎如此密切,您至少应该考虑将它们放在同一个文件中。

【讨论】:

  • 我在这个问题中提供的内容真的很简单。我的实际代码.. 它很长,尤其是操作一些属性的函数。为了我的理智,我想让他们分开,但我感谢您的帮助!
  • @pypy 我提出的三个建议中有两个涉及将它们分开。
【解决方案3】:

在 Python 中,即使是字符串或整数也是对象。但是,这些对象的行为与继承自类object 的行为不同(请参阅immutable objects ...)。 例如:

>>> s = "Hello word"
>>> s.foo = 15
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/local00/home/J91272/Bureau/<ipython console> in <module>()
AttributeError: 'str' object has no attribute 'foo'

然而,

>>> a = lambda x: 1
>>> a.foo = 36
>>> print a.foo
36

属性 foo 包含一个指向变量的指针。 当我们写a.foo = 36时,会创建一个新变量,foo的指针在内存中设计新创建的值。

将变量 a.foo 传递给函数不会传递指针而是传递变量。 当您使用诸如par_a = 25(对于定义的函数func(par_a))等等式修改此变量时,会创建一个新变量并修改par_a 的指针。 但是 a.foo 的指针保持不变。

如果你想传递你描述的实例,最好传递整个对象,例如:

example_func(obj):
    obj.name = "rick"
    obj.age = 30
    return obj.name, obj.age

有时我们更喜欢只传递一些特定的参数。 对于从 Python 调用的非 Pythonic 函数,它甚至不是强制性的。 在这种情况下,我可以建议一个掩码函数,例如:

# Initial function that can not be modified
def example_func(name, age):
    name = "rick"
    age = 30
    return name, age

# Mask function that allows passing the object
def mask_function(obj):
    ret = example_func(obj.name, obj.age)
    obj.name, obj.age = ret
    return ret

如果有更 Pythonic 的解决方案,我会很感兴趣!

【讨论】:

    猜你喜欢
    • 2019-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-04
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    相关资源
    最近更新 更多