python-redis缓存装饰器,2024年最新美团网络安全面试题

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注网络安全)
img

正文

    return deco

def \_de\_ser\_json(self, func):
    @functools.wraps(func)
    def func\_wrapper(\*args, \*\*kwargs):
        return json.loads(func(\*args, \*\*kwargs))

    return func_wrapper

def \_ser\_json(self, func):
    @functools.wraps(func)
    def func\_wrapper(\*args, \*\*kwargs):
        return json.dumps(json.loads(func(\*args, \*\*kwargs)))

    return func_wrapper

def json(self, ttl=None):
    def deco(func):
        for dec in [self._ser_json, self.ttl(ttl), self._de_ser_json]:
            func = dec(func)
        return func

    return deco

if name == ‘__main__’:
pass


* Cache类:缓存
	+ \_\_init\_\_:初始化,必须使用StrictRedis、参数decode\_responses=True
	+ ttl:设置过期时间,单位s
	+ key\_generator:生成key,没填写时,生成redis\_dec:方法名:参数1:参数2…形式的key
	+ delete\_cache:删除缓存,删除全部缓存、指定函数缓存、指定函数及参数缓存
	+ df:缓存df类型数据
	+ int: 缓存int类型数据
	+ float: 缓存float类型数据
	+ dict:缓存dict类型数据
	+ list :缓存list类型数据
	+ json:缓存json类型数据,和dict一样


### 使用


测试缓存int值



python -m unittest test.Test.test_my_int_function


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/4ef5016521344fef8acaf09e31bed767.png)  
 测试批量删除



python -m unittest test.Test.test_delete


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/7ba101aaaff54656aba1c7e027563701.png)  
 测试key生成与删除



python -m unittest test.Test.test_gen_key_delete


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/b23929a39284438e84f215f6afe91891.png)


## redis\_decorators


### 安装


这里先安装一个其他人写的,体验一下



pip install redis_decorators



Successfully installed async-timeout-4.0.3 importlib-metadata-6.7.0 redis-5.0.3 redis-decorators-1.0.1 typing-extensions-4.7.1 zipp-3.15.0


注意:使用时如果报错,需要先删除\_\_init\_\_.py的12行


### 查看源代码


#### \_\_init\_\_.py



from .cache_element import CacheDateTime, CacheElement, CacheElementSingleType
from .cacheable import (
Cacheable,
DictCacheable,
DictCacheType,
DictStringCacheable,
ListCacheable,
ListCacheType,
StringCacheable
)
from .caching import RedisCaching, build_redis_url


初始化,导入各种包


#### cacheable.py 各种可缓存的类型



from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Dict, Generic, List, Optional, TypeVar

from redis import Redis

StoreType = TypeVar(‘StoreType’)
ListCacheType = List[str]
DictCacheType = Dict[str, str]

class Cacheable(Generic[StoreType], ABC):
“”"Performs caching store and fetch operations for a specific type.

Subclass to define how to handle a specific type.
“”"

@abstractmethod
def store(self, client: Redis, key: str, value: StoreType) -> None:
    """Store a value in cache.

Args:
client (Redis): Cache to store in.
key (str): Name of cache value.
value (StoreType): Value to store.

Returns:
None
“”"
pass # pragma: nocover

@abstractmethod
def fetch(self, client: Redis, key: str) -> Optional[StoreType]:
    """Fetch a value from cache.

Args:
client (Redis): Cache to fetch from.
key (str): Name of cache value.

Returns:
StoreType or None: Value fetched from cache or None if no value exists.
“”"
pass # pragma: nocover

class StringCacheable(Cacheable[str]):
def store(self, client: Redis, key: str, value: str):
client.set(key, value)

def fetch(self, client: Redis, key: str) -> Optional[str]:
    return client.get(key)

@dataclass
class DictStringCacheable(Cacheable[str]):
“”"
Attributes:
dict_key (str): Name of hash value.
“”"

dict_key: str

def store(self, client: Redis, key: str, value: str):
    client.hset(key, self.dict_key, value)

def fetch(self, client: Redis, key: str) -> Optional[str]:
    return client.hget(key, self.dict_key)

class DictCacheable(Cacheable[DictCacheType]):
def store(self, client: Redis, key: str, value: DictCacheType):
client.hset(key, mapping=value)

