何时使用"属性"内置:辅助功能和生成器

Set*_*son 9 python properties

我最近发现了Python的property内置函数,它将类方法getter和setter伪装成类的属性.我现在很想以我认为不合适的方式使用它.

property如果类A具有_x您想要限制的允许值的属性,那么使用关键字显然是正确的做法; 即,它将取代用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 ) )
Run Code Online (Sandbox Code Playgroud)

是否适合添加

    vertex_positions = property( get_vertex_positions )
Run Code Online (Sandbox Code Playgroud)

让发电机看起来像财产一样可以吗?想象一下,如果我们的代码中的更改意味着我们不再Polygon.vertices以相同的方式存储.那么添加它可以Polygon吗?

    @property
    def vertices(self):
        for v in self._new_v_thing:
            yield v.calculate_equivalent_vertex()
Run Code Online (Sandbox Code Playgroud)

Mik*_*ham 14

  • 如果您具有普通属性并且获取和/或设置它对于类的用户有意义,则直接公开该属性.公共成员在某些语言中诅咒的一个重要原因是,如果您以后需要做一些更复杂的事情,那么您需要进行API更改; 在Python中,您可以定义一个属性.

  • 如果您正在使用某些内容,则应将其抽象为属性访问,请使用property.如果你想让外部状态(你的情节或网站或其他东西)意识到这种变化,或者如果你要包装一些直接使用成员的库,那么属性可能就是你想要的.

  • 如果某些东西不是属性-y,请不要将其作为属性.制作方法没有坏处,它可能是有利的:它的作用更明显,如果需要,可以传递一些绑定方法,可以在不更改API的情况下添加关键字参数.

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

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

    • 如果您要执行诸如清理输入以确保安全性或重要事项,那么显式优于隐式.当你遇到这样的事情时,你不希望感觉代码只是工作,因为那样你就会遇到没有的代码.

    • 有时人们会使用它property来实现只读属性.通常更好的方法是拥有一个普通的属性,并意识到你无法阻止用户做一些愚蠢和不受支持的事情.

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

    • property不是关键字; 这是你可以重新绑定的正常名称.这很有意思,因为property它不是语法或任何东西:它是一个普通的类,你可以用纯Python实现自己.它使用相同的机制使方法在Python 描述符中起作用.

    • 你描述了什么property是"伪装类方法getter和setter",但事实并非如此.所property采取的只是正常的功能,根本不需要在你的班级中定义; propertyself为你而过.在Python中查找它们时,函数实际上不会成为方法,而是Python在运行时创建方法对象.在类定义期间,它们只是函数.当你有一个普通的方法时,它被称为"实例方法"; 在Python中,"类方法"指的是另一种特殊的东西,它类似于属性,可以改变查找属性时发生的情况.