一、關於私有關鍵字
Python中沒有private關鍵字,與之最接近的概念是名稱修飾(name mangling)。每當在一個屬性前面加上雙下劃線_ _時,解釋器就會立即將其重命名,通過這種方式造成對象實例無法直接訪問屬性。
class MyClass:
__secret_value=1
二、描述符
描述符descriptor允許你自定義在引用一個對象的屬性時應該完成的事情。描述符是python中複雜屬性訪問的基礎。
描述符類基於3個特殊方法,這3個方法組成了描述符協議(descriptor protocol):
1) __set__(self,obj,type=None): 在屬性設置時調用 這一方法。
2)__get__(self,obj,value): 在讀取屬性時調用這一方法。
3)__delete__(self,obj): 對屬性調用del時將調用這一方法。
class RevealAccess(object):
"""
A data descriptor that sets and returns values
normally and prints a message logging their access.
"""
def __init__(self, initval=None, name='var'):
self.val = initval
self.name = name
def __get__(self, obj, objtype):
print('Retrieving', self.name)
return self.val
def __set__(self, obj, val):
print('Updating', self.name)
self.val = val
class MyClass(object):
x = RevealAccess(10, 'var "x"')
y = 5
if __name__ == "__main__":
my_instance = MyClass()
# set x attribute (will issue print)
my_instance.x = 4
# access x attribute (will issue print)
assert my_instance.x == 4
# set y attribute (will pass silently)
my_instance.y = 2
# access x attribute (will pass silently)
assert my_instance.y == 2
2.2 property提供了一個內置的描述符類型
class Rectangle:
def __init__(self, x1, y1, x2, y2):
self.x1, self.y1 = x1, y1
self.x2, self.y2 = x2, y2
@property
def width(self):
"""rectangle height measured from top"""
return self.x2 - self.x1
@width.setter
def width(self, value):
self.x2 = self.x1 + value
@property
def height(self):
"""rectangle height measured from top"""
return self.y2 - self.y1
@height.setter
def height(self, value):
self.y2 = self.y1 + value
def __repr__(self):
return "{}({}, {}, {}, {})".format(
self.__class__.__name__,
self.x1, self.y1, self.x2, self.y2
)
if __name__ == "__main__":
rectangle = Rectangle(0, 0, 10, 10)
print(
"At start we have {} with size of {} x {}"
"".format(rectangle, rectangle.width, rectangle.height)
)
rectangle.width = 2
rectangle.height = 8
print(
"After resizing we have {} with size of {} x {}"
"".format(rectangle, rectangle.width, rectangle.height)
)