Python property

2017-08-08  本文已影响51人  Syfun

Question

我们一般对属性的的操作主要有2个,访问和修改。看个例子。

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

p = Person('Jack')
print p.name
p.name = 'Rose'
print p.name

我们叫这种使用属性的方式叫点模式(我自己取得。。。),那么问题来了,如果我们想要修改属性的时候加入一个简单的类型检查,应该怎么做?

很容易想到新增一个辅助方法来达成目标。

class Person(object):
    def __init__(self, name):
        self.name = name
    
    def set_name(self, value):
        if not isinstance(value, str):
            raise TypeError('Expected a string')
        self.name = value
        
p = Person('Jack')
p.set_name('Rose')

我们也看到了,这种方法虽然可以实现功能,但是使用起来不是很方便。所以我们会想有没有一种方法可以做到使用点模式的时候也能够做类型检查。

Method

我们可以使用内置的property装饰器来实现。

class Person(object):

    def __init__(self, name):
        self._name = name

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

    @name.setter
    def name(self, value):
        if not isinstance(value, basestring):
            raise TypeError('Expected a string')
        self._name = value

    @name.deleter
    def name(self):
        del self._name
        
p = Person('Jack')
p.name = 'Rose'
p.name = 222
del p.name
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-40579c6671bf> in <module>()
      1 p = Person('Jack')
      2 p.name = 'Rose'
----> 3 p.name = 222

<ipython-input-3-335cb8c0ab8b> in name(self, value)
     14     def name(self, value):
     15         if not isinstance(value, str):
---> 16             raise TypeError('Expected a string')
     17         self._name = value
     18 

TypeError: Expected a string

用起来真是so easy啊。

虽然对外访问是name属性,但是内部有个实际存放值的属性_name。

另外还有一种用法。

class Person(object):

    def __init__(self, name):
        self._name = name

    def get_name(self):
        return self._name

    def set_name(self, value):
        if not isinstance(value, str):
            raise TypeError('Expected a string')
        self._name = value

    def del_name(self):
        del self._name

    name = property(get_name, set_name, del_name)

我们看看官方的代码注释,一目了然。

"""
property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
        
fget is a function to be used for getting an attribute value, and likewise
fset is a function for setting, and fdel a function for del'ing, an
attribute.  Typical use is to define a managed attribute x:
        
class C(object):
    def getx(self): return self._x
    def setx(self, value): self._x = value
    def delx(self): del self._x
    x = property(getx, setx, delx, "I'm the 'x' property.")
        
Decorators make defining new properties or modifying existing ones easy:
        
class C(object):
    @property
    def x(self):
        "I am the 'x' property."
        return self._x
    @x.setter
    def x(self, value):
        self._x = value
    @x.deleter
    def x(self):
        del self._x
"""

以后当我们遇到设置属性的时候需要额外逻辑的时候,就可以考虑使用property了。

上一篇 下一篇

猜你喜欢

热点阅读