IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Python同时使用@property和classmethod -> 正文阅读

[Python知识库]Python同时使用@property和classmethod

首先给出代码,其中元类“MyMetaclass”的第三个方法“property_classMethod”同时实现了@property和classmethod,print函数的结果注释在对应语句后面。

class MyMetaclass(type):
    __myDict = {'a': 1, 'b': 2}

    @classmethod
    def classMethod(cls, key):
        return cls.__myDict.get(key, 0)

    @property
    def propertyMethod(self):
        return 1

    @property
    def property_classMethod(cls):
        return cls.__myDict


class Myclass(metaclass=MyMetaclass):
    pass


print(type(MyMetaclass))  # <class 'type'>
print(type(Myclass))  # <class '__main__.MyMetaclass'>
print(type(Myclass()))  # <class '__main__.Myclass'>

# 调用MyMetaclass类方法
print(MyMetaclass.classMethod('a'))  # 1
# 调用Myclass类方法
print(Myclass.classMethod('a'))  # 1

# 打印MyMetaclass.property_classMethod类型
print(type(MyMetaclass.property_classMethod))  # <class 'property'>
# 打印Myclass.property_classMethod类型
print(type(Myclass.property_classMethod))  # <class 'dict'>

# 调用MyMetaclass类属性
print(MyMetaclass.property_classMethod)  # <property object at 0x000002CEF052A958>
# 调用Myclass类属性
print(Myclass.property_classMethod)  # {'a': 1, 'b': 2}

参考链接_作者:p不忘初心q

个人理解

Python类中有三个常用的装饰器,分别是

  1. @property(使一个方法可以被当成属性调用,常用于直接返回某一不想被修改的属性)
  2. @classmethod(将一个方法定义为类方法,其中第一个参数要修改为cls,使得该方法可以不用实例化即可被调用)
  3. @staticmethod(静态方法,类似于类方法,也可以不用实例化,只不过该方法恰好处于类中)

其中@property和@classmethod较常用于制作Python的库,使得类被调用时可以更灵活、更安全。

@staticmethod
def staticMethod():
	print(1)

@classmethod
def classMethod(cls, key):
    return cls.__myDict.get(key, 0)

@property
def propertyMethod(self):
    return 1

@classmethod常用于一些类无需被实例化的场景,大量使用时该类可以看做是一组方法的集合。而有时又想要使一个直接返回一个私有类属性,换句话说想要在不创建对象的情况下返回一个不想被更改的“类”属性。这时就需要同时使用@property和classmethod,尝试了一下下面的写法,果然不行

@property
@classmethod
def property_classMethod(cls):
    return cls.__myDict

因为带有“cls”并装饰有“@classmethod”的类方法调用时方法必须带有调用括号(),这时该方法才会被绑定到类;
而装饰有“@property”的方法调用时不能带括号(被当做一个属性,not callable),会自动绑定到实例;
因此需要一个实例化对象调用此方法,并使得对象调用时自动绑定到类来实现classmethod。

上面的说法看起来很矛盾,因为前面已经提到了不创建对象,怎么这里又创建对象了呢?直到看到上面那篇博客突然想到还有“元类”这个东西。元类的解释很复杂,想要深入了解的话不是一两句能解释得通的,这里暂且理解为定义类的类,在定义类的时候指定“metaclass”参数即可指定元类。

这里为什么要使用元类呢,因为装饰有“@property”的方法需要实例化对象来调用,而我们又不想创建对象,恰好被元类定义的类也是元类的一个实例(Python特性,详细了解需自行查询),因此我们使用元类定义的类直接调用@property方法相当于元类的对象在调用@property方法。同时因为是现在是对象在调用@property方法,并且在定义方法时添加了“cls”参数,因此程序会自动将该方法绑定到元类,实现了classmethod的功能。

为了验证上面的解释,打印了以下参数

print(type(MyMetaclass))  # <class 'type'>
print(type(Myclass))  # <class '__main__.MyMetaclass'>
print(type(Myclass()))  # <class '__main__.Myclass'>

# 调用MyMetaclass类方法
print(MyMetaclass.classMethod('a'))  # 1
# 调用Myclass类方法
print(Myclass.classMethod('a'))  # 1

# 打印MyMetaclass.property_classMethod类型
print(type(MyMetaclass.property_classMethod))  # 因为没有实例化,所以是<class 'property'>
# 打印Myclass.property_classMethod类型
print(type(Myclass.property_classMethod))  # 因为已经实例化,所以是<class 'dict'>

# 调用MyMetaclass类属性
print(MyMetaclass.property_classMethod)  # <property object at 0x000002CEF052A958>
# 调用Myclass类属性
print(Myclass.property_classMethod)  # {'a': 1, 'b': 2}
  1. MyMetaclass 继承自 type,因此 type(MyMetaclass) 结果是 <class ‘type’>;
  2. Myclass 由 MyMetaclass 创建,因此 Myclass 是 MyMetaclass 的对象,所以 type(Myclass) 结果是 <class ‘main.MyMetaclass’>;
  3. Myclass() 是 Myclass 的对象,因此 type(Myclass()) 结果是 <class ‘main.Myclass’>;
  4. classMethod 是类方法,无论 Myclass 还是 MyMetaclass调用结果都相同;
  5. property_classMethod 是直接返回类属性的类方法,当做属性调用,因为MyMetaclass.property_classMethod 未创建实例,所以返回 <property object at 0x000002CEF052A958> (类型为 <class ‘property’>),表示这个方法没有被调用。而 Myclass.property_classMethod 相当于创建了实例,因此返回该方法的返回值 {‘a’: 1, ‘b’: 2} (类型为 <class ‘dict’>)。

一些个人理解,可能有不对的地方欢迎指出。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:25:01  更:2022-02-28 15:28:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/31 6:35:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码