在Python中设置只读属性?

Art*_*are 14 python stdout readonly-attribute python-2.7

考虑到Python的动态性,如果不可能的话,我会感到震惊:

我想改变执行情况sys.stdout.write.

我从这个答案得到了我的另一个问题的想法:https://stackoverflow.com/a/24492990/901641

我试着写这个:

original_stdoutWrite = sys.stdout.write

def new_stdoutWrite(*a, **kw):
    original_stdoutWrite("The new one was called! ")
    original_stdoutWrite(*a, **kw)

sys.stdout.write = new_stdoutWrite
Run Code Online (Sandbox Code Playgroud)

但它告诉我AttributeError: 'file' object attribute 'write' is read-only.

这是一个很好的尝试,让我不要做一些潜在的(可能)愚蠢的事情,但我真的很想继续这样做.我怀疑解释器有一些我可以修改的查找表,但我在Google上找不到类似的东西.__setattr__也没用 - 它返回了关于属性为只读的完全相同的错误.

我特意寻找Python 2.7解决方案,如果这很重要,虽然没有理由拒绝投入适用于其他版本的答案,因为我怀疑未来的其他人会在这里看到与其他版本类似的问题.

use*_*342 20

尽管它具有动态性,但它不允许使用猴子修补内置类型,例如file.它甚至可以通过修改__dict__这种类型来阻止你这样做- 该__dict__属性返回包含在只读代理中的dict,因此无论是赋值file.write还是file.__dict__['write']失败.至少有两个很好的理由:

  1. C代码期望file内置类型对应于PyFile类型结构和内部使用file.writePyFile_Write()函数.

  2. Python实现了对类型的属性访问的缓存,以加速方法查找和实例方法创建.如果允许直接分配类型dicts,则该缓存将被破坏.

当然,允许使用Python实现的类修补程序,它可以很好地处理动态修改.

但是......如果您真的知道自己在做什么,可以使用低级API,例如ctypes挂钩实现并转到类型dict.例如:

# WARNING: do NOT attempt this in production code!

import ctypes

def magic_get_dict(o):
    # find address of dict whose offset is stored in the type
    dict_addr = id(o) + type(o).__dictoffset__

    # retrieve the dict object itself
    dict_ptr = ctypes.cast(dict_addr, ctypes.POINTER(ctypes.py_object))
    return dict_ptr.contents.value

def magic_flush_mro_cache():
    ctypes.PyDLL(None).PyType_Modified(ctypes.py_object(object))

# monkey-patch file.write
dct = magic_get_dict(file)
dct['write'] = lambda f, s, orig_write=file.write: orig_write(f, '42')

# flush the method cache for the monkey-patch to take effect
magic_flush_mro_cache()

# magic!
import sys
sys.stdout.write('hello world\n')
Run Code Online (Sandbox Code Playgroud)

  • 我认为这就是我一直在寻找的那种在任何情况下都适用的巫术。+1并接受。 (2认同)