在 Python 中设置只读属性? [英] Set a Read-Only Attribute in Python?

查看:48
本文介绍了在 Python 中设置只读属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于 Python 的动态性,如果这不可能实现,我会感到震惊:

Given how dynamic Python is, I'll be shocked if this isn't somehow possible:

我想改变sys.stdout.write的实现.

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

I got the idea from this answer to another question of mine: 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

但它告诉我 AttributeError: 'file' 对象属性 'write' 是只读的.

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

This is a nice attempt to keep me from doing something potentially (probably) stupid, but I'd really like to go ahead and do it anyways. I suspect the interpreter has some kind of lookup table its using that I can modify, but I couldn't find anything like that on Google. __setattr__ didn't work, either - it returned the exact same error about the attribute being read-only.

我特别在寻找 Python 2.7 解决方案,如果这很重要,尽管没有理由拒绝提供适用于其他版本的答案,因为我怀疑将来其他人会在这里查看有关其他版本的类似问题.

I'm specifically looking for a Python 2.7 solution, if that's important, although there's no reason to resist throwing in answers that work for other versions since I suspect other people in the future will look here with similar questions regarding other versions.

推荐答案

尽管具有动态性,Python 不允许对诸如 file 之类的内置类型进行猴子修补.它甚至可以通过修改此类类型的 __dict__ 来阻止您这样做 - __dict__ 属性返回包装在只读代理中的 dict,因此都分配给 file.writefile.__dict__['write'] 失败.并且至少有两个很好的理由:

Despite its dynamicity, Python does not allow monkey-patching built-in types such as file. It even prevents you to do so by modifying the __dict__ of such a type — the __dict__ property returns the dict wrapped in a read-only proxy, so both assignment to file.write and to file.__dict__['write'] fail. And for at least two good reasons:

  1. C 代码期望 file 内置类型对应于 PyFile 类型结构,而 file.write 对应于内部使用的 PyFile_Write() 函数.

  1. the C code expects the file built-in type to correspond to the PyFile type structure, and file.write to the PyFile_Write() function used internally.

Python 实现了对类型的属性访问的缓存,以加快方法查找和实例方法的创建.如果允许直接分配给类型字典,此缓存将被破坏.

Python implements caching of attribute access on types to speed up method lookup and instance method creation. This cache would be broken if it were allowed to directly assign to type dicts.

对于用 Python 实现的类,当然可以使用 Monkey-patching,它可以很好地处理动态修改.

Monkey-patching is of course allowed for classes implemented in Python which can handle dynamic modifications just fine.

但是……如果您真的知道自己在做什么,则可以使用诸如 ctypes 之类的低级 API 来挂钩实现并获取类型 dict.例如:

However... if you really know what you are doing, you can use the low-level APIs such as ctypes to hook into the implementation and get to the type dict. For example:

# 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')

这篇关于在 Python 中设置只读属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