关于如何在 python 中使用属性功能的真实示例?
我对如何在 Python 中使用 @property
感兴趣。我已经阅读了 python 文档,并且其中的示例在我看来只是一个玩具代码:
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
我不知道通过包装用属性装饰器填充的 _x
可以获得什么好处。为什么不直接实现为:
class C(object):
def __init__(self):
self.x = None
我认为,属性功能在某些情况下可能很有用。但什么时候呢?有人可以给我一些现实世界的例子吗?
I am interested in how to use @property
in Python. I've read the python docs and the example there, in my opinion, is just a toy code:
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
I do not know what benefit(s) I can get from wrapping the _x
filled with the property decorator. Why not just implement as:
class C(object):
def __init__(self):
self.x = None
I think, the property feature might be useful in some situations. But when? Could someone please give me some real-world examples?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
其他示例包括验证/过滤设置的属性(强制它们在范围内或可接受的范围内)以及复杂或快速变化的术语的惰性评估。
隐藏在属性后面的复杂计算:
验证:
Other examples would be validation/filtering of the set attributes (forcing them to be in bounds or acceptable) and lazy evaluation of complex or rapidly changing terms.
Complex calculation hidden behind an attribute:
Validation:
一个简单的用例是设置一个只读实例属性,正如您所知,在 python 中用一个下划线
_x
开头的变量名称通常意味着它是私有(内部使用),但是有时我们希望能够读取实例属性而不是写入它,因此我们可以使用property
来实现:One simple use case will be to set a read only instance attribute , as you know leading a variable name with one underscore
_x
in python usually mean it's private (internal use) but sometimes we want to be able to read the instance attribute and not to write it so we can useproperty
for this:查看这篇文章了解非常实际的用途。简而言之,它解释了在 Python 中您通常如何放弃显式的 getter/setter 方法,因为如果您在某个阶段需要它们,您可以使用
property
进行无缝实现。Take a look at this article for a very practical use. In short, it explains how in Python you can usually ditch explicit getter/setter method, since if you come to need them at some stage you can use
property
for a seamless implementation.我使用它的一件事是缓存存储在数据库中的查找缓慢但不变的值。这适用于您的属性需要计算或其他一些您只想按需执行的长时间操作(例如数据库检查、网络通信)的情况。
这是在一个 Web 应用程序中,任何给定的页面视图可能只需要这种类型的一个特定属性,但底层对象本身可能有几个这样的属性 - 在构造时将它们全部初始化会很浪费,而属性允许我灵活地使用属性是惰性的,哪些不是。
One thing I've used it for is caching slow-to-look-up, but unchanging, values stored in a database. This generalises to any situation where your attributes require computation or some other long operation (eg. database check, network communication) which you only want to do on demand.
This was in a web app where any given page view might only need one particular attribute of this kind, but the underlying objects themselves might have several such attributes - initialising them all on construction would be wasteful, and properties allow me to be flexible in which attributes are lazy and which aren't.
阅读答案和评论,主题似乎是答案似乎缺少一个简单但有用的示例。我在这里包含了一个非常简单的示例,演示了
@property
装饰器的简单使用。该类允许用户使用各种不同的单位(即in_feet
或in_metres
)指定和获取距离测量值。用法:
Reading through the answers and comments, the main theme seems to be the answers seem to be missing a simple, yet useful example. I have included a very simple one here that demonstrates the simple use of the
@property
decorator. It's a class that allows a user to specify and get distance measurement using a variety of different units, i.e.in_feet
orin_metres
.Usage:
属性只是围绕字段的抽象,它使您可以更好地控制特定字段的操作方式以及进行中间件计算。我想到的很少有用法是验证、事先初始化和访问限制
Property is just an abstraction around a field which give you more control on ways that a specific field can be manipulated and to do middleware computations. Few of the usages that come to mind is validation and prior initialization and access restriction
与使用 setter 和 getter 相比,属性的另一个很好的功能是它们允许您继续在您的代码上使用 OP= 运算符(例如 +=、-=、*= 等)
属性,同时仍然保留 setter 和 getter 将提供的任何验证、访问控制、缓存等。
例如,如果您使用 setter
setage(newage)
和 gettergetage()
编写类Person
,那么要增加您的年龄必须写:但是如果你将
age
设为一个属性,你可以写得更清晰:another nice feature of properties over using setters and getters it that they allow you to continue to use OP= operators (eg +=, -=, *= etc) on your
attributes while still retaining any validation, access control, caching, etc that the setters and getters would supply.
for example if you wrote the class
Person
with a settersetage(newage)
, and a gettergetage()
, then to increment the age you would have to write:but if you made
age
a property you could write the much cleaner:是的,对于发布的原始示例,该属性的工作方式与仅具有实例变量“x”完全相同。
这是Python属性中最好的一点。从外部看,它们的工作方式与实例变量完全相同!这允许您使用类外部的实例变量。
这意味着您的第一个示例实际上可以使用实例变量。如果事情发生了变化,然后您决定更改实现并且属性很有用,则该属性的接口与类外部的代码仍然相同。 从实例变量到属性的更改对类外部的代码没有影响。
许多其他语言和编程课程将指示程序员永远不要公开实例变量,而应使用“getters”和“setters”对于从类外部访问的任何值,即使是问题中引用的简单情况。
许多语言(例如Java)使用类外部的代码
并且在实现类时,有许多“getters”和“setters”,它们的作用与您的第一个示例完全相同:复制一个简单的实例变量。这些 getter 和 setter 是必需的,因为如果类实现发生更改,则类外部的所有代码都需要更改。
但Python属性允许类外的代码与实例变量相同。因此,如果添加属性或具有简单的实例变量,则不需要更改类外部的代码。
因此,与大多数面向对象的语言不同,对于您的简单示例,您可以使用实例变量而不是真正不需要的“getters”和“setters”,这在知识上是安全的如果您将来更改某个属性,则使用您的类的代码无需更改。
这意味着如果存在复杂的行为,您只需要创建属性,并且对于非常常见的简单情况,如问题中所述,只需要一个简单的实例变量,您只需使用实例变量即可。
Yes, for the original example posted, the property will work exactly the same as simply having an instance variable 'x'.
This is the best thing about python properties. From the outside, they work exactly like instance variables! Which allows you to use instance variables from outside the class.
This means your first example could actually use an instance variable. If things changed, and then you decide to change your implementation and a property is useful, the interface to the property would still be the same from code outside the class. A change from instance variable to property has no impact on code outside the class.
Many other languages and programming courses will instruct that a programmer should never expose instance variables, and instead use 'getters' and 'setters' for any value to be accessed from outside the class, even the simple case as quoted in the question.
Code outside the class with many languages (e.g. Java) use
And when implementing the class there are many 'getters' and 'setters' that do exactly as your first example: replicate a simply instance variable. These getters and setters are required because if the class implementation changes, all the code outside the class will need to change.
But python properties allow code outside the class to be the same as with instance variables. So code outside the class does not need to be changed if you add a property, or have a simple instance variable.
So unlike most Object Oriented languages, for your simple example you can use the instance variable instead of 'getters' and 'setters' that are really not needed, secure in the knowledge that if you change to a property in the future, the code using your class need not change.
This means you only need create properties if there is complex behaviour, and for the very common simple case where, as described in the question, a simple instance variable is all that is needed, you can just use the instance variable.
对你的问题的简短回答是,在你的例子中,没有任何好处。您可能应该使用不涉及属性的形式。
属性存在的原因是,如果您的代码将来发生更改,并且您突然需要对数据执行更多操作:缓存值、保护访问、查询某些外部资源......无论如何,您可以轻松修改您的类以添加 getter和数据的设置器而无需更改接口,因此您不必在代码中找到访问该数据的所有位置并对其进行更改。
The short answer to your question, is that in your example, there is no benefit. You should probably use the form that doesn't involve properties.
The reason properties exists, is that if your code changes in the future, and you suddenly need to do more with your data: cache values, protect access, query some external resource... whatever, you can easily modify your class to add getters and setters for the data without changing the interface, so you don't have to find everywhere in your code where that data is accessed and change that too.
许多人一开始没有注意到的是,您可以创建自己的财产子类。我发现这对于公开只读对象属性或可以读取和写入但不能删除的属性非常有用。这也是包装功能(例如跟踪对象字段修改)的绝佳方法。
Something that many do not notice at first is that you can make your own subclasses of property. This I have found very useful for exposing read only object attributes or attribute you can read and write but not remove. It is also an excellent way to wrap functionality like tracking modifications to object fields.