如何使用property()

时间:2015-02-04 21:17:12

标签: python python-3.x

我在如何实现属性以保护属性方面遇到了麻烦。

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

    def set_x(self, x):
        if '_x' in dir(self):
            raise NotImplementedError("Cannot change x coordinate")
        else:
            self._x = x

    def get_x(self):
        return self._x

    #I beleive my mistake is here. I'm not sure if I'm implementing this correctly
    x = property(get_x, set_x, None, None)

所以我想阻止任何用户更改x坐标。我的问题是,如何让python将用户重定向到set_x()和get_x()方法?我已尝试在终端中运行此代码,每当我应用以下内容时,该点都会发生变化。

p = point(3, 4)
p.x = 5 #x is now 5

2 个答案:

答案 0 :(得分:5)

你只需要这么多:

class Point:
    def __init__(self, x, y):
        self._x = x
        self.y = y
    def get_x(self):
        return self._x
    x = property(get_x)

您可以在self._x中设置隐藏字段init,然后根本不需要x的设置器。并get_x返回self._x而不是self.x,因此它不会尝试自己调用。

您可以使用@property装饰器更简洁地执行此操作。

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

答案 1 :(得分:4)

以下代码适用于python2.x和python3.x:

class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def set_x(self, x):
        if '_x' in dir(self):
            raise NotImplementedError("Cannot change x coordinate")
        else:
            self._x = x

    def get_x(self):
        return self._x

    x = property(get_x, set_x, None, None)

p = Point(2, 3)
print(p.x)  # 2
p.x = 6  # NotImplementedError

我所做的几乎都是从object继承(让它在python2.x上运行)并使用名称Point而不是point(这可能是NameError {1}}之前)。

您还可以采取其他措施进行清理(例如,khelwood建议只写一下吸气剂 - 或DSM建议使用hasattr代替'_x' in dir(self))。


注意,如果你真的只想要一个带有xy参数的类型,你想要它是不可变的 - 也许你应该考虑使用colledctions.namedtuple

from collections import namedtuple

Point = namedtuple('Point', 'x,y')
p = Point(2, 3)
p.x  # 2
p.y  # 3
p.x = 6  # AttributeError: can't set attribute