【问题标题】:When to use "property" builtin: auxiliary functions and generators何时使用内置“属性”:辅助函数和生成器
【发布时间】:2011-02-15 12:47:53
【问题描述】:

我最近发现了 Python 的 property built-in,它将类方法 getter 和 setter 伪装成类的属性。我现在很想以我很确定不合适的方式使用它。

如果类A 有一个属性_x 你想限制它的允许值,那么使用property 关键字显然是正确的做法;即,它将取代人们可能用 C++ 编写的 getX()setX() 构造。

但是,还有什么地方适合将函数设为属性呢?例如,如果您有

class Vertex(object):
    def __init__(self):
        self.x = 0.0
        self.y = 1.0

class Polygon(object):
    def __init__(self, list_of_vertices):
        self.vertices = list_of_vertices
    def get_vertex_positions(self):
        return zip( *( (v.x,v.y) for v in self.vertices ) )

是否适合添加

    vertex_positions = property( get_vertex_positions )

?

可以让生成器看起来像一个属性吗?想象一下,如果我们的代码更改意味着我们不再以相同的方式存储Polygon.vertices。那么可以将其添加到Polygon 吗?

    @property
    def vertices(self):
        for v in self._new_v_thing:
            yield v.calculate_equivalent_vertex()

【问题讨论】:

    标签: python properties


    【解决方案1】:
    • 当您有一个普通属性并且获取和/或设置它对类的用户有意义时,直接公开该属性。公共成员在某些语言中令人厌恶的一个重要原因是,如果您以后需要做更复杂的事情,则需要更改 API;在 Python 中,您可以只定义一个属性。

    • 如果您使用的东西应该抽象为属性访问,请使用属性。如果你想让外部状态(你的情节或网站或其他东西)知道变化,或者如果你正在包装一些直接使用成员的库,属性可能是要走的路。

    • 如果某些东西不是属性-y,请不要将其设为属性。创建一个方法没有坏处,而且它可能是有利的:它的作用更明显,如果需要,您可以传递一些绑定的方法,您可以添加关键字参数而无需更改 API。

      很难想象我会使用生成器函数作为属性的情况。拥有一个行为完全相似的普通属性的唯一方法需要相当多的复杂性,因此这种情况并不让人想起属性访问。

    • 您指出您可以使用property 来限制对某些内部属性_x 的访问。这可能是真的,但请记住

      • 如果您要为安全或重要的事情清理输入,显式优于隐式。当涉及到这样的事情时,你不想觉得代码可以正常工作,因为那样你就会遇到不能正常工作的代码。

      • 有时人们使用property 来实现只读属性。通常最好只有一个正常的属性,并意识到你不能阻止用户做一些愚蠢和不受支持的事情。

    • 挑剔你可能会觉得有趣:

      • property 不是关键字;这是一个可以重新绑定的普通名称。这是一种 有趣的是,property 不是语法或任何东西:它是一个普通的类,你可以用纯 Python 自己实现。它使用使方法在 Python 中工作的相同机制——descriptors

      • 您将property 的作用描述为“伪装类方法getter 和setter”,但事实并非如此。 property 采用的只是普通函数,根本不需要在你的类中定义; property 将为您传递 self。当 Python 动态创建方法对象时,函数实际上不会成为方法,除非您查找它们。在类定义期间,它们只是函数。当你有一个普通的方法时,它被称为“实例方法”;在 Python 中,“类方法”指的是 another special thing 类似的属性,它会改变查找属性时发生的情况。

    【讨论】:

      【解决方案2】:

      属性的使用有一个明显的限制:它不接受任何参数,而且永远不会接受。

      因此,您必须确保要转换为属性的函数永远不会被重构为具有额外默认参数等的函数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-10
        • 1970-01-01
        • 2011-09-30
        • 2020-10-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多