1.描述符

#!/usr/bin/python env
# coding=utf-8
# 数据描述符__get__ __set__ __delete__
'''
描述符总结
描述符是可以实现大部分python类特性中的底层魔法,包括@classmethod,@staticmethd,@property甚至是__slots__属性
描述符是很多高级库和框架的重要工具之一,描述符通常是使用到装饰器或者元类的大型框架中的一个组件 注意事项:
一 描述符本身应该定义成新式类,被代理的类也应该是新式类
二 必须把描述符定义成这个类的类属性,不能为定义到构造函数中
三 要严格遵循该优先级,优先级由高到底分别是
1.类属性
2.数据描述符
3.实例属性
4.非数据描述符
5.找不到的属性触发__getattr__()
描述符分2种
1.数据描述符:至少有get set方法
2.非数据描述符:没有set方法 '''
class Str:
def __init__(self, name,val_type):
self.name = name
self.val_type = val_type
# instance 实例对象 owner实例的类
def __get__(self, instance, owner):
print('get方法', instance, owner)
return instance.__dict__[self.name]
# instance 实例对象 value实例的值
def __set__(self, instance, value):
print('set方法', instance, value)
if not isinstance(value, self.val_type):
raise TypeError("%s 的数据类型不是 %s" % (value, self.val_type))
instance.__dict__[self.name] = value def __delete__(self, instance):
print('delete方法', instance)
instance.__dict__.pop(self.name) class People:
# 描述符
name = Str('name', str)
age = Str('age', int)
salary = Str('salary', int) def __init__(self, name, age, salary):
self.name = name
self.age = age
self.salary = salary p1 = People('wangwu', 12, 98921) # 调用
print(p1.__dict__)
# print(p1)
# p1.name # #赋值
# print(p1.__dict__)
# p1.name='egonlin'
# print(p1.__dict__)
#
# #删除
# print(p1.__dict__)
# del p1.name
# print(p1.__dict__)

2.上下文管理协议

操作文件对象写法

1 with open('a.txt') as f:
2   '代码块'

上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法

# 上下文管理协议 with
'''
# with open('filename') as f:
# 代码块
1.with.obj ---> obj.__enter__(), return val
2.as f ----> f=val
3.with obj as f === f=obj.__enter()
4.执行
1)没有异常时,all code运行后,__exit__ 三个参数都为None
2)有异常时,从异常的的位置触发__exit__
a。如果exit的返回值为True,吞掉了异常
b.反之,抛出异常
c.exit的代码执行完毕代表了整个with语句执行完毕
'''
class Foo:
def __init__(self, name):
self.name = name def __enter__(self): # 出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
return self # exc_type 异常类:NameError
# exc_val 异常值:name 'abc异常abc' is not defined
# exc_tb 追踪信息: Traceback后面的内容
# Traceback(most recent call last):
# NameError: name 'abc异常abc' is not defined
def __exit__(self, exc_type, exc_val, exc_tb): # with里有异常时 触发改函数
print("%s %s %s" % (exc_type, exc_val, exc_tb))
return True # 如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行 with Foo('a.txt') as f:
print(f)
# print(abc异常abc)
print(f.name)
print("*"*100)
# 上下文管理实例
class Open:
def __init__(self,filepath,mode='r',encoding='utf-8'):
self.filepath=filepath
self.mode=mode
self.encoding=encoding def __enter__(self):
# print('enter')
self.f=open(self.filepath,mode=self.mode,encoding=self.encoding)
return self.f def __exit__(self, exc_type, exc_val, exc_tb):
# print('exit')
self.f.close()
return True
def __getattr__(self, item):
return getattr(self.f,item) with Open('a.txt','w') as f:
print(f)
f.write('aaaaaa')
f.wasdf #抛出异常,交给__exit__处理

3.类装饰器

