Python是一个面向对象的编程语言,其属性和特性是类中非常重要的概念,可以通过@property和@
一、@property装饰器
Python中@property装饰器用于将方法转换为只读属性,即对该属性的访问将通过该方法进行获取。被@property装饰的方法只能获取值,无法进行修改。以下是一个例子:
class Test:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
t = Test("Tom")
print(t.name)
在上述例子中,通过@property将name方法转换为只读属性,即无法通过t.name进行修改,只能获取其原始值。在控制台执行上述代码,会输出Test实例的name属性值”Tom”。
二、特性(getter/setter)
特性是实现自定义get和set方法的属性,并允许实现访问和修改属性值。特性是通过使用Python中的装饰器来实现的,例如:@property
装饰器和@<property>.setter
装饰器。以下是一个示例:
class Test:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self, value):
if not isinstance(value, str):
raise TypeError('Expected a string')
self._name = value
t = Test("Tom")
t.name = "Jerry"
print(t.name)
在上述例子中,@property
和@name.setter
将name方法转换为一个特性,实现了访问和修改属性值。在调用t.name = “Jerry”时,实际上是调用了setter方法,将value值赋给了名为_name的实例变量。在控制台执行上述代码,会输出属性值"Jerry"
。
三、属性与特性之间的优先权
Python中,属性比特性优先级更高。即,如果同时在类中定义了一个属性和一个特性,并且使用了相同的名称,那么属性将覆盖特性。以下是一个示例:
class Test:
def __init__(self):
self._name = ""
@property
def name(self):
print("Getting name")
return self._name
@name.setter
def name(self, value):
print("Setting name")
self._name = value
t = Test()
t.name = "Tom" # 将属性值设置为"Tom"
print(t.name) # 输出属性值,不会调用特性的getter方法
在上述例子中,虽然在类中定义了一个特性name,但在使用t.name = “Tom”时,实际上将name视为了一个属性,并将其值设置为”Tom”,而没有调用特性的setter方法。在控制台执行上述代码,输出结果为"Tom"
。
如果想在此示例中调用特性的setter方法并更新属性值,则可以采用以下代码:
class Test:
def __init__(self):
self._name = ""
@property
def name(self):
print("Getting name")
return self._name
@name.setter
def name(self, value):
print("Setting name")
self._name = value
t = Test()
t.name = "Tom" # 设置特性的值
print(t.__dict__["_name"]) # 使用字典获取属性的值
在上述代码中,虽然在调用t.name = “Tom”时,将name视为了一个属性,并将其值设置为”Tom”,但在打印_dict__时,仍然可以看到属性值为”Tom”的部分,因为它是一个实例变量,而特性只是一些关联的方法。在控制台执行上述代码,输出结果为"Tom"
。
总之,当在类中定义一个属性和一个特性时,属性将覆盖特性。因此,在使用时应该谨慎命名属性和特性。