1. 程式人生 > >guxh的python筆記:面向物件之屬性

guxh的python筆記:面向物件之屬性

1,類的私有屬性

class Foo:
    
    def __init__(self, x):
        self.x = x

類的屬性在例項化之後是可以更改的:

f = Foo(1)
print(f.x)   # 1
f.x = 2
print(f.x)   # 2

如果想禁止訪問屬性,即讓屬性私有,可以用“雙下劃線” 或者“單下劃線”:

class Foo:

    def __init__(self, x, y):
        self._x = x
        self.__y = y

    def __repr__(self):
        return 'f._x = {}, f.__y = {}'.format(self._x, self.__y)

區別是“雙下劃線”直譯器會對屬性就行“名稱更改”,而“單下劃線”不會有更改,只是約定成俗。

但是知道規則還是可以輕鬆訪問:

f = Foo(1, 1)
f._x = 2
f._Foo__y = 2
print(f)   # f._x = 2, f.__y = 2

所以如果只是為了屬性私有,用“單下劃線”和“雙下劃線”沒有什麼區別。

但“雙下劃線”在繼承時可以避免基類屬性被子類的屬性覆蓋。

 

2,屬性只讀(私有 + property)

私有屬性 + property可以讓屬性變的只讀:

class Foo:

    def __init__(self, x):
        self._x = x
    
    @property
    def x(self):
        return self._x

此時對Foo進行例項化後,可以訪問物件的屬性x,但無法給x賦值:

f = Foo(1)
print(f.x)  # 1
f.x = 2   # AttributeError: can't set attribute

因為例項化時的x存在私有屬性self._x中,當然可以用1中提到的訪問私有屬性的方法去修改,但這被認為是粗略的行為:

f = Foo(1)
f._x= 2
print(f.x)  # 2

 

3,屬性管理(init)

 

 

4,屬性管理(property)

對屬性的操作有:get,set,del。

property只是完成了get操作,配套的get / del分配由setter / delettr完成,組合起來就可以實現對屬性的管理:

class Foo:

    def __init__(self, x):
        self.x = x

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, val):
        if val < 0:
            raise ValueError('x must be >= 0')
        self._x = val

    @x.deleter
    def x(self):
        pass

再看看對x屬性的訪問情況:

f = Foo(1)
print(f.x)  # 1
f.x = 2
print(f.x)  # 2
f = Foo(-1)  # ValueError: x must be >= 0
f.x = -1  # ValueError: x must be >= 0

 如果__init__中使用self._x = x會出現什麼後果?

class Foo:

    def __init__(self, x):
        self._x = x
    ......

f = Foo(-1)
print(c.x)   #  -1
f.x = -1   # ValueError: x must be >= 0

self.x = x在例項化時會觸發set,而self._x = x在例項化時繞過了set,也就是不會對例項化時的引數做檢查。

另外,del可以不定義,del f.x會觸發AttributeError: can't delete attribute,這裡pass演示,del f.x沒什麼效果。

 

5,屬性管理(描述符)

 

 

6,動態存取屬性

getattr,setattr,delattr,hasattr