25 Mar 2015

Add Property to class dynamically in Python

收藏到CSDN网摘




开源社区有一个网友问了个问题,如何动态给类添加一个属性?这在c++中几乎是不可能的,据说.Net和Java这种支持反射机制的语言可以.在Python中,这(相对)非常容易实现,需要正确设置get和set函数就能为一个类动态添加一个属性.具体看代码:
class DynamicPropertyTest(object):
    def __init__(self,name,url,tel):
        self._name = name
        self._url = url
        self._tel = tel

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self,name):
        self._name = name

    @property
    def url(self):
        return self._url

    @url.setter
    def url(self,url):
        self._url = url

    @property
    def tel(self):
        return self._tel

    @tel.setter
    def tel(self,tel):
        self._tel = tel

    def __repr__(self):
        return '\n'.join([item[1].upper()+item[2:]+':\t'+getattr(self,item) for item in dir(self) if not item.startswith('__') and item.startswith('_')])

    # the most important functions get and set
    def add_property(self,key,value):
        fget = lambda self: self._get_property(key)
        fset = lambda self, value: self._set_property(key,value)
        
        # add property here
        setattr(self.__class__,key,property(fget,fset))
        # add local variable with the format as _key like _name, _url and _tel
        setattr(self,'_'+key,value)

# original instance
a = DynamicPropertyTest('Company1','http://www.app1.com','0086-(0)123 45567')
print a

print '\n-- After adding property type --\n'
# add a new property dynamically
a.add_property('type','Private')
print a

# both methods worked
print '\n-- After changing the new and existing property --\n'
# you'll need to know the new added property
a._type = 'Test'
# the following code will overwrite the existing value if exists
a.add_property('type','Public')
a.add_property('name','Company2')
print a


运行上述代码的结果如下:
>>> ================================ RESTART ================================
>>> 
Name: Company1
Tel: 0086-(0)123 45567
Url: http://www.app1.com

-- After adding property type --

Name: Company1
Tel: 0086-(0)123 45567
Type: Private
Url: http://www.app1.com

-- After changing the new and existing property --

Name: Company2
Tel: 0086-(0)123 45567
Type: Public
Url: http://www.app1.com
>>> 

No comments :

Post a Comment