Python24_魔法方法

2019-09-27  本文已影响0人  jxvl假装
  1. 使用__slot__后,不能再动态添加属性
  2. 使用__slot__后,每个子类都需要定义__slot__属性,这个属性不会被继承
# 对于一个对象
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age


s = Student("张3",23)
print(s.__dict__)

#这种内存利用率低
#使用__slot__
class Student:
    __slots__ = ("name", "age") #规定了以后只能有这两个属性,以元组方式

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

s = Student("zhang3",23)
print(s.name)
print(s.age)
print(s.__dict__)   #报错,提示没有这个属性

-** __contains__**

判断该类是否包含某个属性

判断两个对象是否相等,可以自己重写

描述符

是一个类,定义了访问另一个类属性的方式。

实现了__get__()__set__()的描述符称为数据描述符。

只实现了__get__()的描述符称为非数据描述符。

访问对象属性的时候:obj.attr,一般会先调用__getattribut__()方法,查找的顺序如下:

  1. 数据描述符
  2. __dict__属性
  3. 非数据描述符
class RevealAccess:
    def __init__(self, initval = None, name = "var"):
        self.val = initval
        self.name = name

    def __get__(self, instance, owner):
        print("获取...", self.name)
        return self.val
    #注意有set和无set时的区别
    def __set__(self, instance, value):
        print("设置值...",self.name)
        self.val = value

class MyClass:
    x = RevealAccess(10,"var_x")
    y = 5

    def __init__(self):
        pass

m = MyClass()
print(m.x)
m.x = "hello world"
print(m.x)

# 输出如下:
# 获取... var_x
# 10
# 设置值... var_x
# 获取... var_x
# hello world
# 延迟加载:即需要用到的时候再加载,可以减小不必要的资源占用
class InitOnAccess:
    def __init__(self, klass, *args, **kwargs):
        self.klass = klass
        self.args = args
        self.kwargs = kwargs
        self._initialized = None

    def __get__(self, instance, owner):
        if self._initialized is None:
            print("_initialized is None")
            self._initialized = self.klass(*self.args,**self.kwargs)
        else:
            print("cached")
        return self._initialized
    #ps:是一个非数据描述符,因为没有实现set方法

class TestClass:
    laze_initialized = InitOnAccess(list,"arguments")


t = TestClass()
t.laze_initialized
t.laze_initialized
#输出
# _initialized is None
# cached

-__getattr__

查找不存在的属性时调用

-__getattribute__

查找属性时调用,如果发现不存在,再调用getattr

-** __setattr__**

设置属性时调用

-** __delattr__**

删除属性时调用

class Cache:
    _cache = dict()
    # def __init__(self):
    #     self._cache = dict()

    def __setattr__(self,key, value):
        if not Cache._cache.keys().__contains__(key):
            Cache._cache[key] = []
        Cache._cache[key].append(value)

    def __getattr__(self, item):
        if not Cache._cache.keys().__contains__(item):
            return None
        return Cache._cache[item]


c = Cache()
c.user = "zhang3"
c.user = "li4"
print(c.user)

如果一个类重写了call方法,则在实例中可以通过对象名()对该方法进行调用

class Test:
    def __call__(self):
        print("hello wold")

t = Test()
t()

用于索引操作,如字典。以上分别表示获取、设置、删除数据

即:可以把对象当字典用

复习:当类中实现了__iter__方法和__next__方法,就是一个迭代器,可以用于for循环

class Foo:
    def __init__(self, name, age):
        self.info = {"name": name, "age": age}

    def __getitem__(self, item):
        return self.info[item]

    def __setitem__(self, key, value):
        self.info[key] = value

    def __delitem__(self, key):
        del self.info[key]
        
obj = Foo("zhagn3",23)

print(obj["name"])
obj["height"] = 174
print(obj["height"])
del obj["age"]
print(obj["age"])   # 报错
'''输出结果如下:
zhagn3
174
'''
上一篇 下一篇

猜你喜欢

热点阅读