【问题标题】:Is het possible when inheriting from str or unicode in python to keep class instance after assignment?从 python 中的 str 或 unicode 继承以在分配后保留类实例时是否有可能?
【发布时间】:2017-06-09 14:14:32
【问题描述】:

我认为答案是否定的,但如果有机会,那会让我的生活轻松很多。考虑以下代码:

class SchemaString(unicode):
    _schema = dict()

    def validate(self):
        errors = []
        # some validation function using class propertie _schema, not important
        return sorted(list(set(errors)))

s = SchemaString("Hello")
e0 = s.validate()

我想要的是以下仍然有效:

s = "World"
e1 = s.validate()
>> AttributeError: 'str' object has no attribute 'validate'

因此,我的问题是是否有可能在新分配后仍然使用相同的对象,这样我仍然可以使用“验证”方法。换句话说,在python中使用'='时是否使用了一些内部赋值函数,这个赋值函数可以被覆盖吗?

【问题讨论】:

  • 自己尝试看起来并不难 - 让我们知道会发生什么?
  • 答案是否定的,您不能覆盖分配。除此之外,为此使用类似乎没有必要。子类化strunicodedicttuple 和朋友在微妙的方面几乎总是错误的。为什么不使用简单的独立功能?你可以functools.partial把模式状态放进去,有一个函数validate_foobar = functools.partial(validate, foobar_schema)然后validate_foobar(s)

标签: python string inheritance unicode


【解决方案1】:

您不能覆盖“顶级”分配。但是,如果您可以拥有一个根对象并使用命名空间对象中的变量,那么可以,您只需为该对象编写__setattr__ 方法。它可以是一个相当简单的类,并且你可以创建一个单个字母的实例,因此它不会对阅读你的代码造成负面干扰——相反,很容易察觉到正在发生一些特殊的事情:

class NS(object):
    def __setattr__(self, name, value):
        if name not in self.__dict__:
            # Normal, first time assignment:
            super(NS, self).__setattr__(name, value)
            return
        cls = type(self.__dict__[name])
        instance = cls(value)
        super(NS, self).__setattr__(name, instance)

n = NS()

在非交互式提示上:

In [110]: class MyString(str): pass
     ...: 
     ...: n.s = MyString()
     ...: 
     ...: n.s = "bla"
     ...: type(n.s)
     ...: 
Out[110]: __main__.MyString

不使用容器对象,不,没有办法覆盖分配 - 引擎盖下生成的代码完全不同 - 因为字节码直接在“全局”字典中设置变量当前帧,或者如果代码在函数内部运行,则在快速变量缓存中 - 这意味着甚至没有触及 locals 字典。也就是说,可以考虑一个观察者模式,它负责全局字典中的更改,并在模块中的全局变量发生更改时采取行动(例如,如果您的应用程序在自定义事件循环中运行) - 但这太老套了,无论如何都不适用于全局变量。命名空间对象要简单几个数量级。

也就是说,如果您使用的是 Python3,(您应该 - 然后一方面 - 不要担心文本的“unicode”或“str”) - 您也可以覆盖分配类主体中的运算符:为此,您必须使用__prepare__ 方法创建一个自定义元类,该方法将创建一个映射对象,其中您想要的逻辑将在__setitem__ 方法上.在这种情况下,当 Python 代码找到赋值语句时,它只会在这个类字典对象上调用 __setitem__ 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 2020-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-16
    • 1970-01-01
    相关资源
    最近更新 更多