皮皮网

【zjdroid 源码】【美业saas系统源码】【游戏之家手游源码】getattr源码

来源:自瞄源码网 时间:2024-11-23 04:07:32

1.django中request.user的由来
2.说说 Python 的元编程

getattr源码

django中request.user的由来

       在 Django 中,`request.user` 是一个用于获取当前登录用户信息的对象。当用户没有登录时,`request.user` 会返回一个 `AnonymousUser` 对象。那么这个 `AnonymousUser` 对象是从何而来呢?要理解这一点,我们首先得了解一下 `request.user` 的zjdroid 源码工作原理。

       在 Django 的源代码中,`request.user` 的实现涉及到了中间件机制。当请求到来时,中间件会按照定义的顺序执行 `process_request` 函数。在其中,通过 `assert` 断言检查 `session` 中间件是否在 `auth` 中间件之前执行,因为 `auth` 中间件依赖于之前登录的美业saas系统源码 `session` 信息来判断当前用户是否已登录。

       具体来说,当 `session` 中间件执行完毕后,`request.user = SimpleLazyObject(lambda: get_user(request))` 的语句会设置 `request.user` 的值。这里的 `lambda: get_user(request)` 返回的是一个函数对象,而不是立即执行。`SimpleLazyObject` 是游戏之家手游源码一个特殊的对象,它的作用是在实际需要时才调用该函数并获取结果。

       `SimpleLazyObject` 的 `__init__` 方法接收一个函数作为参数,并将其存储在 `_setupfunc` 属性中。在 `get_user(request)` 被调用之前,这个函数并没有被执行,因此 `request.user` 的梦幻西游08怀旧源码值是 `SimpleLazyObject` 实例。

       当尝试访问 `request.user` 的属性,如 `username` 时,会触发 `__getattr__` 方法。由于 `SimpleLazyObject` 并未定义 `__getattr__` 方法,因此会向上查找父类 `LazyObject`。在 `LazyObject` 的bc源码技术论坛 `__init__` 方法中,定义了 `__getattr__` 方法,它返回一个代理函数 `new_method_proxy(getattr)`,使得在需要时才调用实际的 `getattr` 函数。

       当访问 `request.user.username` 等属性时,实际上是在调用 `inner` 函数,这个函数内部首先检查 `_wrapped` 属性是否为空。第一次访问时,`_wrapped` 为 `empty` 类型,因此会调用 `_setup` 函数来初始化实际的用户对象。这个过程涉及到了 `get_user(request)` 函数,实际上这个函数会根据当前的 `request` 对象来确定当前用户的身份。

       `get_user(request)` 函数会调用 `auth.get_user(request)`,这会尝试从 `request.session` 中获取用户 ID,如果 `request.session` 中没有 `auth_user_id` 键,那么 `auth.get_user(request)` 会返回 `AnonymousUser()` 对象。

       至此,我们了解到 `AnonymousUser` 对象是通过中间件和 `get_user(request)` 函数的交互过程生成的。当 `request.user` 为空或者用户未登录时,`AnonymousUser` 对象被创建并返回给 `request.user`,以表示当前用户是匿名的。这一机制确保了在没有用户登录时,`request.user` 的行为是一致的。

       希望上述解释能够帮助你理解 `request.user` 的实现以及 `AnonymousUser` 对象的由来。若有更多问题或需要更深入的了解,请随时提问。

说说 Python 的元编程

       æåˆ°å…ƒè¿™ä¸ªå­—,你也许会想到元数据,元数据就是描述数据本身的数据,元类就是类的类,相应的元编程就是描述代码本身的代码,元编程就是关于创建操作源代码(比如修改、生成或包装原来的代码)的函数和类。主要技术是使用装饰器、元类、描述符类。

       æœ¬æ–‡çš„主要目的是向大家介绍这些元编程技术,并且给出实例来演示它们是怎样定制化源代码的行为。

       è£…饰器 装饰器就是函数的函数,它接受一个函数作为参数并返回一个新的函数,在不改变原来函数代码的情况下为其增加新的功能,比如最常用的计时装饰器:

