with 上下文管理
包含__enter__/__exit__的模块
classWithTest:def __init__(self, name):print("这里是初始化")
self.name=namedef __enter__(self):print("这里是%s的enter" %self.name)returnselfdef __exit__(self, exc_type, exc_val, exc_tb):print("这里是%s的exit" %self.name)print("exc_type", exc_type)print("exc_val", exc_val)print("exc_tb", exc_tb)returnTrue
with WithTest("zgl") as f:print(f.name)print(sss)print("---------->")
输出如下
这里是初始化
这里是zgl的enter
zgl
这里是zgl的exit
exc_typeexc_val name'sss' is notdefined
exc_tb
首先Withtest("zgl"),如果这里出错,上下文管理器是管理不到的,始终会报错,除非再外层加try/except
然后进入__enter__, 要return self 否则f接受到的是None类型
然后开始执行,上下文里面的内容,对于里面的变量赋值,外层函数也可以用,比如a =1 在最外层也是可以用的
如果报错,立刻进入__exit__, exc_type返回的异常类型, exc_val返回的是异常信息, exc_tb返回的是异常栈
如果__exit__返回True,则不报错,进行控制,编译器不发出异常,如果不返回True,则编译器仍然报错
之后不在执行后面的代码,推出上下文管理
类装饰器
类装饰器定义
在类外加上装饰器,使其增加附加功能,返回类
#给每个类添加一个数据属性和一个函数属性
def Decorator(obj):#print(School.__dict__)
#添加数据属性
obj.addr = "浙江省杭州市"
defprice():pass
#添加函数属性
obj.price =pricereturnobj #一定返回的是类本身
@Decorator#相当于执行 School = Decorator(School)
classSchool():def __init__(self,name,price):
self.name=name
self.price=price#打印类的属性字典
print(School.__dict__)
#
{'__module__': '__main__', '__init__': , '__dict__': , '__weakref__': , '__doc__': None, 'addr': '浙江省杭州市', 'price': .price at 0x035D8588>}
带参数的类装饰器
添加可变参数,易于管理,
#给每个类添加一个可变的数据属性
def Decorator(**kwargs):defadd(obj):"添加数据属性"
#print('调用外部函数的**kwargs',kwargs)
for key,val inkwargs.items():#添加数据属性
setattr(obj,key,val) #不可以用obj.__dict__ 的修改操作,是不可变更字典类型returnobj#print("外部传入的参数为:",kwargs)
returnadd
@Decorator(addr= "浙江省杭州市",name ="浙江大学") #执行顺序:1.运行Decorator函数,先打印外部的传入的参数,返回add函数名;2.再执行School = add(School)
classSchool():def __init__(self,price):
self.price=price
@Decorator(addr= "湖北省",price =12000)classSchool1():pass
print(School.__dict__)print(School1.__dict__)
装饰器类
和上面不同,是把类作为装饰器,相当于类的初始化
做一个Property类,把类中的函数变成静态变量
classProperty:def __init__(self, func):
self.func=funcdef __get__(self, instance, owner):#print(self, instance, owner)
#self 调用对象,也就是score实例, instance是test实例 owner归属的类Test
if notinstance:return self #如果类调用返回对象
return self.func(instance) #实例调用这
def __set__(self, instance, value):#print(self, instance, value)
instance.__dict__[ self.func.__name__ ] = value #修改实例test字典
classTest:def __init__(self, mark, discount):
self.mark=mark
self.discount=discount
@Property#实例f = Property(score) 这里是类,数据描述符
defscore(self):return self.mark *self.discount
@propertydefscore1(self):return self.mark *self.discount
test= Test(10, 0.8)#print(Test.score1) ##print(Test.score) #<__main__.property object at>#print(test.score1) #8.0#print(test.score) #8.0
test.score = 1
print(test.__dict__)print(test.__dict__["score"])print(test.score) #8.0 要想使用__dict__的,必须不加__set__, 在__get__里面修改 set(obj, name, value)
做一个classmethod类,把类中的方法变成类方法
本来想通过__call__实现,但是最后,不会获取函数的外层类,所以失败,如果只写Test,那太固定了,没意思,希望厉害的人回复,怎么获取函数的外层类,不是函数的类
classClassmethond:def __init__(self, func):
self.func=funcdef __get__(self, instance, owner):def wrap(*args, **kwargs):return self.func(owner, *args, **kwargs)returnwrap#def __call__(self, *args, **kwargs):
## print(self.cla , self, *args, **kwargs)
#return self.func(self.cla , *args, **kwargs) #本来想通过__call__实现,但是最后,不会获取函数的外层类,所以失败,如果只写Test,那太固定了,没意思
classTest:
x= 1
def __init__(self, mark, discount):
self.mark=mark
self.discount=discount
@Classmethond#实例f = Property(score) 这里是类,数据描述符
defscore(cls):print(cls, cls.x)
@classmethoddefscore1(cls):print(cls, cls.x)
Test.score1()# 1
Test.score() # 1
test= Test(1, 0.8)
test.score1()# 1
test.score() # 1
做一个staticmethod 类,把类中的方法变成静态方法
classStaticmethod:def __init__(self, func):
self.func=funcdef __get__(self, instance, owner):returnself.func#def __call__(self, *args, **kwargs):
## print(self.cla , self, *args, **kwargs)
#return self.func(self.cla , *args, **kwargs)
classTest:
x= 1
def __init__(self, mark, discount):
self.mark=mark
self.discount=discount
@Staticmethoddefscore():print("静态方法")
@staticmethoddefscore1():print("这是静态方法1")#Test.score1()
Test.score1() #这是静态方法1
Test.score() #静态方法
test= Test(10, 0.8)
test.score1()#这是静态方法1
test.score() #静态方法
元类 type 自定义(类名,父类,属性)
元类定义
元类就是用来创建类的“东西”。你创建类就是为了创建类的实例对象,不是吗?但是我们已经学习到了Python中的类也是对象。好吧,元类就是用来创建这些类(对象)的,元类就是类的类,
因此,元类就是创建类这种对象的东西。如果你喜欢的话,可以把元类称为“类工厂”(不要和工厂类搞混了:D) type就是Python的内建元类,当然了,你也可以创建自己的元类。
type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))
class Foo(object):
__metaclass__ = something…
[…]
Python做了如下的操作:
Foo中有__metaclass__这个属性吗?如果是,Python会在内存中通过__metaclass__创建一个名字为Foo的类对象(我说的是类对象,请紧跟我的思路)。如果Python没有找到__metaclass__,它会继续在Bar(父类)中寻找__metaclass__属性,并尝试做和前面同样的操作。如果Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。如果还是找不到__metaclass__,Python就会用内置的type来创建这个类对象。
现在的问题就是,你可以在__metaclass__中放置些什么代码呢?答案就是:可以创建一个类的东西。那么什么可以用来创建一个类呢?type,或者任何使用到type或者子类化type的东东都可以。
抽象函数
importabcclass Abs(metaclass=abc.ABCMeta):#class Abs(object):#__metaclass__ = abc.ABCMeta #这个命名方式不行,不知道为什么 是python3 新修改的么
@abc.abstractmethoddefabstar(self):pass
print(Abs.__dict__)
abcd= Abs()
自定义元类
classUpperAttrMetaclass(type):def __new__(cls, name, bases, dct):
attrs= ((name, value) for name, value in dct.items() if not name.startswith('__'))
uppercase_attr= dict((name.upper(), value) for name, value inattrs)return super(UpperAttrMetaclass, cls).__new__(cls, name, bases, uppercase_attr)class A(metaclass=UpperAttrMetaclass):pass
就是这样,除此之外,关于元类真的没有别的可说的了。使用到元类的代码比较复杂,这背后的原因倒并不是因为元类本身,而是因为你通常会使用元类去做一些晦涩的事情,依赖于自省,控制继承等等。确实,用元类来搞些“黑暗魔法”是特别有用的,因而会搞出些复杂的东西来。但就元类本身而言,它们其实是很简单的:
1) 拦截类的创建
2) 修改类
3) 返回修改之后的类
属性描述符、property(@setter,@deleter)和__setattr__
我这是么理解的,
property用于的是少数属性的控制,1个2个
属性描述符用于的是某些的相同属性的控制 具有相同属性
__setattr__ 全部属性的控制,当然也可以部分,不够代码结构复杂
__get__ __getAttribute__ ___getattr__ __getitem__ 顺序
__get__使用在数据描述符中,暂时不考虑,后面三个的优先级顺序为__getitem__ > __getAttribute__ >___getattr__
对类属性A.x的获取不触发,对a.x的获取才触发
其他set del的顺序和这个一致,
__del__是析构函数是在实例删除时候触发的
classA:
data= 1
def __init__(self, id):
self.id=iddef __getattribute__(self, item):print("这里是getattribute",item)#raise AttributeError
#print("这是getattribute后期")
#return object.__getattribute__(self, item)
return super(A, self).__getattribute__(item)def __getattr__(self, item):print("这里是getattr")def __getitem__(self, item):print("这里是getitem", item)#raise AttributeError
return self.__dict__[item]#return object.__getattribute__(self, item)
#if item in self.__dict__:
#return self.__dict__[item]
#else:
#raise ValueError
a = A("11")print(a.__dict__)#这里是getattribute __dict__#{'id': '11'}
print(a.data)#这里是getattribute data#1
print(a.x)#这里是getattribute x#这里是getattr#None
print(a["x"])#这里是getitem x#这里是getattribute __dict__###KeyError: 'x'
print(a["data"])#这里是getitem data#这里是getattribute __dict__#KeyError: 'data'
print(a["id"])#这里是getitem id#这里是getattribute __dict__#11