描述符的使用

  python是弱类型语言,及参数的赋值没有类型限制,下面通过描述符机制来实现类型限制功能

  描述符应用1.py

class Typed:
def __get__(self, instance, owner):
print('get方法')
print('instance是[%s]'%instance)
print('owner是[%s]'%owner) def __set__(self, instance, value):
print('set方法')
#instance就是实例化出来的对象本身
print('instance是[%s]'%instance)
print('value是[%s]'%value) def __delete__(self, instance):
print('delete方法')
print('instance是[%s]' % instance) class People:
name = Typed()
def __init__(self,name,age,salary):
self.name = name
self.age = age
self.salary = salary #实例化触发了以下三个赋值操作
#p1.__dict__['name'] = 'zhangsan'
#p1.__dict__['age'] = 18
#p1.__dict__['salary'] = 999999
#但是数据属性被描述符描述了进行赋值操作调用的是描述类的set方法
#因为set方法没有进行实际赋值操作所以字典的name属性为None
p1 = People('zhangsan',18,999999)
# set方法
# instance是[<__main__.People object at 0x000001E527F67390>]
# value是[zhangsan]
print(p1)
#<__main__.People object at 0x000001BF1B047390>
print(p1.__dict__)
#调用数据属性触发__get__方法输出
p1.name
# get方法
# instance是[<__main__.People object at 0x000001F7F3ED8080>]
# owner是[<class '__main__.People'>]
#调用del删除数据属性,触发__delete__方法输出
del p1.name
# delete方法
# instance是[<__main__.People object at 0x0000018239F274E0>]

  以上只是测试是否调用了描述符,但是对应的__get__,__set__,__delete__只是执行了打印操作没有进行返回值,设置值,删除值的操作所以只有打印输出

  PS:根据优先级数据描述符大于实例所以优先调用数据描述符,假如进行了p1.name = ‘lisi’会执行set方法但是不会赋值,name依旧为空

  下面在__get__,__set__,__delete__执行对应的返回值,设置值,删除值操作

  描述符应用2.py

class Typed:
def __init__(self,key):
self.key=key def __get__(self, instance, owner):
print('get方法')
# print('instance是[%s]'%instance)
# print('owner是[%s]'%owner)
#使用对应的key返回值
return instance.__dict__[self.key] def __set__(self, instance, value):
print('set方法')
#instance就是实例化出来的对象本身
# print('instance是[%s]'%instance)
# print('value是[%s]'%value)
#对对应的key进行赋值设置操作
instance.__dict__[self.key] = value def __delete__(self, instance):
print('delete方法')
# print('instance是[%s]' % instance)
#使用对应的key删除操作
instance.__dict__.pop(self.key) class People:
name = Typed('name')
def __init__(self,name,age,salary):
self.name = name
self.age = age
self.salary = salary #实例化触发了以下三个赋值操作
#p1.name = 'zhangsan'
#p1.age = 18
#p1.salary = 999999
#其中p1.name = 'zhangsan'调用了描述符类Typed进行实例化
#name = Typed('name')运行初始化函数__init__
#self.name = 'name'
p1 = People('zhangsan',18,999999)
#set方法
#打印字典name也赋值成功
print(p1.__dict__)
#{'age': 18, 'name': 'zhangsan', 'salary': 999999}
p1.name
#get方法
del p1.name
#delete方法
#打印字典上一步的删除操作也成功删除了属性name
print(p1.__dict__)
#{'age': 18, 'salary': 999999}

  通过定义描述符类的初始化__init__函数获取字典需要修改对应的key值然后执行相应的返回值,设置值,删除值的操作

  下面对用户实例化输入的信息进行判断,比如输入姓名只能是字符串格式不能是数字或者其他格式

  描述符应用3.py

