在python中从str或unicode继承时,是否可以在赋值后保留类实例?

在python中从str或unicode继承时,是否可以在赋值后保留类实例?,python,string,inheritance,unicode,Python,String,Inheritance,Unicode,我想答案是否定的,但如果有机会,我的生活会轻松很多。考虑下面的代码: class SchemaString(unicode): _schema = dict() def validate(self): errors = [] # some validation function using class propertie _schema, not important return sorted(list(set(errors)))

我想答案是否定的,但如果有机会,我的生活会轻松很多。考虑下面的代码:

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中使用“=”时是否使用了一些内部赋值函数,该赋值函数是否可以被覆盖?

您不能覆盖“顶级”赋值。但是,如果您可以拥有根对象并在名称空间对象内使用变量,那么是的,您只需要为该对象编写
\uuuuuu setattr\uuuuu
方法。它可以是一个相当简单的类,您可以创建一个单个字母的实例,因此它不会对读取代码造成负面干扰-相反,很容易察觉到发生了一些特殊的事情:

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()
并在ineteractive提示符上:

In [110]: class MyString(str): pass
     ...: 
     ...: n.s = MyString()
     ...: 
     ...: n.s = "bla"
     ...: type(n.s)
     ...: 
Out[110]: __main__.MyString
如果不使用容器对象,不,就无法覆盖赋值-引擎盖下生成的代码完全不同-因为字节码直接在当前帧的“全局”字典中设置变量,或者在快速变量缓存中,如果代码在函数中运行-这意味着即使不触及
局部变量
字典。也就是说,可以考虑一种观察者模式,它负责全局字典中的更改,并在模块中更改全局变量时采取操作(例如,如果您的应用程序在自定义事件循环中运行),但这太老套了,而且无论如何对全局变量都不起作用。名称空间对象要简单几个数量级


也就是说,如果您使用的是Python3(首先,您应该停止担心文本的“unicode”或“str”)-您还可以重写类主体中的赋值运算符:为此,您必须使用
\uuuuuu prepare\uuuuu
方法创建一个自定义元类,该方法将创建一个映射对象,其中所需的逻辑将位于
\uuuuuuu setitem\uuuuu
方法上。在本例中,Python代码在找到赋值语句时,只需对这个类似字典的对象调用
\uuuuu setitem\uuuu
方法

让我们知道会发生什么?答案是否定的,你不能忽略这个任务。除此之外,使用类来实现这一点似乎是不必要的;将
str
unicode
dict
tuple
和friends子类化也几乎总是以微妙的方式出错。为什么不使用简单的独立功能?您可以
functools.partial
将架构状态放入其中,使用一个函数
validate\u foobar=functools.partial(validate,foobar\u schema)
然后
validate\u foobar
可能重复的