【问题标题】:Updating a variable by its id within python在 python 中通过其 id 更新变量
【发布时间】:2018-04-15 11:51:25
【问题描述】:

我知道如何通过 Python 中的 id 获取变量的值,例如:

a = "hello world!"
ctypes.cast(id(a), ctypes.py_object).value

我想知道是否可以通过 id 覆盖变量值?

最简单的方法,这个:

ctypes.cast(id(a), ctypes.py_object).value = "new value"

不工作。

【问题讨论】:

    标签: python pointers ctypes


    【解决方案1】:

    为什么它不起作用

    对象ctypes.cast(id(a), ctypes.py_object) 仅提供内存中对象的视图。因此,当更新value 属性时,您不会更新对象本身,您所做的只是创建一个新对象并让value 指向它。

    import ctypes
    
    a = "Hello World!"
    py_obj = ctypes.cast(id(a), ctypes.py_object)
    
    id(py_obj.value) # 1868526529136
    
    py_obj.value = 'Bye Bye World!'
    
    # Here we can see that `value` now points to a new object
    id(py_obj.value) # 1868528280112
    

    如何改变任何对象

    使用ctypes 可以直接更新内存,从而改变任何对象。甚至对于被认为是不可变的字符串也是如此。

    下面的练习很有趣,但不应该在其他情况下使用。除此之外,它还可能破坏对象引用计数,从而导致内存管理错误。

    import ctypes
    import sys
    
    def mutate(obj, new_obj):
        if sys.getsizeof(obj) != sys.getsizeof(new_obj):
            raise ValueError('objects must have same size')
    
        mem = (ctypes.c_byte * sys.getsizeof(obj)).from_address(id(obj))
        new_mem = (ctypes.c_byte * sys.getsizeof(new_obj)).from_address(id(new_obj))
    
        for i in range(len(mem)):
            mem[i] = new_mem[i]
    

    以下是示例。其中你会发现为什么你不能使用上面的代码,除非你真的知道你在做什么或作为一个练习。

    s = 'Hello World!'
    mutate(s, 'Bye World!!!')
    print(s) # prints: 'Bye World!!!'
    
    # The following happens because of Python interning
    mutate('a', 'b')
    print('a') # prints: 'b'
    
    mutate(1, 2)
    print(1) # prints: 2
    

    特别是,上面的示例使 Python 退出时出现未知错误代码或崩溃,具体取决于版本和环境。

    【讨论】:

    • @user2357112 您使用的是哪个版本的 Python,我无法在您的编辑中重现错误
    • 2.7.11 在 Windows 上。
    • 我添加了版本,因为它似乎适用于 Python 3.6
    • 我在Ideone 上也遇到了崩溃,Python 3.5,显然是某种 Linux 风格。也许在新的口译员中尝试一下。它可能受到您所做的其他事情的影响,例如 mutate(1, 2)
    • 是的,mutate(1, 2) 可能是原因,因为它使 Python 退出,代码为 -1073740940。我的猜测是,通过改变一个整数,我们可能已经改变了退出代码
    【解决方案2】:

    a 是一个字符串,而字符串在 Python 中是不可变的。

    文档示例:

    >>> s = "Hello, World"
    >>> c_s = c_wchar_p(s)
    >>> print(c_s)
    c_wchar_p(139966785747344)
    >>> print(c_s.value)
    Hello World
    >>> c_s.value = "Hi, there"
    >>> print(c_s)              # the memory location has changed
    c_wchar_p(139966783348904)
    >>> print(c_s.value)
    Hi, there
    >>> print(s)                # first object is unchanged
    Hello, World
    >>>
    

    【讨论】:

      猜你喜欢
      • 2023-03-05
      • 2019-12-20
      • 1970-01-01
      • 1970-01-01
      • 2020-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多