我想答案是否定的,但如果有机会的话,我的生活会轻松很多。考虑以下代码:
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中使用'='时是否使用了一些内部赋值函数,这个赋值函数可以被覆盖吗?
最佳答案
您不能覆盖“顶级”分配。但是,如果您可以拥有一个根对象并在命名空间对象中使用变量,那么是的,您只需为该对象编写 __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__
方法。
关于python - 在 python 中从 str 或 unicode 继承时是否有可能在分配后保留类实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44460073/