from functools import wrapsdef timeit(logger=None):"""耗时统计装饰器,单位是秒,保留 4 位小数"""def decorator(func):@wraps(func)def wrapper(*args, **kwargs):start = time.time()result = func(*args, **kwargs)end = time.time()if logger:logger.info(f"{ func.__name__} cost { end - start :.4f} seconds")else:print(f"{ func.__name__} cost { end - start :.4f} seconds")return resultreturn wrapperreturn decorator

       (注:比如上面使用 @wraps(func) 注解是很重要的, 它能保留原始函数的元数据) 只需要在原来的函数上面加上 @timeit() 即可为其增加新的功能:

@timeit()def test_timeit():time.sleep(1)test_timeit()#test_timeit cost 1. seconds

       ä¸Šé¢çš„代码跟下面这样写的效果是一样的:

test_timeit = timeit(test_timeit)test_timeit()

       è£…饰器的执行顺序 当有多个装饰器的时候,他们的调用顺序是怎么样的?

       å‡å¦‚有这样的代码,请问是先打印 Decorator1 还是 Decorator2 ?

from functools import wrapsdef decorator1(func):@wraps(func)def wrapper(*args, **kwargs):print('Decorator 1')return func(*args, **kwargs)return wrapperdef decorator2(func):@wraps(func)def wrapper(*args, **kwargs):print('Decorator 2')return func(*args, **kwargs)return wrapper@decorator1@decorator2def add(x, y):return x + yadd(1,2)# Decorator 1# Decorator 2

       å›žç­”这个问题之前,我先给你打个形象的比喻,装饰器就像函数在穿衣服,离它最近的最先穿,离得远的最后穿,上例中 decorator1 是外套,decorator2 是内衣。

       add = decorator1(decorator2(add))

       åœ¨è°ƒç”¨å‡½æ•°çš„时候,就像脱衣服,先解除最外面的 decorator1,也就是先打印 Decorator1,执行到 return func(

       args, kwargs) 的时候会去解除 decorator2,然后打印 Decorator2,再次执行到 return func(

       args, kwargs) 时会真正执行 add() 函数。

       éœ€è¦æ³¨æ„çš„是打印的位置,如果打印字符串的代码位于调用函数之后,像下面这样,那输出的结果正好相反:

def decorator1(func):@wraps(func)def wrapper(*args, **kwargs):result = func(*args, **kwargs)print('Decorator 1')return resultreturn wrapperdef decorator2(func):@wraps(func)def wrapper(*args, **kwargs):result = func(*args, **kwargs)print('Decorator 2')return resultreturn wrapper

       è£…饰器不仅可以定义为函数,也可以定义为类,只要你确保它实现了__call__() 和 __get__() 方法。

       å…ƒç±» Python 中所有类(object)的元类,就是 type 类,也就是说 Python 类的创建行为由默认的 type 类控制,打个比喻,type 类是所有类的祖先。我们可以通过编程的方式来实现自定义的一些对象创建行为。

       å®šä¸€ä¸ªç±»ç»§æ‰¿ type ç±» A,然后让其他类的元类指向 A,就可以控制 A 的创建行为。典型的就是使用元类实现一个单例:

class Singleton(type):def __init__(self, *args, **kwargs):self._instance = Nonesuper().__init__(*args, **kwargs)def __call__(self, *args, **kwargs):if self._instance is None:self._instance = super().__call__(*args, **kwargs)return self._instanceelse:return self._instanceclass Spam(metaclass=Singleton):def __init__(self):print("Spam!!!")

       å…ƒç±» Singleton 的__init__和__new__ 方法会在定义 Spam 的期间被执行,而 __call__方法会在实例化 Spam 的时候执行。

       descriptor 类(描述符类)

       descriptor 就是任何一个定义了 __get__(),__set__()或 __delete__()的对象,描述器让对象能够自定义属性查找、存储和删除的操作。这里举官方文档[1]一个自定义验证器的例子。

       å®šä¹‰éªŒè¯å™¨ç±»ï¼Œå®ƒæ˜¯ä¸€ä¸ªæè¿°ç¬¦ç±»ï¼ŒåŒæ—¶è¿˜æ˜¯ä¸€ä¸ªæŠ½è±¡ç±»ï¼š