class Typed:
def __init__(self,key):
self.key=key def __get__(self, instance, owner):
print('get方法')
# print('instance是[%s]'%instance)
# print('owner是[%s]'%owner)
#使用对应的key返回值
return instance.__dict__[self.key] def __set__(self, instance, value):
print('set方法')
#instance就是实例化出来的对象本身
# print('instance是[%s]'%instance)
# print('value是[%s]'%value)
#对应的key进行赋值设置操作
if not isinstance(value,str):
print('你输入是不是字符串类型,错误')
return
instance.__dict__[self.key] = value def __delete__(self, instance):
print('delete方法')
# print('instance是[%s]' % instance)
#使用对应的key删除操作
instance.__dict__.pop(self.key) class People:
name = Typed('name')
def __init__(self,name,age,salary):
self.name = name
self.age = age
self.salary = salary p1=People(18,18,999999)
#因为调用__set__方法的时候检测到输入的名字不是字符串,然后直接return了所以name没有赋值
print(p1.__dict__)

#set方法
#你输入是不是字符串类型,错误
#{'salary': 999999, 'age': 18}

  可以把错误返回改的高端一点

  描述符应用4.py

class Typed:
def __init__(self,key):
self.key=key def __get__(self, instance, owner):
print('get方法')
# print('instance是[%s]'%instance)
# print('owner是[%s]'%owner)
#使用对应的key返回值
return instance.__dict__[self.key] def __set__(self, instance, value):
print('set方法')
#instance就是实例化出来的对象本身
# print('instance是[%s]'%instance)
# print('value是[%s]'%value)
#对应的key进行赋值设置操作
if not isinstance(value,str):
# print('你输入是不是字符串类型,错误')
# return
raise TypeError('%s你传入的不是字符串'%value)
instance.__dict__[self.key] = value def __delete__(self, instance):
print('delete方法')
# print('instance是[%s]' % instance)
#使用对应的key删除操作
instance.__dict__.pop(self.key) class People:
name = Typed('name')
def __init__(self,name,age,salary):
self.name = name
self.age = age
self.salary = salary p1=People(18,18,999999)

  运行直接报错

  以上只是实现了输入的name必须是字符串,并没有对输入的age限制必须是整型

  描述符应用5.py

class Typed:
def __init__(self,key,expected_type):
self.key=key
self.expected_type=expected_type
def __get__(self, instance, owner):
print('get方法')
# print('instance是[%s]'%instance)
# print('owner是[%s]'%owner)
#使用对应的key返回值
return instance.__dict__[self.key] def __set__(self, instance, value):
print('set方法')
#instance就是实例化出来的对象本身
# print('instance是[%s]'%instance)
# print('value是[%s]'%value)
#对应的key进行赋值设置操作
if not isinstance(value,self.expected_type):
# print('你输入是不是字符串类型,错误')
# return
raise TypeError('%s你传入的不是%s'%(value,self.expected_type))
instance.__dict__[self.key] = value def __delete__(self, instance):
print('delete方法')
# print('instance是[%s]' % instance)
#使用对应的key删除操作
instance.__dict__.pop(self.key) class People:
name = Typed('name',str)
age = Typed('age',int)
def __init__(self,name,age,salary):
self.name = name
self.age = age
self.salary = salary p1=People('zhangsan','abc',999999)
print(p1.__dict__)

  因为age输入的是字符串所以报错

