自助建站还是人工建站好,网页制作基本步骤,产品设计和工业设计有什么区别,wordpress 和 wix大家好#xff0c;小编来为大家解答以下问题#xff0c;python语言的描述错误的选项#xff0c;python描述算法的方法有几种#xff0c;今天让我们一起来看看吧#xff01; 一、描述符是什么 描述符#xff1a;是一个类#xff0c;只要内部定义了方法__get__, __set__, …大家好小编来为大家解答以下问题python语言的描述错误的选项python描述算法的方法有几种今天让我们一起来看看吧 一、描述符是什么 描述符是一个类只要内部定义了方法__get__, __set__, __delete__中的一个或者多个。描述符属性方法绑定等内部机制都是描述符在起作用python打印皮卡丘怎么弄。描述符以单个属性出现并针对该属性的不同访问行为做出响应。最重要的是描述符能“感知”通过什么引用该属性从而和目标建立绑定关联。 二、描述符的实现 class Deor: 描述符 def __set_name__(self, owner, name): 描述符属性必须定义为类型成员所以其自身不适合存储实例相关的状态在创建属性时__set_name__方法被调用并可以通过参数获知目标类型(owner)以及属性名称 :param owner: :param name: :return: print(self, owner, name) self.name f__{name}__ def __get__(self, instance, owner): 以类型或实例访问描述符属性时__get__被自动调用且会接收到类型和实例引用 :param instance: :param owner: :return: print(self,instance,owner) return getattr(instance,self.name, None) def __set__(self, instance, value): 仅在实例引用时被调用。以类型引用进行赋值会导致描述符属性被替换 :param instance: :param value: :return: print(self, instance, value) setattr(instance, self.name, value) def __delete__(self, instance): 仅在实例被引用时调用。以类型引用进行删除操作会导致描述符属性被删除 :param instance: :return: print(self, instance) raise AttributeError(delete is disabled) class X: data Deor() x X() # 执行__set_name__ __main__.deor object at data x.data 100 # 执行__set__ __main__.deor object at __main__.x object at 100 print(x.data) # 执行__get__ __main__.deor object at __main__.x object at print(x.__dict__) # {__data__: 100} print(X.__dict__) # {__module__: __main__, data: __main__.deor object at, __dict__: , __weakref__: , __doc__: None} X.data 2 # 以类型引用进行赋值会导致描述符属性被替换 print(x.data) # 2 print(X.data) # 2 print(x.__dict__) # {__data__: 100} print(X.__dict__) # {__module__: __main__, data: 2, __dict__: , __weakref__: , __doc__: None} 三、数据描述符 如果定义了__set__或__delete__方法那么我们便称其为数据描述符(data deor)而仅有__get__的则是非数据描述符(non-data deor)。这两者的区别在于数据描述符属性的优先级高于实例名字空间中的同名成员。 class Deors: 数据描述符 def __set_name__(self, owner, name): self.name name # 获取Deors 实例对象名字 def __get__(self, instance, owner): print(执行Deors的get) return self.name def __set__(self, instance, value): self.name value print(执行Deors的set) def __delete__(self, instance): print(执行Deors的delete) class Light: # 使用描述符 name Deors() def __init__(self, name, price): self.name name self.price price # 使用类的实例对象来测试 light Light(电灯泡, 60) # 执行描述符的set内置属性 light.name # 执行描述符的get内置属性 print(light.__dict__) # 查看实例的字典不存在name {price: 60} print(Light.__dict__) # 查看类的字典存在name(为描述符的对象) # {__module__: __main__, name: __main__.deors object at, # __init__: , __dict__: , # __weakref__: , __doc__: None} del light.name # 执行描述符的delete内置属性 del Light.name # 以类型引用进行删除操作会导致描述符属性被删除 print(Light.__dict__) # {__module__: __main__, __init__: , __dict__: , __weakref__: , __doc__: None} print(light.name) # 报错描述符属性被删除 如果注释掉__set__就成为了非数据描述符。 描述符的优先级问题类属性数据描述符实例属性非数据描述符找不到属性触发__getattr__() 说明问题一类属性数据描述符 class Deor: def __get__(self, instance, owner): print(__get__) return self.name def __set__(self, instance, value): print(开始赋值:, value) self.name value print(__set__) class X: data Deor() x X() x.data 100 # 调用__set__赋值 print(x.__dict__) # {} x.data 3 print(x.data) # 3 print(x.__dict__) # {} print(X.data) # 调用__get__ print(X.__dict__) # {__module__: __main__, data: __main__.deor object at, __dict__: , __weakref__: , __doc__: None} X.data 44444 # 语句没有触发set的执行说明类属性的优先级大于数据描述符的优先此时相当于类属性覆盖了数据描述符从而说明对类属性的一切操作都与描述符无关 print(x.data) # 4 print(x.__dict__) # {} print(X.__dict__) # {__module__: __main__, data: 44444, __dict__: , __weakref__: , __doc__: None} 说明问题二数据描述符实例属性 参考“描述符代码” 数据描述符的优先级大于实例属性的优先级此时实例属性name被数据描述符所覆盖而price没有描述符代理所以它任然是实例属性。 说明问题三实例属性非数据描述符 class Deors: 非数据描述符 def __get__(self, instance, owner): print(执行Deors的get) def __delete__(self, instance): print(执行Deors的delete) class X: data Deors() x X() x.data 3 # 报错AttributeError: __set__ 四、方法绑定 因为函数默认实现了描述符协议所以当以实例或类型访问方法时__get__首先被调用。类型和实例作为参数被传入__get__从而截获绑定目标(self)如此就将函数包装称绑定方法对象返回。实际被执行的就是这个会隐式传入第一个参数的包装品。 class Person: def __init__(self, name, age): self.name name self.age age def print_info(self): print(my name is %s ,my age is %s % (self.name, self.age)) p Person(ways, 13) print(p.print_info) # print(p.print_info.__get__(p,Person)) # m p.print_info.__get__(p,Person) Person.print_info(m.__self__,) # my name is ways ,my age is 13 print(m.__self__, m.__func__) # __main__.person object at 方法执行分成了两个步骤 p.print_info(): #1. m p.print_info.__get__(p,Person) 将函数包装成绑定方法 #2. m()等价Person.print_info(m.__self__,) 执行时隐式将self/cls参数传递给目标函数 五、描述符的使用例子 1、模拟property class My_Property: 使用描述符模拟property def __init__(self, func): self.func func print(self.func) # def __get__(self, instance, owner): res self.func(instance) # 回调传入的函数将运行结果保存在res中 setattr(instance,self.func.__name__,res) # 为函数名func.__name__ 设置值为res存入对象的字典 return res class Test: def __init__(self,weight,height): self.weight weight self.height height My_Property def my_area(self): return self.weight*self.height test Test(3, 4) print(test.my_area) # 12 print(test.__dict__) # {weight: 3, height: 4, my_area: 12} 六、描述符的使用总结 1、描述符是可以实现大部分python类特性中的底层魔法,包括classmethod,staticmethd,property甚至是__slots__属性 2、描述父是很多高级库和框架的重要工具之一,描述符通常是使用到装饰器或者元类的大型框架中的一个组件. 参考https://www.cnblogs.com/Lynnblog/p/9033455.html 和《python3学习笔记上》