【问题标题】:Is there a simple way of emulating a pointer in python?有没有一种简单的方法可以在 python 中模拟指针?
【发布时间】:2019-08-15 02:26:39
【问题描述】:

我希望创建一个包含类中其他值的列表,并确保该列表是最新的,而无需自己更新。

我试过这样写:

class Test:
    def __init__(self, arg, arg2):
        self.arg = arg
        self.arg2= arg2
        self.list = [self.arg, self.arg2] #list I want up to date

    def update(self, arg, arg2):
        self.arg = arg
        self.arg2 = arg2
        #the simple answer is to add: self.list=[self.arg, self.arg2] or a function doing it. That is not what I am asking.

    def write_list(self):
        print(self.list)

tes = Test(1, 2)
tes.write_list()
tes.update(23,24)
tes.write_list()

我希望输出是:

[1,2]
[23,24]

【问题讨论】:

  • 对于某些类型的数据,它总是复制值 - 即。对于整数 - 对于其他人,它将使用参考(指针),它将按您的预期工作 - 即。对于列表或类。一些模块使用类来保存像整数这样的值(tkinterIntVarkivyPropertyInteger)然后列表将保存引用/指针 - 但它可能需要类的方法来设置/获取值 - @987654328 @, IntVar.set(val)
  • 取决于argarg2的数据类型。如果它们是不可变的(例如int),则不能这样做。如果不是,您可以简单地改变它们(例如self.arg.update(arg)),这也会反映在列表中。
  • 好的,谢谢您的回答!就像我当时想的那样,没有办法用最少的代码做到这一点。
  • @furas:Python 不复制整数。持有整数的变量确实持有对整数的引用,就像列表和任何其他 Python 数据类型一样。只是你不能做任何事情来改变一个 int,而你可以改变一个列表。

标签: python pointers variables reference


【解决方案1】:

int 是不可变的。因此,当您在更新方法中执行 self.arg=arg 时,self.list 仍将指向旧值。

我建议创建一个Pointer 类来存储您的整数,并使用更新方法来改变值:

class Test:
    def __init__(self, arg, arg2):
        self.arg = Pointer(arg)
        self.arg2= Pointer(arg2)
        self.list = [self.arg, self.arg2]

    def update(self, *args):
        for pointer, val in zip(self.list, args):
            pointer.update(val)

    def write_list(self):
        print (self.list)

class Pointer:
    def __init__(self, num):
        self.num = num

    def update(self, num):
        self.num = num

    def __repr__(self):
        return repr(self.num)

tes = Test(1, 2)
tes.write_list()
tes.update(23,24)
tes.write_list()

#[1, 2]
#[23, 24]

【讨论】:

  • 不变性几乎是一条红鲱鱼。即使self.arg 引用了一个可变对象,那么self.arg=arg 也不会改变任何东西。
  • 是的,但我认为在 OP 的概念中,他期望 self.list,一个存储 self.argself.arg2 的列表,将在定义 self.arg 的新值时发生变化。
【解决方案2】:

另一种方法是使用属性,其中lst 模仿传统属性,但实际上是在运行时重新创建的。但是,这样做有一些效率低下,因为每次访问 test_instance.lst 时都会重新创建列表。

class Test:
    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2

    @property
    def lst(self):
        return [self.arg1, self.arg2]

    def update(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2

    def write_list(self):
        print(self.lst)

tes = Test(1, 2)
tes.write_list()
tes.update(23,24)
tes.write_list()

# Output:
#   [1, 2]
#   [23, 24]

另一个选项,至少对于示例代码,只是从.update() 中更新.lst 属性:

class Test:
    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2
        self.lst = [arg1, arg2]

    def update(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2
        self.lst = [arg1, arg2]

    def write_list(self):
        print(self.lst)

tes = Test(1, 2)
tes.write_list()
tes.update(23,24)
tes.write_list()

【讨论】:

  • 这很有趣,你能快速告诉我@property 是如何工作的吗?
  • @property 是一个方法装饰器,它允许您使用方法调用的返回值“模拟”一个属性(例如test.lst)。文档(链接)以及this question/answers 可能会有所帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-22
  • 2012-09-15
  • 2010-09-24
  • 2019-10-03
  • 2021-10-31
  • 2011-03-02
  • 1970-01-01
相关资源
最近更新 更多