from abc import ABC, abstractmethodclass Validator(ABC):def __set_name__(self, owner, name):self.private_name = '_' + namedef __get__(self, obj, objtype=None):return getattr(obj, self.private_name)def __set__(self, obj, value):self.validate(value)setattr(obj, self.private_name, value)@abstractmethoddef validate(self, value):pass

       è‡ªå®šä¹‰éªŒè¯å™¨éœ€è¦ä»Ž Validator 继承,并且必须提供 validate() 方法以根据需要测试各种约束。

       è¿™æ˜¯ä¸‰ä¸ªå®žç”¨çš„数据验证工具:

       OneOf 验证值是一组受约束的选项之一。

class OneOf(Validator):def __init__(self, *options):self.options = set(options)def validate(self, value):if value not in self.options:raise ValueError(f'Expected { value!r} to be one of { self.options!r}')

       Number 验证值是否为 int 或 float。根据可选参数,它还可以验证值在给定的最小值或最大值之间。

class Number(Validator):def __init__(self, minvalue=None, maxvalue=None):self.minvalue = minvalueself.maxvalue = maxvaluedef validate(self, value):if not isinstance(value, (int, float)):raise TypeError(f'Expected { value!r} to be an int or float')if self.minvalue is not None and value < self.minvalue:raise ValueError(f'Expected { value!r} to be at least { self.minvalue!r}')if self.maxvalue is not None and value > self.maxvalue:raise ValueError(f'Expected { value!r} to be no more than { self.maxvalue!r}')

       String 验证值是否为 str。根据可选参数,它可以验证给定的最小或最大长度。它还可以验证用户定义的 predicate。

class String(Validator):def __init__(self, minsize=None, maxsize=None, predicate=None):self.minsize = minsizeself.maxsize = maxsizeself.predicate = predicatedef validate(self, value):if not isinstance(value, str):raise TypeError(f'Expected { value!r} to be an str')if self.minsize is not None and len(value) < self.minsize:raise ValueError(f'Expected { value!r} to be no smaller than { self.minsize!r}')if self.maxsize is not None and len(value) > self.maxsize:raise ValueError(f'Expected { value!r} to be no bigger than { self.maxsize!r}')if self.predicate is not None and not self.predicate(value):raise ValueError(f'Expected { self.predicate} to be true for { value!r}')

       å®žé™…应用时这样写:

@timeit()def test_timeit():time.sleep(1)test_timeit()#test_timeit cost 1. seconds0

       æè¿°å™¨é˜»æ­¢æ— æ•ˆå®žä¾‹çš„创建:

@timeit()def test_timeit():time.sleep(1)test_timeit()#test_timeit cost 1. seconds1

       æœ€åŽçš„话 关于 Python 的元编程,总结如下:

       å¦‚果希望某些函数拥有相同的功能,希望不改变原有的调用方式、不写重复代码、易维护,可以使用装饰器来实现。

       å¦‚果希望某一些类拥有某些相同的特性,或者在类定义实现对其的控制,我们可以自定义一个元类,然后让它类的元类指向该类。

       å¦‚果希望实例的属性拥有某些共同的特点,就可以自定义一个描述符类。

       ä»¥ä¸Šå°±æ˜¯æœ¬æ¬¡åˆ†äº«çš„所有内容,如果你觉得文章还不错,欢迎关注公众号:Python编程学习圈,每日干货分享,内容覆盖Python电子书、教程、数据库编程、Django,爬虫,云计算等等。或是前往编程学习网,了解更多编程技术知识。

原文:/post/