def fetch(self, client: Redis, key: str) -> Optional[DictCacheType]:
    return client.hgetall(key) or None

class ListCacheable(Cacheable[ListCacheType]):
def store(self, client: Redis, key: str, value: ListCacheType):
client.delete(key)
client.rpush(key, *value)

def fetch(self, client: Redis, key: str) -> Optional[ListCacheType]:
    return client.lrange(key, 0, -1) or None

* Cacheable类:**抽象类**,不可实例化。对特定类型执行缓存存储(store)和提取(fetch)操作。子类来定义如何处理特定类型。
* StringCacheable类:Cacheable子类,使用set、get处理字符串。
* DictStringCacheable类:Cacheable子类,使用hset、hget处理字典,有dict\_key,有dataclass装饰,将会自动添加\_\_init\_\_等方法。
* DictCacheable类:Cacheable子类,使用hset、hgetall处理字典。
* ListCacheable类:Cacheable子类,使用delete、rpush、lrange处理列表。


#### cache\_element.py 缓存的元素



from abc import ABC, abstractmethod
from dataclasses import dataclass
from datetime import datetime
from typing import Generic, Optional, TypeVar

from redis import Redis

from .cacheable import Cacheable, StringCacheable

FetchType = TypeVar(‘FetchType’)
StoreType = TypeVar(‘StoreType’)

class CacheElement(Generic[FetchType, StoreType], ABC):
“”"Get and set cache values.

Attributes:
    cacheable (Cacheable): Instance used to store and fetch values.
"""

cacheable: Cacheable[StoreType]

def get_value(self, client: Redis, key: str) -> Optional[FetchType]:
    """Returns cached value or None if no value exists."""
    value = self.cacheable.fetch(client, key)
    if value is None:
        return None

    return self.load(value)

def set_value(self, client: Redis, key: str, value: FetchType) -> None:
    """Set value in cache.

    Args:
        client (Redis): Cache to fetch from.
        key (str): Name of cache value.

    Returns:
        None
    """
    self.cacheable.store(client, key, self.dump(value))

@abstractmethod
def load(self, value: StoreType) -> FetchType:
    """Load value from cache into expected Python type."""
    pass  # pragma: nocover

@abstractmethod
def dump(self, value: FetchType) -> StoreType:
    """Dump value from Python type into type expected by cache."""
    pass  # pragma: nocover

@dataclass
class CacheElementSingleType(CacheElement[FetchType, FetchType]):
“”"A CacheElement that fetches the same type that it stores.

By default, values are passed to and from cache as-is, i.e. no serialization
or deserialization is performed.

For example, a string can be stored and fetched without modification whereas
a datetime would need to be serialized for storage and deserialized for
retrieval.
"""

cacheable: Cacheable[FetchType]

def load(self, value: FetchType) -> FetchType:
    return value

def dump(self, value: FetchType) -> FetchType:
    return value

@dataclass
class CacheDateTime(CacheElement[datetime, str]):
“”“Store and fetch datetime values with string serialization.”“”

cacheable: Cacheable[str] = StringCacheable()

def dump(self, value: datetime) -> str:
    return value.isoformat()

def load(self, value: str) -> datetime:
    return datetime.fromisoformat(value)

* CacheElement类:**抽象类**。缓存元素,子类实现设置和获取缓存值。
* CacheElementSingleType类:CacheElement子类,有cacheable,有dataclass装饰,自动添加\_\_init\_\_等方法。
* CacheDateTime类:CacheElement子类,通过字符串序列化的方式缓存日期类型,有cacheable,有dataclass装饰,自动添加\_\_init\_\_等方法。


#### caching.py 缓存主要逻辑



from datetime import timedelta
from functools import partial, update_wrapper
from typing import Any, Callable, Optional, Union

from redis import Redis

from .cache_element import CacheDateTime, CacheElement, CacheElementSingleType
from .cacheable import (
DictCacheable,
DictCacheType,
DictStringCacheable,
ListCacheable,
ListCacheType,
StringCacheable
)

class RedisCaching:
“”“Provides decorators for automatic caching.”“”

cache_cls = Redis
_cache_instances = {}

