面向对象进阶1

# 描述符的应用
class Aoo:
    def __init__(self,key,expected_type):
        self.key = key
        self.expected_type = expected_type

    def __get__(self,instance,owner):
        return instance.__dict__[self.key]

    def __set__(self,instance,value):
        if not isinstance(value,self.expected_type):
            raise TypeError("%s传入的类型不是%s"%(self.key,self.expected_type))
        instance.__dict__[self.key] = value

    def __delete__(self,instance):
        instance.__dict__pop(self.key)

class Foo:
    name = Aoo("name",str)
    age  = Aoo("age",int)

    def __init__(self,name,age):
        self.name = name
        self.age = age

r = Foo("lwj",18)
print(r.name)
print(r.age)

 

# 类的装饰器
def deco(obj):
    obj.a = 2
    obj.b = 20
    return obj

@deco  # Aoo = deco(Aoo)
class Aoo:
    pass

Aoo()
print(Aoo.__dict__)

 

# 类的装饰器修订
def pice(**kwargs):
        def deco(obj):
            for key,values in kwargs.items():
                setattr(obj,key,values)
            return obj
        return deco

@pice(a=2,x=20)  # deco = pice(a=2,x=20)  Aoo= deco(Aoo)
class Aoo:
    pass

Aoo()
print(Aoo.__dict__)

 

# 类的装饰器应用
class Aoo:
    def __init__(self,key,expected_type):
        self.key = key
        self.expected_type = expected_type

    def __get__(self,instance,owner):
        return instance.__dict__[self.key]

    def __set__(self,instance,value):
        if not isinstance(value,self.expected_type):
            raise TypeError("%s传入的类型不是%s"%(self.key,self.expected_type))
        instance.__dict__[self.key] = value

    def __delete__(self,instance):
        instance.__dict__pop(self.key)

def pice(**kwargs):  # kwargs = {"name":str,"age":int}
    def deco(obj):      # obj = Foo
        for key,values in kwargs.items():   # (("name",str),("age",int))
            setattr(obj,key,Aoo(key,values)) # setattr(Foo,"name",Aoo("name",str))
        return obj
    return deco
 
@pice(name=str,age=int) # deco = pice(name=str,age=int)  Foo = deco(Foo)
class Foo:
    name = Aoo("name",str)
    age  = Aoo("age",int)

    def __init__(self,name,age):
        self.name = name
        self.age = age

r = Foo("lwj",18)
print(r.__dict__)

 

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

class Open:
    def __init__(self,name):
        self.name=name

    def __enter__(self):
        print("with语句,对象的__enter__被触发,有返回值则赋值给r声明的变量")
        #return self

    def __exit__(self,exc_type,exc_val,exc_tb):
        print("with中代码块执行完毕时执行我")

with Open("a.txt")as r:
    print("sb")
print("2222222")

 

__exit__()中三个参数分别代表异常类型,异常值和追溯信息,with语句中代码出现异常则with后的代码都无法执行

class Open:
    def __init__(self,name):
        self.name=name

    def __enter__(self):
        print("with语句,对象的__enter__被触发,有返回值则赋值给r声明的变量")
        #return self

    def __exit__(self,exc_type,exc_val,exc_tb):
        print("with中代码块执行完毕时执行我")

with Open("a.txt")as r:
    print("sb")
    print(ssdasdad)
    print("111111111111111")
print("2222222")

 

如果__exit__()返回值为True,那么异常会被清空,就好像什么都没发生一样,with后的语句正常执行

class Open:
    def __init__(self,name):
        self.name=name

    def __enter__(self):
        print("with语句,对象的__enter__被触发,有返回值则赋值给r声明的变量")
        #return self

    def __exit__(self,exc_type,exc_val,exc_tb):
        print("with中代码块执行完毕时执行我")
        return True

with Open("a.txt")as r:
    print("sb")
    print(ssdasdad)
    print("111111111111111")
print("2222222")

 

1、引子
class Aoo:
    pass
r = Aoo() # r 是通过Aoo类实例化的对象
python中一切皆对象,类本身也是一个对象,当使用关键字class的时候python解析器在加载class的时候就会创建一个对象(这里的对象指的是类而非类的实例)

上例可以看出r是由Aoo这个类产生的对象,而Aoo本身也是对象,那它又是由哪个类产生的呢?
type函数可以查看类型,也可以用来查看对象的类,二者都是一样的
print(type(r)) # 输出:<class ‘__main__.Aoo‘>  表示,obj 对象由Aoo类创建
print(type(Aoo))  # 输出:<type ‘type‘>

2、什么是元类
元类是类的类,是类的模板
元类是用来控制如何创建类的,正如类是创建对象的模板一样
元类是实例为类,正如类的实例为对象(r对象是Aoo的一个实例,Aoo类是type类的一个实例)
type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是typr类实例化的对象

3、创建元类的两种方法
第一种:
class Aoo:
    def __init__(self):
        pass

第二种:
def __init__(self,name,age):
    self,name = name
    self.age = age
Aoo = type("Aoo",(object,),{"x":1,"__init__":__init__})

4、一个类没有声明自己的元类,默认它的元类就是type,除了使用元类type,用户也可以通过继承typr来自定义元类
class Mytepy(type):
    def __init__(self,a,b,c):
        pass

    def __class__(self,*args,**kwargs):
        obj = object.__new__(self)  # obj = object.__new__(Aoo)
        self.__init__(obj,*args,**kwargs) # Aoo.__init__(r,*args,**kwargs)
        return obj  # 返回 r

class Aoo(metaclass=Mytepy): # Aoo = Mytepr("Aoo",(object,),{"name":name}) ---> __init__
    def __init__(self,name):
        self.name = name
r = Aoo("lwj")
print(r.name)

 

利用描述符自定制property
class Lazyproperty:
    def __init__(self,func):
        self.func = func

    def __get__(self,instance,owner):
        if instance is None:
            return self
        res = self.func(instance) # res = self.area(r)
        setattr(instance,self.func.__name__,res)  # r,area,运行area的结果
        return res

class Aoo:
    def __init__(self,name,width,length):
        self.name = name
        self.width = width
        self.length = length

    @Lazyproperty  # area = Lazypropery(area)
    def area(self):
        return self.width * self.length

r = Aoo("未知",2,20)
# 实例调用
print(r.area)
# 类调用
print(Aoo.area)

 

property补充
# 只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter

class Aoo:
    @property
    def AAA(self):
        print("get的时候运行我")

    @AAA.setter
    def AAA(self,val):
        print("set的时候运行我")

    @AAA.deleter
    def AAA(self):
        print("deleter的时候运行我")
r = Aoo()
r.AAA
r.AAA = "aaa"
del r.AAA



class Aoo:
    def get_AAA(self):
        print("get的时候运行我")

    def set_AAA(self,val):
        print("set的时候运行我")

    def del_AAA(slef):
        print("deleter的时候运行我")
    AAA = property(get_AAA,set_AAA,del_AAA)
r = Aoo()
r.AAA
r.AAA = "aaa"
del r.AAA

 

property 用法

class Aoo:
    def __init__(self):
        # 原价
        self.original_price = 100
        # 折扣
        self.discount = 0.8

    @property
    def price(self):
        # 实际价格 = 原价 * 折扣
        new_pirce = self.original_price * self.discount 
        return new_pirce

    @price.setter
    def price(self,value):
        self.original_price  = value

    @price.deleter
    def price(self):
        del self.original_price

a = Aoo()
print(a.price)  # 获取商品价格
a.price = 200 # 修改商品原价
print(a.price)
del a.price      # 删除商品原价
# print(a.price)
相关文章
相关标签/搜索