21面向对象描述器

目录

1、什么是描述器?

1、原始的代码可以理解成为这样:

2、增加解释器可以改成如下,解释器就是集增删改查为一体的一个小的property

有一点需要注意的地方是:property里面内置的参数不是get_age()就是不用调用。

3、装饰器可以也放在前面

一些小注意和补缺:self.age=value会发生无限递归,为什么 self.__age = value不会发生无限递归?

4、有一个封装的思想,我觉得以后可能非常重要!!!

5、但是这样写的话,Age()这个就是共享的了


1、什么是描述器?

其实是一个类里面的属性,指向一个特殊的对象,但是这个对象具有:增,删,改,查四种实例方法。在外界尝试去操作一个描述器,解释器会去判断是否是一个描述器,如果是,会自动把外界的赋值操作转化成__Set__操作,转化的操作是解释器自己完成的。不需要人为的操作

21面向对象描述器_第1张图片

1、原始的代码可以理解成为这样:

class Person:
    def __init__(self):
        self.__age = 10
    def get_age(self):
        return self.__age
    def set_age(self,value):
        if value < 0:
            value = 0
        self.age = value
    def del_age(self):
        del self.__age
p = Person()
p.set_age(-100)
print(p.get_age())
p.del_age()
print(p.get_age())

2、增加解释器可以改成如下,解释器就是集增删改查为一体的一个小的property

class Person:
    def __init__(self):
        self.__age = 10
    def get_age(self):
        return self.__age
    def set_age(self,value):
        if value < 0:
            value = 0
        self.__age = value
    def del_age(self):
        del self.__age
    age = property(get_age,set_age,del_age)
    name = 'sz'
p = Person()
p.age = 19
print(p.age)

21面向对象描述器_第2张图片

有一点需要注意的地方是:property里面内置的参数不是get_age()就是不用调用。

3、装饰器可以也放在前面

class Person:
    def __init__(self):
        self.__age = 10
    @property
    def age(self):
        return self.__age
    @age.setter
    def age(self,value):
        if value < 0:
            value = 0
        self.__age = value
    @age.deleter
    def age(self):
        del self.__age
    # age = property(get_age,set_age,del_age)
    # name = 'sz'
p = Person()
p.age = 19
print(p.age)

一些小注意和补缺:self.age=value会发生无限递归,为什么 self.__age = value不会发生无限递归?

答:self.age = value是设置值,self.__age = value是访问私有变量,为啥是访问私有变量?因为在python内部有一个名字重整机制,就是会把__age改成 _类名__age因此,self.__age = value 其实是直接访问了重命名后的属性 _类名__age,而不是通过属性的 setter 方法来设置。这就避免了无限递归的问题。但需要注意的是,这种方式是一种绕过属性的 getter 和 setter 方法的机制,可能会绕过属性的其他逻辑,因此在使用时需要谨慎考虑。

4、有一个封装的思想,我觉得以后可能非常重要!!!

class Age:
    def __init__(self):
        self.__age = 10
    def get_age(self):
        return self.__age
    def set_age(self,value):
        if value < 0:
            value = 0
        self.__age = value
    def del_age(self):
        del self.__age

class Person:
    age = Age()

p = Person()
p.age = 19
print(p.age)

另外一个封装的案例

class Age:
    def __get__(self, instance, owner):
        print('get')
    def __set__(self, instance, value):
        print('set')
    def __delete__(self, instance):
        print('我被删除啦')
class Person:
    age = Age()
p = Person()
p.age = 10
print(p.age)

上面那块的增删改查,全部被封装在Age的这个函数里面了,下面只需要直接调用就可以了~

class的Age也是一个类,但是在Person那块也是一个类,所以可以试着去调用类的方法看看能不能触发set和del的属性

class Age:
    def __get__(self, instance, owner):
        print('get')
    def __set__(self, instance, value):
        print('set')
    def __delete__(self, instance):
        print('我被删除啦')
class Person:
    age = Age()
# p = Person()
# p.age = 10
# print(p.age)
print(Person.age)
Person.age = 19
del Person.age

结果如下:只会获得,但是不会,set和del了,所以以后用装饰器的时候,还是用对象去操作比较好!21面向对象描述器_第3张图片

5、但是这样写的话,Age()这个就是共享的了

你可能感兴趣的:(python,开发语言)