Python描述器(Python Descriptors)

Python 描述器 Descriptors 详解 Python 描述器 Descriptors 详解1、概念介绍2、通过示例验证2.1 正常的属性访问2.2 非数据描述器且实例没有同名属性2.3 非数据描述器且实例有同名属性2.4 数据描述器且实例有同名属性2.5 数据描述器且实例有同名属性,验证属性查找顺序,无限递归2.6 数据描述器且实例有同名属性,验证属性查找顺序,解决无限递归2.7 数据描述器且实例有同名属性,禁止实例同名属性覆盖2.8 `__set_name__`3、描述器应用 1、概念介绍 描述器 是两个之间的事 描述器一般会用到4 阅读详情

描述器 Descriptors

定义

  • 在Python中,类中实现了魔术方法__get__ __set__ __delete__三者中其一则称其为描述器。
  • 当一个类的属性为描述器时,访问这些属性会受到以上三者的控制。

魔术方法

只有当实现的类作为一个类的属性时,以下方法才起作用

实现__get__方法则称为非数据描述器

实现__get__和其他二者其一称为数据描述器

方法参数作用
__get__instance:属主实例
owner:属主类型
当实现类作为类属性时,通过类或者实例访问该属性时会调用该方法。访问到的值为该方法的返回值。
__set__instance
value:要修改的值,即等号右侧的值
当实现类作为类属性时,通过实例修改该属性时会调用该方法。实现该方法后,实例访问描述器属性时会优先访问类的。
__delete__instance当实现类作为类属性时,通过实例删除该属性时会调用该方法。实现该方法后,实例访问描述器属性时会优先访问类的。
class A:

    def __get__(self, instance, owner):
        print('get')

    def __set__(self, instance, value):
        print('set')

    def __delete__(self, instance):
        print('delelte')


class B:

    a = A()

b = B()

B.a
b.a
b.a = 1
del b.a

>>>get              
>>>get
>>>set
>>>delelte

通过B的类或实例在访问类的属性a时,由于a的类定义了__get__方法,会对其调用。

由于A定义了__set__方法,B的实例访问a属性时会优先访问类的属性,此时会调用__set__方法,而不会给实例新增属性。

作用

装饰器property

通过使用装饰器property,可以像访问类属性的方式来调用get、set、del方法,对属性访问加以控制。

class Property:
    
    def __init__(self, getter, setter=None, deleter=None):
        self.__get = getter
        self.__set = setter
        self.__del = deleter

    def setter(self, set):
        self.__set = set

        return self

    def deleter(self, dele):
        self.__del = dele

        return self

    def __get__(self, instance, owner):
        return self.__get(instance)

    def __set__(self, instance, value):
        self.__set(instance, value)

    def __delete__(self, instance):
        self.__del(instance)
        
class A():

    def __init__(self):
        self.__x = 1

    @Property
    def x(self):
        return self.__x

    @x.setter
    def x(self, value):
        self.__x = value

    @x.deleter
    def x(self):
        del self.__x

a = A()
a.x

>>>1
  • 在装饰get方法时,会调用Property类的初始化方法,将get方法加入到Property实例中,并返回Property实例对象。

  • 通过返回的Property实例调用类方法setter和deleter来装饰set方法和del方法,返回值必须是该Property实例对象。

  • 在A的属性中,x始终是一个Property对象。Property类是一个描述器,当使用实例来访问和修改属性时,就会调用Property的__get__ __set__ __delete__中的对应方法,在这些方法中会调用实例传进来的对应方法,从而达到像直接操作属性一般的效果。

类型检查

class Typed:

    def __init__(self, name, type):
        self.name = name
        self.type = type

    def __get__(self, instance, owner):

        return instance.__dict__[self.name] # 只能通过字典来访问 其他方式都会触发__get__方法

    def __set__(self, instance, value):

        print(value,self.type,self.name)
        if isinstance(value, self.type):
            instance.__dict__[self.name] = value
        else:
            raise TypeError('{} must {} type'.format(self.name, self.type))

    def __delete__(self, instance):

        del instance.__dict__[self.name]


class Test():

    name = Typed('name', str)
    age = Typed('age', int)
    def __init__(self, name, age):
        self.name = name
        self.age = age

利用描述器的特性,对类添加属性来控制实例的同名变量的修改。

直接在类中添加不够优雅

  • 使用inspect模块中来查看参数注解,自动来获取参数名以及类型数据
  • 使用装饰器来注入属性
import inspect


