python - 在Python中使用@property构建一个类

标签 python class optimization coding-style

我不清楚@property的使用(优点和缺点)。我想询问一些使用在 Martijn 的帮助下构建的类的示例.

数据(文本格式)始终具有 xyz 来表征点(1、2 和3 列文本文件)。有时我有一个“classification”(第四列)属性和/或 location(第五列)。取决于文件的处理方式(有时更多属性)。

class Point(object):
    __slots__= ("x", "y", "z", "data", "_classification")
    def __init__(self, x, y, z):
        self.x = float(x)
        self.y = float(y)
        self.z = float(z)
        self.data = [self.x,self.y,self.z]

    @property
    def classification(self):
        return getattr(self, '_classification', None)

    @classification.setter
    def classification(self, value):
        self._classification = value
        if value:
            self.data = self.data[:3] + [value]
        else:
            self.data = self.data[:3]

    def __len__(self):
        return len(self.data)


p = Point(10,20,30)
len(p)
3
p.classification = 1
len(p)
4
p.data
[10.0, 20.0, 30.0, 1]

我希望在已设置分类时添加位置,以便理解使用@property的原理。我尝试使用以下代码,但我不知道这是否是Pythonic:

class Point(object):
    __slots__= ("x", "y", "z", "data", "_classification",'_location')
    def __init__(self, x, y, z):
        self.x = float(x)
        self.y = float(y)
        self.z = float(z)
        self.data = [self.x,self.y,self.z]

    @property
    def classification(self):
        return getattr(self, '_classification', None)

    @classification.setter
    def classification(self, value):
        self._classification = value
        if value:
            self.data = self.data[:3] + [value]
        else:
            self.data = self.data[:3]

    @property
    def location(self):
        return getattr(self, '_location', None)

    @location.setter
    def location(self, value):
        self._location = value
        if value:
            self.data = self.data[:4] + [value]
        else:
            self.data = self.data[:4]

    def __len__(self):
        return len(self.data)



p = Point(10,20,30)
p.classification = 1
p.data
[10.0, 20.0, 30.0, 1]
p.location = 100
p.data
[10.0, 20.0, 30.0, 1, 100]


p = Point(10,20,30)
p.location = 100
p.data
[10.0, 20.0, 30.0, 100]

最佳答案

所以,你的类有效,你只是问它是否是 Pythonic 的。我不是专家,但我会推荐您引用Zen of Python :

Explicit is better than implicit.

对我来说,当您设置一个属性(位置、分类)时,它最终会默默地修改其他属性,这是隐式的,而不是显式的。我认为更好、更容易理解的用例是使用诸如 assign_location 和/或 assign_classification 方法。这样,使用 API 的人就可以知道他不仅仅是在设置属性,而是在调用一个函数,该函数具有解释其作用的文档字符串。

至于该属性的哲学是什么,我不确定它的包含是否基于哲学。属性装饰者所做的就是去掉这样难看的东西:

class Foo:
    def __getattr__(self, attr):
        if attr == 'location':
            ...
        elif attr == 'classification':
            ...

我非常喜欢的一个用途是使用属性来保证线程安全。例如:

class Foo(object):
    def __init__(self):
        self.lock = threading.Lock()
    @property
    def classification(self):
        return self.classification

    @classification.setter
    def classification(self, value):
        with self.lock:
            (something else thread-protected)
            self.classification = value

最后,还有一个建议。除非您知道为什么使用插槽,否则不要这样做。除非您知道为什么需要插槽,否则您不需要它们。

关于python - 在Python中使用@property构建一个类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15138451/

相关文章:

python - 如何将函数的参数作为后缀添加到该函数内的每个变量?

class - 如何设置类中介值并将其传递给 esb

python - 使用 Gekko 的 ARX 模型的 MPC

python - 从 boto 导入 modul2s 时出现问题

python - Django 跟踪匿名用户

c++ - 具有静态变量和函数的 C++ 类中的问题

c++ - 使用以 vector 为输入的递归方法时的段错误

java - Java 是否将除以 2 的幂的除法优化为位移位?

sql - 每个标准的限制

python - 从函数返回控制台对象后,paramiko/Socket 关闭