2012-09-03 33 views
0

我想在這裏做一些防禦性的編程,以避免對象以不易調試的方式改變狀態,所以在Python中以下是可能的是有辦法保護Foo.name不被更改,以便強制我更明確地執行此操作?在Python中保護可變對象的變化

class A(object): 
    def __init__(self, foo): 
     self.foo = foo 

class B(object): 
    def __init__(self, foo): 
     self.foo = foo 

    def rename(self, new_name): 
     self.foo.name = new_name 

class Foo(object): 
    def __init__(self, name): 
     self.name = name 

if __name__ == '__main__': 
    foo = Foo('Fooname') 
    print 'A foo instance is born and baptized as %s' % foo.name 
    ainstance = A(foo) 
    print 'The foo instance is then passed to A and is still called %s' % foo.name 
    binstance = B(foo) 
    print 'But then the foo instance is passed to B' 
    binstance.foo.name = 'Barname' 
    print 'And in B it is renamed to %s' % foo.name 

此輸出:

A foo instance is born and baptized as Fooname 
The foo instance is then passed to A and is still called Fooname 
But then the foo instance is passed to B 
And in B it is renamed to Barname 

我知道我可以實現重命名美孚,我可以強迫自己使用的方法,或者我可以使用名稱重整但是這仍然沒有真正阻止我在不經意間改變foo.name即使它被稱爲foo._name

+1

也很難保護您免於斷開計算機並將其扔出最近的窗口。 – unwind

+0

你提到'foo._name',那是一個下劃線前綴。這並不完美,但是您是否嘗試過使用兩個下劃線作爲前綴? 'foo .__ name' – cdarke

+0

嗨cdarke,這是故意的。我相信這是Python世界中的一種常見做法,它具有雙下劃線的好處,而不會改變名稱並添加對類名稱的依賴關係。 – Lorenzo

回答

3

您可以攔截任意屬性如下設置:

class Foo(object): 
    def __init__(self, name): 
     self.name = name 

    def __setattr__(self, attrname, value): 
     print "Intercepted: " + attrname + " attribute of Foo set to " + value 
     super(Foo, self).__setattr__(attrname, value) 

只要有人設置了Foo實例的任何屬性,就會告訴你。很明顯,你可以在__setattr__中做任何你喜歡的事情,如果有人在意想不到的時間設置屬性,則可以放棄程序。

Properties是對單一的屬性來實現一個更合適的方法:

class Foo(object): 
    def __init__(self, name): 
     self.__name = name 

    def getname(self): 
     return self.__name 

    def setname(self, name): 
     print "Intercepted: name attribute of Foo set to " + name 
     self.__name = name 

    name = property(getname, setname) 

__setattr__,您可以攔截所有從單一地點屬性設置。

+2

我覺得'object .__ setattr __(self,name,value)'比'self .__ dict __ [name] = value'更具慣用意義。 – mgilson

+0

@mgilson:同意並更改 - 謝謝! – RichieHindle

+0

更好的是:使用'super(Foo,self).__ setattr __(attrname,value)',並且在與其他基類重寫'__setattr__'的子類一起使用時玩得很好。 –