Python: predicate methods as properties?

Using the @property decorator, Python completely eliminated the need for getters and setters for object properties (some might say β€œattributes”). This makes the code much easier, while maintaining extensibility when something needs to be complicated.

I was wondering what the Pythonic approach to the next kind of method is. Let's say I have the following class:

 class A(object): def is_winner(self): return True # typically a more arcane method to determine the answer 

Such methods usually take no arguments and have no side effects. You can call these predicates. And, given their name, they often resemble what could be saved as a property.

I tend to add the @property decorator to the above to be able to call it as an object property (i.e. foo.is_winner ), but I was wondering if this is a standard task. At first glance, I could not find documentation on this issue. Is there a common standard for this situation?

+6
source share
1 answer

It seems that the general consensus is that attributes are usually considered instantaneous and accessible after use, so if a calculation done as @property is expensive, it is probably best to either cache the result for repetition to use (@Martijn Pieters) or leave it as a method, since it is generally expected that methods will take longer than searching for attributes. PEP 8 Notes :

  • Note 2: try to maintain a side effect of functional behavior, although side effects such as caching are generally excellent.

  • Note 3: Avoid using properties for expensive calculation operations; attribute notation makes the subscriber believe that access is (relatively) cheap.


One specific use case for the @property decorator is to add some behavior to the class that does not require class users to change foo.bar calls to foo.bar() calls - for example, if you want to count the number of times the attribute referred to, you you can convert the attribute to @property where the decorated method manages some state before returning the requested data.

Here is an example of the source class:

 class Cat(object): def __init__(self, name): self.name = name # In user code baxter = Cat('Baxter') print(baxter.name) # => Baxter 

Using the @property decorator, we can now add some machines under the hood without affecting the user code:

 class Cat(object): def __init__(self, name): self._name = name self._name_access_count = 0 @property def name(self): self._name_access_count += 1 return self._name # User code remains unchanged baxter = Cat('Baxter') print(baxter.name) # => Baxter # Also have information available about the number of times baxter name was accessed print(baxter._name_access_count) # => 1 baxter.name # => 'Baxter' print(baxter._name_access_count) # => 2 

This processing of the @property decorator is mentioned in some blog posts ( 1 , 2 ) as one of the main use cases, allowing us to write the simplest code first, and then move on to the methods decorated with @, if necessary.

+2
source

Source: https://habr.com/ru/post/984962/


All Articles