# 函数装饰器范式
# def wrap(func):
# def wrapper(*args, **kwargs):
# func(*args, **kwargs)
# return True
# return wrapper # 无参类装饰器范式
# def wrap(cls):
# return cls # 有参类装饰器范式
# def wrap(**kwargs):
# def wrapper(obj):
# # 操作kwargs
# return obj
# return wrapper # 有参类装饰器
class Check_type:
def __init__(self, name, val_type):
self.name = name
self.val_type = val_type # instance 实例对象 owner实例的类
def __get__(self, instance, owner):
# print('get方法', instance, owner)
return instance.__dict__[self.name] # instance 实例对象 value实例的值
def __set__(self, instance, value):
# print('set方法', instance, value)
if not isinstance(value, self.val_type):
raise TypeError("%s的数据类型不是 %s" % (value, self.val_type))
instance.__dict__[self.name] = value def __delete__(self, instance):
# print('delete方法', instance)
instance.__dict__.pop(self.name) def Typed(**kwargs): # kwargs ===> name=str, age= int, salary=int
def wrapper(obj):
for key, val in kwargs.items():
# 描述符 val是key的类型
# val = Check_type('val', str)
setattr(obj, key, Check_type(key, val))
return obj
return wrapper @Typed(y=2, x=1, z=3)
class Foo:
pass @Typed(name='wangwu')
class foo:
pass @Typed(name=str, age=int, salary=int) # @warpper -->People=warper(people)
class People:
# 描述符
# name = Str('name', str)
# age = Str('age', int)
# salary = Str('salary', int)
def __init__(self, name, age, salary):
self.name = name
self.age = age
self.salary = salary print(People.__dict__)
p1 = People('wangwu', "d", 98921) # 调用
print(p1.__dict__)

4.仿property

# 类装饰器
# class Cls_property:
# def __init__(self,func):
# self.func = func
# 仿property类装饰器 class Cls_property:
def __init__(self, func):
# print("func属性 %s " %(func))
self.func = func # 描述get有两个参数 第一个是实例 第二个是类
def __get__(self, instance, owner):
# val = self.func()
print('get---->')
print('instance: %s' % instance) # 实例对象 r1
print('owner: %s' % owner) # 类 Room
if instance is None:
return self
res = self.func(instance)
# property延时计算
setattr(instance, self.func.__name__, res)
return res
# 加上set 数据描述符
# def __set__(self, instance, value):
# pass class Room:
tag = 168 def __init__(self, owner, width, length):
self.owner = owner
self.width = width
self.length = length # @cls_property
@Cls_property # area=property(area)
def area(self):
return self.width * self.length # @cls_property
@property # area=property(area)
def area1(self):
return self.width * self.length # 类方法 能访问类的属性不能访问实例属性
@classmethod
def test_tag(cls, x):
print(cls)
print("from test_tag %s %s" % (cls.tag, x)) # 静态方法 不能访问类、实例属性
@staticmethod
def action(a, b, c):
print("%s %s %s" % (a, b, c)) # 类可以调用,实例不可调用test
def test(cls, x):
print(cls)
print("from test_tag %s %s" % (cls.tag, x)) @property # <property object at 0x01FE80F0>
def pro_test(self):
return "pro_test" r1 = Room('zq', 1, 100)
print(r1.__dict__) # 没找到area属性值 那就调用代理的Roo的area值
print(r1.area)
print(r1.__dict__) # 没找到area属性值 那就调用代理的Roo的area值
print(r1.area)
print(r1.area)
print(r1.area)
# print(Room.__dict__['area']) # print(Room.area)
# print(Room.pro_test) # 一个静态属性property本质就是实现了get,set,delete三种方法
# 方法一
class Foo:
@property
def AAA(self):
print('get的时候运行我啊') @AAA.setter
def AAA(self,value):
print('set的时候运行我啊', value) @AAA.deleter
def AAA(self):
print('delete的时候运行我啊') #只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA
print("<----------------------->") # 方法二
class Foo:
def get_AAA(self):
print('get的时候运行我啊') def set_AAA(self,value):
print('set的时候运行我啊', value) def delete_AAA(self):
print('delete的时候运行我啊')
AAA=property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应 f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA

5.元类 metaclass

元类是类的类,是类的模板

元类的实例是类,类的实例是 对象

type是python的一个内建元类 ,用来控制生成类,python中任何class定义的类其实都是type类实例化的对象

# 创建类有2种方法
# metaclass
# 类的默认元类是type
# 1.
class Foo:
pass
# tpye(str)
t = type(Foo)
print(t)
# print(t.__dict__) def test(self):
pass
def __init__(self, name, age):
self.name = name
self.age = age # s三个参数 类名 (父类,), {属性字典}
# 2.type(类名,(object,),{})
t = type('t', (object,), {'a': 1, '__init__': __init__, 'test': test})
print(t.__dict__) # {'a': 1, '__weakref__': <attribute '__weakref__' of 't' objects>, '__init__': <function __init__ at 0x002C4738>, '__module__': '__main__', 'test': <function test at 0x00703660>, '__doc__': None, '__dict__': <attribute '__dict__' of 't' objects>}
print(t) # <class '__main__.t'>
print("------------------------->") # 自定义元类
class Mytype(type):
def __init__(self, *args, **kwargs):
print("元类的自定义类")
# for i in args:
# print(i) def __call__(self, *args, **kwargs): # self == Foo
# print("__call__函数:",self)
obj = object.__new__(self) # object.__nee__(Foo) --> 产生 f1 产生实例obj
# print("obj产生: ",obj)
self.__init__(obj, *args, **kwargs) # Foo.__init__()
return obj class Foo(metaclass=Mytype): # Mytype(传了4个参数: self,Foo,(),{})-->触发mytype __init__
def __init__(self, name):
self.name = name # f1.name = name print(Foo)
f1 = Foo('wangwu')
print(f1)
# print(f1.__dict__)

