python - 在类范围内动态覆盖列表的内置函数

标签 python python-2.7 inheritance scope built-in

纯粹好奇的问题:

class Li(list): pass
m, n= Li([1]), Li([2])
def r(*args, **kwargs): raise Exception('hop')
setattr(m, '__iadd__', r)
m += n
print m # [1, 2]
setattr(Li, '__iadd__', r)
m += n

输出:

[1, 2]
Traceback (most recent call last):
  File "C:\...\test_override.py", line 8, in <module>
    m+=n
  File "C:\...\test_override.py", line 3, in r
    def r(*args, **kwargs): raise Exception('hop')
Exception: hop

如果我使用 setattr(m, 'append', r) 那么 m.append(2) 将失败。那么是在类对象上调用 __iadd__ 吗?

我还可以在类范围内使用 settattr 吗?一个天真的尝试,如下所示:

def r(*args, **kwargs): raise Exception('hop')
class Li(list):
    for s in {'__iadd__','append'}: setattr(Li, s, r)

失败并出现NameError:名称“Li”未定义

最佳答案

在新样式类中,实例__getattr__方法不再拦截内置操作发出的调用。当使用内置操作时,搜索从类级别开始,而不是从实例级别开始。然而,对方法名称的显式调用将起作用:

>>> class Li(list): pass
>>> m, n= Li([1]), Li([2])
>>> def r(*args, **kwargs):
        raise Exception('hop')

>>> setattr(m, '__iadd__', r)
>>> m += n           # no exception raised

>>> m.__iadd__(n)    # explicitly calling the method searches the instance first
Traceback (most recent call last):
  File "<pyshell#76>", line 1, in <module>
    m.__iadd__(n)
  File "<pyshell#73>", line 1, in r
    def r(*args, **kwargs): raise Exception('hop')
Exception: hop

实现第二个目标的一种方法是使用 a metaclass ,特别是如果您只想创建一次属性(根据您的评论):

>>> class Meta(type):
    def __new__(meta, name, bases, attrdict):
        print 'adding class attributes!'
        for s in {'__iadd__','append'}:
            attrdict[s] = r
        return super(Meta, meta).__new__(meta, name, bases, attrdict)
    def __init__(cls, name, bases, attrdict):
        super(Meta, cls).__init__(name, bases, attrdict)


>>> class Li(list):
    __metaclass__ = Meta


adding class attributes!          # attributes added here
>>> t = Li()                      # but not on instance creation
>>> Li.__dict__
dict_proxy({'__module__': '__main__', '__metaclass__': <class '__main__.Meta'>, '__iadd__': <function r at 0x02AAA270>, '__dict__': <attribute '__dict__' of 'Li' objects>, '__weakref__': <attribute '__weakref__' of 'Li' objects>, '__doc__': None, 'append': <function r at 0x02AAA270>})

关于python - 在类范围内动态覆盖列表的内置函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29858405/

相关文章:

c# - 继承方法无法访问派生类中的新实现

python 找不到 numpy

java - Java中通过继承类实现接口(interface)

c# - 如何在 F# 中实现 C# 接口(interface)?

Python 频率分布 (FreqDist/NLTK) 问题

python - 在 Python 中使用自定义函数解析方程式

python - 用于测试的 Scrapy 限制请求

python - 我的 Django 应用程序中一个不断增长的大表需要更好的性能策略

python - pandas - 包括所有列和行对值

python - Python 中的数据包嗅探器