class Typed:

    def __init__(self, name, type):
        self.name = name
        self.type = type

    def __get__(self, instance, owner):

        return instance.__dict__[self.name]

    def __set__(self, instance, value):

        # print(value,self.type,self.name)
        if isinstance(value, self.type):
            instance.__dict__[self.name] = value
        else:
            raise TypeError('{} must {} type'.format(self.name, self.type))

    def __delete__(self, instance):

        del instance.__dict__[self.name]

# 使用函数装饰器,检查类初始化函数的参数名和类型注解来初始化Typed类动态写入到类中,并将其返回
def typeAssert(cls): 
    parameters = inspect.signature(cls).parameters

    for name, par in parameters.items():
        if par.annotation != par.empty:
            setattr(cls, name, Typed(name, par.annotation))

    return cls


# 使用类来做装饰器,将会返回一个对象。当把该实例当作类来实例化对象时,会在__call__中返回一个被装饰的类的实例
class TypeAssert:

    def __init__(self, cls):

        parameters = inspect.signature(cls).parameters
        for name, par in parameters.items():
            if par.annotation != par.empty:
                setattr(cls, name, Typed(name, par.annotation))
        self.__cls = cls

    def __call__(self, *args, **kwargs):

        return self.__cls(*args, **kwargs)


@TypeAssert
class Test():

    # name = Typed('name', str)
    # age = Typed('age', int)
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age
Python中的描述器(Descriptors) 文章目录Python中的描述器(Descriptors)描述器的表现描述器非数据描述器数据描述器带`__set__`的数据描述器带`__delete__`的数据描述器Python中常见的描述器练习 Python中的描述器(Descriptors) 描述器的表现 魔术方法 说明 __get__(self,instance,owner) 获取所有者的属性,定义了该函数,那么... 阅读详情

相关推荐

Python中的描述器Descriptors in Python)是一种强大的工具,用于在中管理属性的访问和赋值操作

Python中的描述器Descriptors in Python)是一种强大的工具,用于在中管理属性的访问和赋值操作。描述器提供了一种机制,通过定义特定的方法来控制属性的读取、写入和删除行为。总结一下,Python中的描述器是一种强大的机制,用于管理属性的访问和赋值操作。它们可以帮助我们实现属性级别的自定义逻辑,并在属性操作时执行相应的方法。当我们尝试访问或修改的属性时,描述器会拦截这些操作,并调用相应的方法来处理。的属性,它是我们刚刚定义的描述器的实例。在上面的示例中,我们定义了一个名为。

PixelShadeZ的博客 106

什么是python 描述符(descriptor)

采用property实现描述符与使用实现描述符的作用是一样的,只是实现方式不一样。留心的你发现property里面还有getter,setter,deleter方法,那他们是做什么用的呢?此时,你有没有发现描述符似曾相识,没错,用过Django就知道在定义model的时候,就用到了描述符。的访问方式不再像普通对象那样访问,它通过一种叫描述符协议的方法来访问。普通的Python对象操作(get,set,delete)属性时都是在这个对象的。方法获取,同样的道理,给name赋值的时候是通过调用。

mohen_777的博客 485

Python黑魔法之描述符

引言 Descriptors(描述符)Python语言中一个深奥但很重要的一个黑魔法,它被广泛应用于Python语言的内核,熟练掌握描述符将会为Python程序员的工具箱添加一个额外的技巧。本文我将讲述描述符的定义以及一些常见的场景,并且在文末会补充一下__getattr__,__getattribute__, __getitem__这...

weixin_34397291的博客 348

python描述器(Descriptor)

描述器(Descriptor也有人译为描述符) 任何定义了__get__(),__set__()或__delete__()方法的对象。当一个属性为描述器时,它的特殊绑定行为就会在属性查找时被触发。通常情况下,使用a.b来获取、设置或删除一个属性时会在a的字典中查找名称为b的对象,但如果b是一个描述器,则会调用对应的描述器方法。理解描述器的概念是更深层次理解 ...

cnds123的专栏 2311

Python 里的“看门大爷”:彻底搞懂描述符 (Descriptors)

