在学习python的类和对象相关是写了如下的代码:
class Dog:
def __init__(self, name, age, sex = '雌性'):
self.name = name
self.__age = age
self.sex = sex
#实例方法
def run(self):
print('{}在跑...'.format(self.name))
#实例方法
def speak(self, sound):
print('{}在叫,"{}"!'.format(self.name, sound))
@property
def age(self):
return self.__age
@age.setter
def age(self, age):
self.__age = age
dog = Dog('球球', 2)
print('狗狗年龄:{}'.format(dog.age()))
dog.age = 3
print('修改后的狗狗年龄:{}'.format(dog.age()))
但在运行时遇到了如下的错误:
Traceback (most recent call last):
File "D:/learnpython/chapter9/ch9_5_3_2.py", line 24, in <module>
print('狗狗年龄:{}'.format(dog.age()))
TypeError: 'int' object is not callable
错误发生在 dog.age()
这一行,提示 'int' object is not callable
,意思是“整数对象不可调用”。这表明 Python 认为 dog.age
是一个整数,但我们试图用 ()
来调用它(就像调用函数一样),而整数是不能被调用的。
问题根源
问题出在使用了 @property
装饰器。@property
的作用是将方法转换为“属性”,这样可以像访问属性一样访问它,而不需要加括号。具体来说:
1. 当你定义
@property
def age(self):
return self.__age
这表示 age
是一个“只读”属性(除非你定义了 setter),可以直接 dog.age
来获取值,而不是 dog.age()
。
2. 同样,@age.setter
允许你直接赋值:
dog.age = 3
而不是调用一个方法。
解决方案
去掉 dog.age
后面的括号即可
关键点总结
-
@property
的作用:-
将方法转换为属性,可以直接通过
obj.property
访问,而不是obj.property()
。 -
通常用于封装私有变量,提供更可控的访问方式。
-
-
@property
和@xxx.setter
的配套使用:-
@property
定义 getter 方法。 -
@xxx.setter
定义 setter 方法,允许修改属性。
-
-
调用时的区别:
-
普通方法:
obj.method()
-
属性方法:
obj.property
(不加括号)
-
补充说明
如果你希望 age
是一个方法而不是属性,可以去掉 @property
:
def get_age(self):
return self.__age
def set_age(self, age):
self.__age = age
然后调用:
print(dog.get_age())
dog.set_age(3)
但 Python 更推荐用 @property
的方式,因为它更符合“统一访问原则”(属性访问和方法访问语法一致)。