网站首页 > 基础教程 正文
作者:麦叔
来源:麦叔编程
背景
这是某位麦友提的问题,可惜我忘记记录名字了。如果当事人看到,请在评论留言,我给你置顶,感谢。
?
麦叔之前有讲过python的 __call__(),__get__, __getattr__, __getattribute__这几个方法吗,网上搜索的讲的都不透彻,烦请麦叔讲解下吧
?
其他几个我们都聊过了,今天我们来聊最后一个__get__,以及它的搭档__set__
抛出问题
借用昨天的例子,有一个类Maiyou,它有3个属性:name,age和id_no。
class Maiyou():
def __init__(self,name, age, id_no):
self.name=name
self.age=age
self.id_no = id_no
m1 = Maiyou('Kevin', 18, '1234567890')
print(m1.name)
print(m1.age)
print(m1.id_no)
因为身份证id_no很敏感,我们希望每次读取或者修改这个属性的时候都能打印一句日志,记录一下。
在实际工作中,我们可以在这里做权限控制,只有传入了秘钥才可以访问。今天我们就简化为打印日志。
普通青年的方法
普通的方法,我们可以
- 把这个属性的名字改为_id_no,前面加了下划线,表示是私有变量,外界不能访问。
- 添加专门的访问方法:get_id_no和set_id_no。外面需要访问就通过方法来访问。这也是比较「夹里夹气」的方法。
class Maiyou():
def __init__(self,name, age, id_no):
self.name=name
self.age=age
self._id_no = id_no
def get_id_no(self):
return self._id_no
def set_id_no(self, id_no):
self._id_no = id_no
m1 = Maiyou('Kevin', 18, '1234567890')
print(m1.name)
print(m1.age)
print(m1.get_id_no())
m1.set_id_no('66666666666')
很明显这个方法比较繁琐。
我们可以通过@property装饰器,让它更方便一点,但超出了本3分钟的范围了。因为今天的重点是descriptor,这也是这个场景中最正确的做法。
文艺青年的做法 - 使用descriptor
?
Descriptor,中文名字是描述器。它是一种特殊的类,它的作用是用来封装一个属性。它的特征就是需要有__get__和__set__函数
?
我们来看一下使用了descriptor的例子:
class IdDescriptor:
def __get__(self, obj, objtype=None):
value = obj._id_no
print(f'获取age: {value}')
return value
def __set__(self, obj, value):
obj._id_no = value
print(f'age从{obj._id_no}更新为: {value}')
class Maiyou():
id_no = IdDescriptor()
def __init__(self,name, age, id_no):
self.name=name
self.age=age
self.id_no = id_no
m1 = Maiyou('Kevin', 18, '1234567890')
m1.id_no
m1.id_no = '66666666666'
m2 = Maiyou('Yushao', 16, '9876543210')
m1.id_no
m1.id_no = '888888888'
输出结果:
age从1234567890更新为: 1234567890
获取age: 1234567890
age从66666666666更新为: 66666666666
age从9876543210更新为: 9876543210
获取age: 66666666666
age从888888888更新为: 888888888
解释一下:
- 我们定义了一个描述器类IdDescriptor来表示身份证号。它提供了__get__和__set__方法,用于设置属性的值。
- 它的set方法会给当前对象设置一个私有属性,并且打印日志;它的get方法会返回当前对象的私有属性。
- 在Maiyou类中,我们创建了一个描述器实例作为类属性id_no。这样每次调用这个属性的时候,就会触发相应的set和get方法。
可能知识稍微有点深,因为麦友的水平也正在逐步加深。多看两遍,细细品味,有问题给我留言。
猜你喜欢
- 2024-10-31 如何用 GitHub Actions 写出高质量的 Python代码?
- 2024-10-31 Python集成ActiveMQ,异步发送处理消息,详细代码手把手操作
- 2024-10-31 python 魔法方法连载三 __setattr()__
- 2024-10-31 CentOS 7下编译安装Python3 centos7安装python3.7
- 2024-10-31 3分钟掌握Python 中的集合 python中集合的概念
- 2024-10-31 Python3 集合 python 集合 discard
- 2024-10-31 群晖安装python3 群晖安装python3.7
- 2024-10-31 十六、Python集合set常用方法 python set集合和list集合的区别
- 2024-10-31 python数据类型-集合set python set集合取值
- 2024-10-31 python笔记18:set 集合 python set集合取值
- 最近发表
- 标签列表
-
- jsp (69)
- gitpush (78)
- gitreset (66)
- python字典 (67)
- dockercp (63)
- gitclone命令 (63)
- dockersave (62)
- linux命令大全 (65)
- pythonif (86)
- location.href (69)
- dockerexec (65)
- tail-f (79)
- queryselectorall (63)
- location.search (79)
- bootstrap教程 (74)
- 单例 (62)
- linuxgzip (68)
- 字符串连接 (73)
- html标签 (69)
- c++初始化列表 (64)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)