def \_\_init\_\_(self, url=None, \*\*kwargs):
    self._default_cache_kwargs = {'decode\_responses': True, 'socket\_timeout': 15}
    self.init(url, \*\*kwargs)

def init(self, url, \*\*kwargs):
    self._url = url
    self._cache_kwargs = {
        \*\*self._default_cache_kwargs,
        \*\*kwargs,
    }

def get\_cache(self) -> Redis:
    if self._url in self._cache_instances:
        return self._cache_instances.get(self._url)

    cache = self.cache_cls.from_url(self._url, \*\*self._cache_kwargs)
    self._cache_instances[self._url] = cache
    return cache

def delete(self, cache_key: str):
    self.get_cache().delete(cache_key)

def cache\_value(
    self,
    cache_element: CacheElement,
    get_cache_key: Callable[..., str] = None,
    expire_in: Union[int, timedelta] = None,
):
    """Decorate a function to automatically cache its return value.

Wrapper does two things:

  1. If cached value does not exist, cache the return value of the function.
  2. If cached value exists, return it instead of calling the function.

Args:
cache_element (CacheElement): Instance used to get and set cache value.
get_cache_key (Callable): Function that returns name of cache value.
Accepts the same arguments as the decorated function.
expire_in (Union[int, timedelta]): Number of seconds until this key
expires after being set. Can be a datetime.timedelta object.

Examples:
Decorate a function that returns a string:
… code-block:: python

@cache.cache_string(get_cache_key=lambda arg: f’object:{arg}')
def expensive_fetch_operation(arg) -> str:

return computed_value

Use cache\_key of decorated function to set get\_cache\_key:
… code-block:: python

@cache.cache_string()
def expensive_fetch_operation(arg) -> str:

return computed_value

@expensive_fetch_operation.cache_key
def expensive_fetch_operation_cache_key(arg) -> str:

return computed_value
“”"

    def decorator(func):
        return CacheValueWrapper(
            self, func, cache_element, get_cache_key, expire_in
        )

    return decorator

def cache\_string(self, get_cache_key: Callable[..., str] = None, \*\*kwargs):
    """Decorate a function to store a string."""
    return self.cache_value(
        CacheElementSingleType[str](cacheable=StringCacheable()),
        get_cache_key,
        \*\*kwargs,
    )

def cache\_dict(self, get_cache_key: Callable[..., str] = None, \*\*kwargs):
    """Decorate a function to store a dictionary {str: str}."""
    return self.cache_value(
        CacheElementSingleType[DictCacheType](cacheable=DictCacheable()),
        get_cache_key,
        \*\*kwargs,
    )

def cache\_dict\_string(self, dict_key: str, get_cache_key=None, \*\*kwargs):
    """Decorate a function to store a specific key inside a cached hash."""
    return self.cache_value(
        CacheElementSingleType[str](cacheable=DictStringCacheable(dict_key)),
        get_cache_key,
        \*\*kwargs,
    )

def cache\_list(self, get_cache_key: Callable[..., str] = None, \*\*kwargs):
    """Decorate a function to store a list of strings."""
    return self.cache_value(
        CacheElementSingleType[ListCacheType](cacheable=ListCacheable()),
        get_cache_key,
        \*\*kwargs,
    )

def cache\_datetime(self, get_cache_key: Callable[..., str] = None, \*\*kwargs):
    """Decorate a function to store a datetime."""
    return self.cache_value(CacheDateTime(), get_cache_key, \*\*kwargs)

class CacheValueWrapper:
def __init__(
self,
caching: RedisCaching,
func: Callable,
cache_element: CacheElement,
get_cache_key: Optional[Callable[…, str]] = None,
expire_in: Union[int, timedelta] = None,
):
self._caching = caching
self._func = func
self._cache_element = cache_element
self._get_cache_key = get_cache_key
self._expire_in = expire_in
update_wrapper(self, func)

def \_\_call\_\_(self, \*args: Any, \*\*kwargs: Any):
    cache_key = self._calculate_cache_key(\*args, \*\*kwargs)
    value = self._cache_element.get_value(self._caching.get_cache(), cache_key)

    if value is None:
        client = self._caching.get_cache()
        value = self._func(\*args, \*\*kwargs)
        self._cache_element.set_value(client, cache_key, value)
        expire_in = self._calculate_expire_in(value, \*args, \*\*kwargs)

        if expire_in:
            client.expire(cache_key, expire_in)

    return value

def \_\_get\_\_(self, instance, owner):
    return partial(self, instance)

def cache\_key(self, func):
    self._get_cache_key = func
    return func

def expire\_in(self, func):
    self._expire_in = func
    return func

def \_calculate\_expire\_in(self, value, \*args, \*\*kwargs):
    if callable(self._expire_in):
        kwargs['value'] = value
        return self._expire_in(\*args, \*\*kwargs)

    return self._expire_in

def \_calculate\_cache\_key(self, \*args: Any, \*\*kwargs: Any):
    if self._get_cache_key is None:
        arg_str = ':'.join([self._func.__name__, \*[str(arg) for arg in args], str(kwargs)])
        return ':'.join(['redis\_decorators', arg_str])

    return self._get_cache_key(\*args, \*\*kwargs)

def build_redis_url(host, password, db, use_secure=True):

prefix = 'rediss' if use_secure else 'redis'

if password:
    url = f'{prefix}://:{password}@{host}'
else:
    url = f'{prefix}://{host}'

if db:
    url = f'{url}/{db}'

return url

* RedisCaching类:提供自动化缓存装饰器


	+ get\_cache方法:获取Redis实例
	+ delete方法:删除指定key
	+ cache\_value:装饰器,自动缓存函数返回值
	+ cache\_string:缓存字符串
	+ cache\_dict:缓存字典
	+ cache\_dict\_string:
	+ cache\_list:缓存列表
	+ cache\_datetime:缓存日期时间
* CacheValueWrapper类:


	+ cache\_key:缓存key
	+ expire\_in:过期时间
	+ \_calculate\_cache\_key:如果cache\_key为None时,计算key为redis\_decorators:函数名:参数1:参数2…
	+ \_calculate\_expire\_in:计算过期时间
* build\_redis\_url:根据参数构建url


### 使用


缓存字符串



python -m unittest test.Test.test_my_string_function

本人从事网路安全工作12年,曾在2个大厂工作过,安全服务、售后服务、售前、攻防比赛、安全讲师、销售经理等职位都做过,对这个行业了解比较全面。

最近遍览了各种网络安全类的文章,内容参差不齐,其中不伐有大佬倾力教学,也有各种不良机构浑水摸鱼,在收到几条私信,发现大家对一套完整的系统的网络安全从学习路线到学习资料,甚至是工具有着不小的需求。

最后,我将这部分内容融会贯通成了一套282G的网络安全资料包,所有类目条理清晰,知识点层层递进,需要的小伙伴可以点击下方小卡片领取哦!下面就开始进入正题,如何从一个萌新一步一步进入网络安全行业。

学习路线图

其中最为瞩目也是最为基础的就是网络安全学习路线图,这里我给大家分享一份打磨了3个月,已经更新到4.0版本的网络安全学习路线图。

相比起繁琐的文字,还是生动的视频教程更加适合零基础的同学们学习,这里也是整理了一份与上述学习路线一一对应的网络安全视频教程。

网络安全工具箱

当然,当你入门之后,仅仅是视频教程已经不能满足你的需求了,你肯定需要学习各种工具的使用以及大量的实战项目,这里也分享一份我自己整理的网络安全入门工具以及使用教程和实战。

项目实战

最后就是项目实战,这里带来的是SRC资料&HW资料,毕竟实战是检验真理的唯一标准嘛~

面试题

归根结底,我们的最终目的都是为了就业,所以这份结合了多位朋友的亲身经验打磨的面试题合集你绝对不能错过!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注网络安全)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

经不能满足你的需求了,你肯定需要学习各种工具的使用以及大量的实战项目,这里也分享一份我自己整理的网络安全入门工具以及使用教程和实战。

项目实战

最后就是项目实战,这里带来的是SRC资料&HW资料,毕竟实战是检验真理的唯一标准嘛~

面试题

归根结底,我们的最终目的都是为了就业,所以这份结合了多位朋友的亲身经验打磨的面试题合集你绝对不能错过!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注网络安全)
[外链图片转存中…(img-jCDnVAyQ-1713363785231)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 29
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值