Python全栈day28(描述符应用)的更多相关文章

  1. Python全栈day28(类的装饰器)

    类是一个对象也可以像函数一样加装饰器 类的装饰器.py def deco(obj): print('======',obj) obj.x=1 obj.y=2 obj.z=3 return obj # ...

  2. Python全栈--7.1--字符串的格式化

    Python字符串格式化:(百分号/format) 1.百分号的方式: %[(name)][flags][width].[precision]typecode (name)      可选,用于选择指 ...

  3. Python全栈day28(上下文管理)

    我们知道在操作文件对象的时候可以这么写 with open('a.txt',''r) as f: 代码 上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明 ...

  4. Python全栈之路目录结构

    基础 1.Python全栈之路-----基础篇 2.Python全栈之路---运算符与基本的数据结构 3.Python全栈之路3--set集合--三元运算--深浅拷贝--初识函数 4.Python全栈 ...

  5. Python全栈【Socket网络编程】

    Python全栈[socket网络编程] 本章内容: Socket 基于TCP的套接字 基于UDP的套接字 TCP粘包 SocketServer 模块(ThreadingTCPServer源码剖析) ...

  6. Python全栈开发【面向对象进阶】

    Python全栈开发[面向对象进阶] 本节内容: isinstance(obj,cls)和issubclass(sub,super) 反射 __setattr__,__delattr__,__geta ...

  7. python 全栈开发,Day43(python全栈11期月考题)

    python全栈11期月考题 1.常用字符串格式化有哪些?并说明他们的区别 2.请手写一个单例模式(面试题) 3.利用 python 打印前一天的本地时间,格式为‘2018-01-30’(面试题) 4 ...

  8. python 全栈开发,Day30(第一次面向对象考试)

    月考题: python 全栈11期月考题 一 基础知识:(70分) 1.文件操作有哪些模式?请简述各模式的作用(2分) 2.详细说明tuple.list.dict的用法,以及它们的特点(3分) 3.解 ...

  9. python全栈开发之正则表达式和python的re模块

    正则表达式和python的re模块 python全栈开发,正则表达式,re模块 一 正则表达式 正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的 ...

随机推荐

  1. 8086汇编之 CALL 和 RET指令

    Ret 和 call 也是转移指令,可是他们跟jmp不同的是,这两个转移指令都跟栈有关系. <1> ret 用栈中的数据改动IP的地址,从而实现近转移 ( ip ) = ( (ss)*16 ...

  2. Atitit.软件开发概念(11)--网络子系统--url编码 空格问题URLEncoder java js php

    Atitit.软件开发概念(11)--网络子系统--url编码 空格问题URLEncoder java js php 1. RFC2396标准 including HTML 4.01 section  ...

  3. Linux Shell编程之常用技巧

    前言 本文集中介绍了bash编程中部分高级编程方法和技巧.通过学习本文内容,可以帮你解决以下问题: 1.bash可以网络编程么? 2..(){ .|.& };. 据说执行这些符号可以死机,那么 ...

  4. git使用GitHub远程仓库

    1.为什么要使用远程仓库我们知道本地仓库可以很容易地实现版本控制,但在多人开发的情况下,我们需要使用一个服务器作为远程仓库.GitHub是一个开源代码库平台以及版本控制系统. 2.GitHub仓库创建 ...

  5. 移动端rem的用法

    标签: 1.rem(font size of the root element)是指相对于根元素的字体大小的单位,em(font size of the element)是指相对于父元素的字体大小的单 ...

  6. 商派onex本地部署无法进入的问题

    商派最新版的ONex本地虚拟机部署项目无法进入注册的问题解决 进入项目的database.php文件,复制host的值 vim /etc/hosts,将hosts内容添加到/etc/hosts里面去就 ...

  7. sqlmap中tamper脚本绕过waf

    0x00 背景 sqlmap中的tamper脚本来对目标进行更高效的攻击. 由于乌云知识库少了sqlmap-tamper 收集一下,方便学习. 根据sqlmap中的tamper脚本可以学习过绕过一些技 ...

  8. C语言 · 大数加法

    算法提高 大数加法   时间限制:1.0s   内存限制:256.0MB      问题描述 输入两个正整数a,b,输出a+b的值. 输入格式 两行,第一行a,第二行b.a和b的长度均小于1000位. ...

  9. 示例 - 25行代码等价实现 - 借助Nodejs在服务端使用jQuery采集17173游戏排行信息

    今天在园子里看到一篇文章: 借助Nodejs在服务端使用jQuery采集17173游戏排行信息 感觉用SS来实现相同功能更加简洁, 于是写了一下, 发现25行代码就搞定了 (包括自动翻页), 于是跟大 ...

  10. js 刷新后不提示并保留控件状态

    保存后,想提示一下并保留查询条件的状态,发现可以用document.forms[0].submit();继续提交达到刷新的目的 代码如下: ScriptManager.RegisterStartupS ...