@property和传统的getter和setter都有各自的优点。这取决于您的用例。
@property的优点
You don't have to change the interface while changing the implementation of data access. When your project is small, you probably want to use direct attribute access to access a class member. For example, let's say you have an object foo of type Foo, which has a member num. Then you can simply get this member with num = foo.num. As your project grows, you may feel like there needs to be some checks or debugs on the simple attribute access. Then you can do that with a @property within the class. The data access interface remains the same so that there is no need to modify client code.
Cited from PEP-8:
For simple public data attributes, it is best to expose just the attribute name, without complicated accessor/mutator methods. Keep in mind that Python provides an easy path to future enhancement, should you find that a simple data attribute needs to grow functional behavior. In that case, use properties to hide functional implementation behind simple data attribute access syntax.
Using @property for data access in Python is regarded as Pythonic:
It can strengthen your self-identification as a Python (not Java) programmer.
It can help your job interview if your interviewer thinks Java-style getters and setters are anti-patterns.
传统getter和setter的优点
Traditional getters and setters allow for more complicated data access than simple attribute access. For example, when you are setting a class member, sometimes you need a flag indicating where you would like to force this operation even if something doesn't look perfect. While it is not obvious how to augment a direct member access like foo.num = num, You can easily augment your traditional setter with an additional force parameter:
def Foo:
def set_num(self, num, force=False):
...
Traditional getters and setters make it explicit that a class member access is through a method. This means:
What you get as the result may not be the same as what is exactly stored within that class.
Even if the access looks like a simple attribute access, the performance can vary greatly from that.
Unless your class users expect a @property hiding behind every attribute access statement, making such things explicit can help minimize your class users surprises.
As mentioned by @NeilenMarais and in this post, extending traditional getters and setters in subclasses is easier than extending properties.
Traditional getters and setters have been widely used for a long time in different languages. If you have people from different backgrounds in your team, they look more familiar than @property. Also, as your project grows, if you may need to migrate from Python to another language that doesn't have @property, using traditional getters and setters would make the migration smoother.
警告
Neither @property nor traditional getters and setters makes the class member private, even if you use double underscore before its name:
class Foo:
def __init__(self):
self.__num = 0
@property
def num(self):
return self.__num
@num.setter
def num(self, num):
self.__num = num
def get_num(self):
return self.__num
def set_num(self, num):
self.__num = num
foo = Foo()
print(foo.num) # output: 0
print(foo.get_num()) # output: 0
print(foo._Foo__num) # output: 0