Python 对象模型里,描述符就是一个把“属性访问”变成“方法调用”的代理。只要一个实现了以下任意一个__get__:有人要读属性时触发(对应__set__:有人要改属性时触发(对应__delete__:有人要删属性时触发(对应del obj.x这是“看门大爷”的自我修养。# 我们用一个私有变量名来存真正的数据,防止死循环# 【读】当有人访问 student.math 时# instance: 就是那个 student 对象 (如果是 Student.math 访问,这里是 None)

先说一下,就简单地写点儿氵文,不是博客,只是我的笔记本/工具书 1087

Python描述器Descriptors

描述器Descriptors 一、描述器的表现 用到3个魔术方法: get() 、 set() 、 delete() 方法签名如下: object.get(self, instance, owner) object.set(self, instance, value) object.delete(self, instance) self 指代当前实例,调用者 ,instance 是owner的实例...

SherLocK Echizen 的博客 295

Python描述器Descriptors

描述器的表现:                         用到了三个魔术方法:__get__(),__set__(),__delete__() 方法签名如下:                         object.__get__(self,instance,owner)                         object.__set__(self,inatance,...

Futures_的博客 326

Python--描述器 Descriptors

描述器 Descriptors描述器表现`__get__`self、instance、owner`三个参数的意思描述器定义属性的访问顺序`__set__`属性查找顺序Python中的描述器新增方法练习实现StaticMethod装饰器实现ClassMethod装饰器对实例的数据进行校验 描述器表现 用到的魔术方法:__get__()、__set__()、__delete()__ 方法签名如下 o...

python_lqx的博客 492

python 描述器 详解_Python描述器Descriptors

描述器的表现—————————————————————————用到3个魔术方法: __get__()\__set__()\__delete__()方法签名:object.__get__(self, instance, owner)object.__set__(self, instance, value)object.__delete__(self, instance)self 指当前实例,调用者i...

weixin_39804329的博客 174

python描述器Descriptors和元MetaClasses

http://blog.csdn.net/pipisorry/article/details/50444769 描述器(Descriptors) 描述器决定了对象属性是如何被访问的。描述器的作用是定制当你想引用一个属性时所发生的操作。 构建描述器的方法是至少定义以下三个方法中的一个。需要...

chuange6363的博客 104

Python描述器

描述器Descriptors 描述器的表现 用到三个方法 : __ get__(),__ set__(), __ delete__() 方法签名如下: object.get(self,instance,owner) object.set(self,instance,value) object.delete(self,instance) self指代当前实例,调用者 instan...

haihaihai2232的博客 631

Python面向对象之描述器

描述器Descriptors 描述器的表现 描述器需要用到三个魔术方法:get(),set(),delete()。 方法签名如下: object.get(self,instance,owner) object.set(self,instance,owner) object.delete(self,instance) self指代当前实例,调用者 instance是owner的实例 owner是属...

都枯槐的博客 358

详解Python中的描述器

参考文章:《Python 黑魔法之描述符》《面向对象(深入)|python描述器详解》 0、引言 Descriptors(描述器)Python语言中一个深奥但很重要的一个黑魔法,它被广泛应用于Python语言的内核,熟练掌握描述器将会为Python程序员的工具箱添加一个额外的技巧。本文我将讲述描述符的定义以及一些常见的场景,并且在文末会补充一下__getattr__,__getattribu...

David's Tweet 1147

描述器Descriptors

1.1 描述器的表现 用到三个魔术方法:get()、set()、delete() 方法的签名如下: object.get(self, instance, owner) object.set(self, instance, owner) object.delete(self, instance) self指代当前实例,调用者 instance是owner的实例 owner是属性所属的 class ...

野马 296

描述器 Descriptors

概述 老子曰:一生二,二生三,三生万物,儒家思想认为,世界万物相生相克,有上必有下,有苦必有甜。大家都在描述一个什么问题?世界生态的构成和对象之间的相互作用。 面向对象又是什么?面向对象是哲人们为实现机器语言编程的一种哲学思想,通过面向对象思想模拟世界万物的生态。 现实世界可以抽象为不同种的组成,不同种下又有一个个独立的个体对象组成,每个在现实生活中的个体不一定完全相同,但是每个个体在生...

从0到1 379

Python(Class)描述器(Descriptor)

笔者的的SailWorks模块包含离线分析功能。离线分析的后台实现,包含调度引擎、执行引擎、计算引擎和存储引擎。计算和存储引擎由Hive提供,调度引擎和执行引擎由我们自己实现。调度引擎根据DAG图和调度计划,安排执行顺序,监控执行过程。执行引擎接收调度引擎安排的任务,向Yarn申请容器,在容器中执行具体的任务。在容器中执行的任务我们是用Python语言实现的。在实现这个组建时,笔者是对着python的基础语法教程,边学边写。

OkGogooXSailboat的博客 1067
上一篇: Python实现双向链表
下一篇: Python的异常(Python Exception)
子黄求知若渴
博客等级 码龄9年 4粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值