参考:http://www.cnblogs.com/linhaifeng/articles/6204014.html#_label15

python 描述符 上下文管理协议 类装饰器 property metaclass的更多相关文章

  1. Python之面向对象上下文管理协议

    Python之面向对象上下文管理协议 析构函数: import time class Open: def __init__(self,filepath,mode='r',encode='utf-8') ...

  2. python基础----实现上下文管理协议__enter__和__exit__

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

  3. Python系列之 - 上下文管理协议

    with obj as f: '代码块' 1.with obj ---->触发obj.__enter__(),拿到返回值 2.as f----->f=返回值. 3.with obj as ...

  4. python描述符(descriptor)、属性(property)、函数(类)装饰器(decorator )原理实例详解

     1.前言 Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题 ...

  5. 11.python描述符---类的装饰器---@property

    描述符1.描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()这三个内置方法中的一个,描述符也被称为描述符协议(1):__ ...

  6. 杂项之python描述符协议

    杂项之python描述符协议 本节内容 由来 描述符协议概念 类的静态方法及类方法实现原理 类作为装饰器使用 1. 由来 闲来无事去看了看django中的内置分页方法,发现里面用到了类作为装饰器来使用 ...

  7. Descriptor - Python 描述符协议

    描述符(descriptor) descriptor 是一个实现了 __get__. __set__ 和 __delete__ 特殊方法中的一个或多个的. 与 descriptor 有关的几个名词解释 ...

  8. python实现可以被with上下文管理的类或函数

      # .开始之前先明确一下with机制 # 1.类包函数__enter__()和__exit__()函数,即是可以被上下文管理的类 # __enter__用来执行with时的方法,__exit__返 ...

  9. 用python优雅打开文件及上下文管理协议

    有次面试被问到如何优雅地打开一个文件?   那就是用with语句,调用过后可以自动关闭.   但是为什么使用with语句就可以自动关闭呢,原因就是上下文管理协议.   上下文管理协议:包含方法 __e ...

随机推荐

  1. CF1139D Steps to One 题解【莫比乌斯反演】【枚举】【DP】

    反演套 DP 的好题(不用反演貌似也能做 Description Vivek initially has an empty array \(a\) and some integer constant ...

  2. L: Long Long Ago---二分

    L: Long Long Ago 时间限制: 1 s      内存限制: 128 MB        题目描述 今天SHIELD捕获到一段从敌方基地发出的信息里面包含一串被经过某种算法加密过的的序列 ...

  3. dp--最大区间和变形-cf-1155D

    dp--最大区间和变形-cf-1155D D. Beautiful Array time limit per test 2 seconds memory limit per test 256 mega ...

  4. service worker --- offline APP

    相关介绍: https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API/Using_Service_Workers

  5. 基于libcurl实现REST风格http/https的get和post

    c/c++开发中经常要用到http/https协议,直接使用socket工作量很大,要是使用socket实现https,那更不可思议,开源的c/c++的http客户端框架,libcurl是首选,而且也 ...

  6. JavaScript设计模式-4.继承和聚合

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. linux mint 19 pyenv 安装 python 3.7.0 问题解决

    Python3: ImportError: No module named '_ctypes' 解决 sudo apt-get install libffi-dev WARNING: The Pyth ...

  8. jstack 结果查看

    首先可以用jstack -l pid >sample.dump把java进程的运行栈dump出来. 还可以用grep java.lang.Thread.State sample.dump | a ...

  9. WINFORM如何实现无聚焦框的Button按钮

    当我们将一个button按钮设置如下属性时,总有一个聚焦框来困扰着我们 button1.FlatStyle = FlatStyle.Flat; 我们想要的效果是这样的: 但当使用了Tab切换焦点时 发 ...

  10. visual studio清理nuget包缓存

    最近在使用nuget包的时候发现一个问题.昨天我组长明明发了一个新版本的包上去,可在我电脑上死活找不到这个新版本的包.刷新,重启vs,重启电脑,好长时间才出来.今天又碰到这个问题了,在同事电脑上都能搜 ...