实例对象.实例属性
class PoloBlog:
# 构造方法
def __init__(self, name):
self.name = name
blog = PoloBlog("小菠萝")
# 破坏了封装原则
print(blog.name)
blog.name = "啊?"
print(blog.name)
# 输出结果
小菠萝
啊?
class PoloBlog:
# 构造方法
def __init__(self, name):
self.name = name
# set 属性的方法【setter】
def setName(self, name):
self.name = name
# get 属性的方法【getter】
def getName(self):
return self.name
blog = PoloBlog("小菠萝")
# 获取 blog 实例对象的 name 实例属性
print(blog.getName())
# 设置 name 实例属性
blog.setName("新的小菠萝")
print(blog.getName())
# 输出结果
小菠萝
新的小菠萝
这样跟 java 的写法就差不多了,但还是有点麻烦
可以实现在不破坏类封装原则的前提下,让开发者依旧使用 对例对象.属性 的方式操作类中的属性
属性名 = property(fget=None, fset=None, fdel=None, doc=None)
# property() 函数
class PoloBlog:
# 构造函数
def __init__(self, name):
self.__name = name
# setter
def setName(self, name):
self.__name = name
# getter
def getName(self):
return self.__name
# del
def delName(self):
self.__name = "xxx"
# property()
name = property(getName, setName, delName, "小菠萝测试笔记")
# 调用说明文档
# help(PoloBlog.name)
print(PoloBlog.name.__doc__)
blog = PoloBlog("小菠萝")
# 自动调用 getName()
print(blog.name)
# 自动调用 setName()
blog.name = "新的小菠萝"
print(blog.name)
# 自动调用 delName()
del blog.name
print(blog.name)
# 输出结果
小菠萝测试笔记
小菠萝
新的小菠萝
xxx
getName return 的是私有属性 __name,注意不是 name,不然会陷入死循环
property() 方法的四个参数都是默认参数,可以不传参
# property() 函数
class PoloBlog:
# 构造函数
def __init__(self, name, age):
self.__name = name
self.__age = age
# setter name
def setName(self, name):
self.__name = name
# getter name
def getName(self):
return self.__name
# del name
def delName(self):
self.__name = "xxx"
# setter age
def setAge(self, age):
self.__age = age
# getter age
def getAge(self):
return self.__age
# property()
name = property(getName, setName, delName, "小菠萝测试笔记")
# 没有 fdel、doc
age = property(getAge, setAge)
blog = PoloBlog("小菠萝", 14)
print(blog.age)
blog.age = "24"
print(blog.age)
del blog.age
print(blog.age)
# 输出结果
14
24
del blog.age
AttributeError: can't delete attribute
因为 property() 没有传 fdel 方法,所以无法删除属性,它是一个可读写,不可删的属性
name = property(getName) # name 属性可读,不可写,也不能删除
name = property(getName, setName,delName) #name属性可读、可写、也可删除,就是没有说明文档
# @property
class PoloBlog:
def __init__(self, name):
self.__name = name
@property
def name(self):
return self.__name
blog = PoloBlog("小菠萝")
print(blog.name)
blog.name = "test"
# 输出结果
小菠萝
blog.name = "test"
AttributeError: can't set attribute
name 是一个只读属性,不可写,相当于 __name 私有属性只有 getter 方法,没有 setter 方法
class PoloBlog:
def __init__(self, name):
self.__name = name
def getName(self):
return self.__name
name = property(getName)
blog = PoloBlog("小菠萝")
print(blog.name)
那想给 __name 设置值怎么办呢?
@方法名.setter
def 方法名(self, value):
self.__value = value
...
# @setter
class PoloBlog:
def __init__(self, name):
self.__name = name
@property
def name(self):
return self.__name
@name.setter
def name(self, name):
self.__name = name
blog = PoloBlog("小菠萝")
# 打印属性值
print(blog.name)
# 修改属性
blog.name = "新的小菠萝"
print(blog.name)
# 输出结果
小菠萝
新的小菠萝
和 setter 装饰器差不多写法
@方法名.deleter
def 方法名(self):
...
class PoloBlog:
def __init__(self, name):
self.__name = name
@property
def name(self):
return self.__name
@name.setter
def name(self, name):
self.__name = name
@name.deleter
def name(self):
print("删除 __name")
blog = PoloBlog("小菠萝")
# 打印属性值
print(blog.name)
# 修改属性
blog.name = "新的小菠萝"
# 删除属性
del blog.name
# 输出结果
小菠萝
删除 __name
加了 @property 的方法相当于一个实例属性,所以不能和其他实例属性重名
class A:
def __init__(self):
# 已经定义了 name 实例属性
self.name = 2
# 这里相当于也定义了一个 name 实例属性
@property
def name(self):
return self.name
@name.setter
def name(self, name):
self.name = name
a = A()
print(a.name)
# 输出结果
Traceback (most recent call last):
File "/Users/polo/Documents/pylearn/第四章:面向对象/17_实战5.py", line 26, in <module>
a = A()
File "/Users/polo/Documents/pylearn/第四章:面向对象/17_实战5.py", line 14, in __init__
self.name = 2
File "/Users/polo/Documents/pylearn/第四章:面向对象/17_实战5.py", line 23, in name
self.name = name
File "/Users/polo/Documents/pylearn/第四章:面向对象/17_实战5.py", line 23, in name
self.name = name
File "/Users/polo/Documents/pylearn/第四章:面向对象/17_实战5.py", line 23, in name
self.name = name
[Previous line repeated 994 more times]
RecursionError: maximum recursion depth exceeded
报错翻译:递归错误 超过最大递归深度
其实就是因为命名冲突导致了死循环
改下命名就好了
class A:
def __init__(self):
# 已经定义了 name 实例属性
self.name = 2
# 这里相当于也定义了一个 name 实例属性
@property
def name_func(self):
return self.name
@name_func.setter
def name_func(self, name):
self.name = name
a = A()
print(a.name)
# 输出结果
2