網頁

2015年7月9日 星期四

[Python] hook function for self.x, self.x = 3, delete self.x

主題: hook function for self.x, self.x = 3, delete self.x


說明:

我們有一個class A,
假設我們想要在"讀取"self.x或在"設定"self.x時或在"刪除"self.x時可以多做一些"額外的事情(某個function)",那麼該怎麼把我們的function插入呢?

實作:

實作一個descriptor, 並安裝到A中成為class member data。

#!/usr/bin/python

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

        def __get__(self, instance, cls):
                if instance is None:
                        return self
                else:
                        return instance.__dict__[self.name]

        def __set__(self, instance, value):
                if not isinstance(value, int):
                        raise TypeError('Expected an int')
                instance.__dict__[self.name] = value

        def __delete__(self, instance):
                del instance.__dict__[self.name]

class A(object):
        x = Integer('x')
        def __init__(self, x, y):
                self.x = x
                self.y = y

a = A(1.0, 2)

結果:

Traceback (most recent call last):
  File "./descriptor.py", line 27, in 
    a = A(1.0, 2)
  File "./descriptor.py", line 24, in __init__
    self.x = x
  File "./descriptor.py", line 15, in __set__
    raise TypeError('Expected an int')
TypeError: Expected an int

無效: 

因為這件事情很重要,再重複一次,
"實作一個descriptor, 並安裝到A中成為class member data。"
如果你實作了一個descriptor,但安裝到class中不是成為class member data而是instance data, 這樣是不起作用的。

class A(object):
        def __init__(self, x, y):
                self.x = Integer('x')
                self.y = y

繼承還是有效: 

class B(A):
        def __init__(self, x, y):
                self.x = x
                self.y = y

b = B(1.0, 2)
繼承還是有效,因為child class繼承了class member data
Traceback (most recent call last):
  File "./descriptor.py", line 32, in 
    b = B(1.0, 2)
  File "./descriptor.py", line 29, in __init__
    self.x = x
  File "./descriptor.py", line 15, in __set__
    raise TypeError('Expected an int')
TypeError: Expected an int

順帶一題: 

property, classmethod, staticmethod, __slots__都是相同概念:
安裝一個descriptor到class上

沒有留言:

張貼留言