2017-06-09 32 views
2

我認爲答案是否定的,但如果有機會,這會讓我的生活變得更輕鬆。請看下面的代碼:從Python中的str或unicode繼承以便在賦值後保留類實例時是否有可能?

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中使用'='時是否使用了一些內部賦值函數,並且該賦值函數是否可以被覆蓋?

+1

看起來很難嘗試自己 - 讓我們知道會發生什麼? – barny

+3

答案是否定的,你不能覆蓋任務。除此之外,爲此使用班級似乎沒有必要;子類化'str','unicode','dict','tuple'和朋友在微妙的方面也幾乎總是錯誤的。爲什麼不使用簡單的獨立式功能?你可以將'functools.partial'模式狀態放入它,有一個函數'validate_foobar = functools.partial(validate,foobar_schema)'然後'validate_foobar(s)' – user2722968

+1

[可以重複Python賦值嗎?] (https://stackoverflow.com/questions/11024646/is-it-possible-to-overload-python-assignment) –

回答

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() 

而關於ineteractive提示:

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

沒有求助於的容器對象,沒有,沒有辦法來覆蓋分配 - 下引擎罩生成該代碼是完全不同的 - 如字節碼直接在當前幀的「全局」字典中設置變量,或者在代碼運行時在快速變量緩存中設置變量在一個函數內 - 這意味着甚至連字典都不會被觸摸。也就是說,可以考慮一個觀察者模式來處理全局字典中的更改,並在模塊中更改全局變量時採取行動(例如,如果您的應用程序正在自定義事件循環中運行) - 但這太hacky了,無論如何都不適用於全局變量。命名空間對象的大小比較簡單。

這就是說,如果你正在使用Python3,(你應該 - 然後一兩件事 - 停止擔心「統一」或「STR」爲文本) - 你也可以重寫賦值運算符的一個類的主體:爲此,您必須創建一個帶有__prepare__方法的自定義元類,該方法將創建一個映射對象,其中您希望的邏輯位於__setitem__方法中。在這種情況下,當Python代碼找到賦值語句時,只會在這個類似字典的對象上調用__setitem__方法。

相關問題