with open as f: 函数触发 enter 和 exit
class Open:
def __init__(self,name):
self.name = name
def __enter__(self): #开始时执行
print('执行enter')
return self
def __exit__(self, exc_type, exc_val, exc_tb): # 结束时执行
print('执行exit')
with Open('a.txt') as f:
print(f)
print(f.name)
输出结果:
执行enter
<__main__.Open object at 0x0000023A6CD6A080>
a.txt
执行exit
with obj as f
with obj as f:
'代码块'
1.with obj ---> 触发obj.__enter__(), 拿到返回值
2.as f -----> f=返回值
3.with obj as f 等同于 f=obj.__enter__()
4.执行代码块
一:没有异常的情况下,整个代码块运行完毕后去触发__exit__,它的三个参数都为none
二:在有异常的情况下,从异常出现的位置直接触发__exit__
a: 如果__exit__的返回值为True,代表吞掉了异常
b: 如果__exit__的返回值不为True,代表吐出了异常
c: __exit__的运行完毕就代表了整个with语句的执行完毕
异常信息
>>> abc
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'abc' is not defined
NameError ----->class
name 'abc' is not defined ----->异常的值
Traceback ----->追踪信息
用新式类作输入类型检测,get,set,del
class Type:
def __init__(self, key):
self.key = key
def __get__(self, instance, owner):
print('get 方法')
print(instance)
print(owner)
return instance.__dict__[self.key]
def __set__(self, instance, value):
print('set 方法')
print(instance)
print(value)
if not isinstance(value,str):
print("必须传入字符串")
return
instance.__dict__[self.key] = value
def __delete__(self, instance):
print('del 方法')
print(instance)
del instance.__dict__[self.key]
class earth:
name = Type('name')
def __init__(self, name, age):
self.name = name
self.age = age
e = earth('libai', 20)
print(e.__dict__)
print(e.name)
e.name = 12
print(e.__dict__)
print('----------------------------------')
del e.name
print(e.__dict__)
输出结果:
set 方法
<__main__.earth object at 0x000002257741AEF0>
libai
{'name': 'libai', 'age': 20}
get 方法
<__main__.earth object at 0x000002257741AEF0>
<class '__main__.earth'>
libai
set 方法
<__main__.earth object at 0x000002257741AEF0>
12
必须传入字符串
{'name': 12, 'age': 20}
----------------------------------
del 方法
<__main__.earth object at 0x000002257741AEF0>
{'age': 20}
改进上面的程序,使得可以检测 多种类型
class Type:
def __init__(self, key, except_type):
self.key = key
self.except_type = except_type
def __get__(self, instance, owner):
print('get 方法')
print(instance)
print(owner)
return instance.__dict__[self.key]
def __set__(self, instance, value):
print('set 方法')
print(instance)
print(value)
if not isinstance(value,self.except_type):
print("必须传入 %s " %self.except_type)
return
instance.__dict__[self.key] = value
def __delete__(self, instance):
print('del 方法')
print(instance)
del instance.__dict__[self.key]
class earth:
name = Type('name', str)
age = Type('age', int)
def __init__(self, name, age):
self.name = name
self.age = age
e = earth('libai', 20)
print('---------------------------------')
e.name = 20
print('---------------------------------')
e.age = 'bbs'
输出结果:
set 方法
<__main__.earth object at 0x000002254086D080>
libai
set 方法
<__main__.earth object at 0x000002254086D080>
20
---------------------------------
set 方法
<__main__.earth object at 0x000002254086D080>
20
必须传入 <class 'str'>
---------------------------------
set 方法
<__main__.earth object at 0x000002254086D080>
bbs
必须传入 <class 'int'>
类的装饰器,先来一段函数的装饰器
def deco(func):
print('========================')
return func
@deco #deco 函数就是 test 当成func传入deco,返回值再赋给test
def test():
print('hello,big big world')
test()
输出结果:
========================
hello,big big world
装饰器装饰类
def deco(obj):
print('========================')
obj.x = 1
obj.y = 2
obj.z = 3
return obj
@deco #deco 函数就是 test 当成obj传入deco,返回值再赋给test
class test:
pass
print(test.__dict__)
输出结果:
========================
{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'test' objects>, '__weakref__': <attribute '__weakref__' of 'test' objects>, '__doc__': None, 'x': 1, 'y': 2, 'z': 3}
函数也存在 dict 属性 ,一切皆对象
def deco(obj):
print('========================')
obj.x = 1
obj.y = 2
obj.z = 3
return obj
@deco
def test():
pass
print(test.__dict__)
输出结果:
========================
{'x': 1, 'y': 2, 'z': 3}
装饰器,改成类型检测,如果检测到不匹配,就print 和不写入
def deco(**kwargs): #接收参数传入**kwargs
def wrapper(obj): #返回的 wrapper 传入earth
print('========================')
for key,value in kwargs.items(): # .items() 格式为元组
setattr(obj, key, Type(key, value))
return obj
print(kwargs)
return wrapper
#类型传入检测
class Type:
def __init__(self, key, except_type):
self.key = key
self.except_type = except_type
def __get__(self, instance, owner):
print('get 方法')
print(instance)
print(owner)
return instance.__dict__[self.key]
def __set__(self, instance, value):
print('set 方法')
print(instance)
print(value)
if not isinstance(value,self.except_type):
print("必须传入 %s " %self.except_type)
return
instance.__dict__[self.key] = value
def __delete__(self, instance):
print('del 方法')
print(instance)
del instance.__dict__[self.key]
@deco(name=str,age=int) #name 传入类型 str,age传入类型 int
class earth:
def __init__(self, name, age):
self.name = name
self.age = age
e = earth('libai', '23') #触发set方法
print('*************************************************')
print(earth.__dict__)
print(e.__dict__)
输出结果:
{'name': <class 'str'>, 'age': <class 'int'>}
========================
set 方法
<__main__.earth object at 0x0000025C38B4E080>
libai
set 方法
<__main__.earth object at 0x0000025C38B4E080>
23
必须传入 <class 'int'>
*************************************************
{'__module__': '__main__', '__init__': <function earth.__init__ at 0x0000025C38B34950>, '__dict__': <attribute '__dict__' of 'earth' objects>, '__weakref__': <attribute '__weakref__' of 'earth' objects>, '__doc__': None, 'name': <__main__.Type object at 0x0000025C38B4AF98>, 'age': <__main__.Type object at 0x0000025C38B4E048>}
{'name': 'libai'}
@property 就是把装饰的类或者函数当成参数传入 property(类) 中,执行完后把返回值再赋给所装饰的类,下面是自定义的 @property,与原生的@property 有类似的功能
class Lazyproperty:
def __init__(self, func):
self.func = func
print('func = ', self.func)
def __get__(self, instance, owner):
print('instance = ', instance)
print('owner = ', owner)
# 以下这句 self.func(instance) 被执行并赋值给print打印时,
# 会执行一遍 test 函数,这也就是为什么输出结果中会有两个 test被打印
print('------------------>>>', self.func(instance))
print('***************************************************')
return self.func(instance)
class earth:
def __init__(self):
pass
@Lazyproperty
def test(self):
print('test')
return '你好吗?'
e = earth()
print(e.test)
输出结果:
func = <function earth.test at 0x0000021C699B47B8>
instance = <__main__.earth object at 0x0000021C699CAEB8>
owner = <class '__main__.earth'>
test
------------------>>> 你好吗? # test 被打印两次
***************************************************
test
你好吗?
优先级寻找十分重要啊,
class Lazyproperty:
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
print('get')
res = self.func(instance)
setattr(instance, self.func.__name__, res)
return res
# 如果存在 __set__ 方法,class Lazyproperty 为数据描述符,优先级高于实例属性,
# 寻找属性时会优先寻找 数据描述符,就会每次执行都调用一次 get 方法
# 现在不存在 __set__ 方法,class Lazyproperty 为非数据描述符,优先级低于实例属性,
# 寻找属性时会优先寻找 实例属性,
# 整个程序执行过程:
# 首先呢,@Lazyproperty 会先执行一遍,把 test 函数当成参数传入,
# 实例化后再赋给test,下面,实例化 earth 类为 e,直接传参到
# self.x 和 self.y ;
# 调用 e.test 过程中,会先寻找 e 的实例属性,实例属性不存在 test,
# 那就去找非数据描述符, class Lazyproperty 的 get 方法被执行,
# instance 是类的实例,也就是 e ,self.func 就是 test,
# owner 是 earth 类,在 earth 类中的 test 函数必须传入一个参数,
# 也就是 instance ,self.func(instance) 执行结果被存到 e.__dict__
# 实例属性中,之后 get 方法就不会执行了,因为在实例属性中找得到结果
# 可以实现不用每次执行都计算一遍
# def __set__(self, instance, value):
# pass
class earth:
def __init__(self, x, y):
self.x = x
self.y = y
@Lazyproperty
def test(self):
return (self.x*self.y)
e = earth(10,22)
print(e.test)
print(e.test)
print(e.test)
print(e.__dict__)
输出结果:
get
220
220
220
{'x': 10, 'y': 22, 'test': 220}
@property 的补充,setter ,deleter
class Foo:
@property
def AAA(self):
print('get 的时候触发')
@AAA.setter
def AAA(self, val):
print('set 的时候触发 ',val)
@AAA.deleter
def AAA(self):
print('del 的时候触发')
#只有在属性 AAA 定义 property 后才能定义 AAA.setter, AAA.deleter
f = Foo()
f.AAA
f.AAA = 'bbb'
del f.AAA
输出结果:
get 的时候触发
set 的时候触发 bbb
del 的时候触发
上面的程序可以这么写
class Foo:
def get_AAA(self):
print('get 的时候触发')
def set_AAA(self, val):
print('set 的时候触发 ',val)
def del_AAA(self):
print('del 的时候触发')
AAA = property(get_AAA,set_AAA,del_AAA)
#只有在属性 AAA 定义 property 后才能定义 AAA.setter, AAA.deleter
f = Foo()
f.AAA
f.AAA = 'bbb'
del f.AAA
输出结果跟上面是一模一样的
类创建实例对象,元类创建类,python 中任何 class 定义的类其实都是 type 类实例化的对象,类也可以直接用 type 来创建
class Foo:
def __init__(self):
pass
def __init__(self):
pass
earth = type('earth',(object,),{'__init__':__init__,'x':28})
print(earth.__dict__)
print('---------------------------------------------------------')
print(Foo)
print(Foo.__dict__)
print(type(Foo))
print(type(type(type(Foo)))) # type 又是谁创建的呢? 还是 type!
输出结果:
{'__init__': <function __init__ at 0x0000019D88944598>, 'x': 28, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'earth' objects>, '__weakref__': <attribute '__weakref__' of 'earth' objects>, '__doc__': None}
---------------------------------------------------------
<class '__main__.Foo'>
{'__module__': '__main__', '__init__': <function Foo.__init__ at 0x0000019D88944620>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
<class 'type'>
<class 'type'> # 类的类的类的类
自定义元类
class MyType(type):
def __init__(self, a, b, c):
print('元类的构造函数执行')
def __call__(self, *args, **kwargs):
obj = object .__new__(self)
self.__init__(obj, *args, **kwargs)
return obj
class Foo(metaclass=MyType):
def __init__(self, name):
self.name = name
f1 = Foo('alex')
最后一个就是 python 的异常与处理, try 与 except,还有 else ,exception,这些就不写了,可以看这个:
http://www.cnblogs.com/linhaifeng/articles/6232220.html
python 编程就学到这里了,下面学习一些模块
网友评论