django知识点

前言

介绍django的重要知识点


1、__getattr__方法、__getattribute__方法及其应用

1.1 __getattr__方法

概述:对象中有成员时,不会触发;对象中没有成员时,会触发;

class Foo(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        return 123

    def __getattr__(self, item):
        print("---->", item)
        return 999


obj = Foo("任刚", 19)
# 不触发 __getattr__
print(obj.name)		# 任刚
print(obj.age)		# 19
print(obj.show())	# 123

# 触发 __getattr__(不存在成员)
print(obj.xxxxx)		# ----> xxxx  999
v2 = getattr(obj,"xxxxx")
print(v2)				# ----> xxxx  999

1.2 __getattribute__方法

  • 只要执行 对象.xxxx都会执行 __getattribute__方法;
  • object中的 __getattribute__ 内部处理机制:
    • 对象中有值,返回
    • 对象中无值,报错

1.3 两种方法结合使用

class HttpRequest(object):
    def __init__(self):
        pass

    def v1(self):
        print("我是HttpRequest中的v1")

    def v2(self):
        print("我是HttpRequest中的v2")


class Request(object):
    def __init__(self, req, xx):
        self._request = req
        self.xx = xx

    def __getattr__(self, attr):
        try:
            return getattr(self._request, attr)
        except AttributeError:
            return self.__getattribute__(attr)

# ------------------------------------------------------
req = HttpRequest()
req.v1()    # 输出结果为:我是HttpRequest中的v1
req.v2()    # 输出结果为:我是HttpRequest中的v2

# ------------------------------------------------------
request = Request(req, 111)
print(request.xx)    # 输出结果为‘111’,request对象中有xx成员,不执行`__getattr__(self, attr)`方法

request.v1()
# 输出结果为:我是HttpRequest中的v1;因为request对象中没有v1,执行`__getattr__(self, attr)`方法(即req对象),`getattr(self._request, attr)`中有v1,返回v1,如果也没有的成员,则会报错。
    
request.v2()    # 输出结果为:我是HttpRequest中的v2
request.v3()    # 报错,执行父类object中的`__getattribute__(attr)`方法

通过关键的第17号至21行代码,将__getattr__方法与__getattribute__方法结合使用,可以将reqeust._request.v1()简写为reqeust.v1()。

1.4 drf中request对django的request进行封装,用的就是上述方式

1.4.1 总体流程

在这里插入图片描述

1.4.2 主要源码

class HttpRequest:
    """A basic HTTP request."""

    # The encoding used in GET/POST dicts. None means use default setting.
    _encoding = None
    _upload_handlers = []

    def __init__(self):
        # WARNING: The `WSGIRequest` subclass doesn't call `super`.
        # Any variable assignment made here should also happen in
        # `WSGIRequest.__init__()`.

        self.GET = QueryDict(mutable=True)
        self.POST = QueryDict(mutable=True)
        self.COOKIES = {}
        self.META = {}
        self.FILES = MultiValueDict()

        self.path = ''
        self.path_info = ''
        self.method = None
        self.resolver_match = None
        self.content_type = None
        self.content_params = None
class Request:
    """
    Wrapper allowing to enhance a standard `HttpRequest` instance.

    Kwargs:
        - request(HttpRequest). The original request instance.
        - parsers(list/tuple). The parsers to use for parsing the
          request content.
        - authenticators(list/tuple). The authenticators used to try
          authenticating the request's user.
    """

    def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
                 
		# isinstance(object, classinfo),判断一个对象的变量类型,返回值为True或False
		# assert 断言,在表达式条件为 false 的时候触发异常
		# request 为django中的基本request【drf封装前】
		
        assert isinstance(request, HttpRequest), (
            'The `request` argument must be an instance of '
            '`django.http.HttpRequest`, not `{}.{}`.'
            .format(request.__class__.__module__, request.__class__.__name__)
        )
		# 核心代码
        self._request = request
        
        self.parsers = parsers or ()
        self.authenticators = authenticators or ()
        self.negotiator = negotiator or self._default_negotiator()
        self.parser_context = parser_context
        self._data = Empty
        # ……

    def __getattr__(self, attr):
        """
        If an attribute does not exist on this instance, then we also attempt
        to proxy it to the underlying HttpRequest object.
        """
        try:
            return getattr(self._request, attr)
        except AttributeError:
            return self.__getattribute__(attr)

2、__init__方法、super()方法

2.1 __init__方法

2.1.1 介绍

  • __init__方法是 Python 中面向对象编程中类的特殊方法,也称为构造方法,当创建一个类的实例时,__init__方法会自动调用。
  • self参数是必须的,它代表创建的对象本身,在方法内部可以通过self来引用对象的属性和方法。除了self以外的其他参数是可选的,根据实际需求定义。

2.1.2 示例代码

class HttpRequest(object):
    # 
    def __init__(self, name, age):
        self.name = name
        self.age = age


request = HttpRequest('小杨', 19)

request.city = "北京"

print(request.name)  # 输出结果为:小杨
print(request.age)  # 输出结果为:
print(request.city)  # 输出结果为:北京

2.1.3 注意事项

  • __init__方法在对象创建时自动调用,无需手动调用。
  • __init__方法可以接收任意数量的参数,但必须遵循特定的参数签名。
  • __init__方法中,必须给对象的每一个属性赋值,否则该对象将不完整,不能正常工作。
  • 可以在__init__方法中调用其他方法,但请注意不要在初始化的过程中产生太多的计算,因为这可能会影响程序的性能。
  • 一个类可以没有__init__方法,在这种情况下,程序将以默认方式创建该类的对象。

2.2 super()方法

2.2.1 介绍

  • 根据类的【继承关系】,逐步往上找,并不是单纯找父类中的方法;

2.2.2 示例代码一

class Base:
    def f1(self):
        print("Base")

class Foo(Base):
	pass

class Bar(Foo):
    def f1(self):
        print("Bar")
        super().f1()

obj = Bar()
obj.f1()  # 执行结果为:[Bar,Base]

2.2.3 示例代码二

class Base:
    def f1(self):
        print("Base")

class Foo:
    def f1(self):
        print("Foo")        
        
class Bar(Foo,Base):
    def f1(self):
        print("Bar")
        super().f1()
        
obj = Bar()
obj.f1()  # 执行结果为[Bar,Foo]

2.2.4 示例代码三

class Base:
    def f1(self):
        print("Base")

class Foo:
    def f1(self):
        print("Foo")
        super().f1()
        
class Bar(Foo,Base):
    def f1(self):
        print("Bar")
        super().f1()
        
obj = Bar()
obj.f1()  #执行结果为: [Bar,Foo,Base]

2.2.5 示例代码四

class Base:
    def f1(self):
        print("Base")

class Foo:
    def f1(self):
        print("Foo")
        super().f1()
        
class Bar(Foo,Base):
    def f1(self):
        print("Bar")
        super().f1()
        
obj = Foo()
obj.f1()    # 代码报错,因为Foo父类为object,没有f1方法

2.3 __init__super用法

2.3.1 示例代码

class Parent:
    def __init__(self, value1, value2):
        self.value1 = value1
        self.value2 = value2


class Child(Parent):
    def __init__(self, value1, value2, value3):
        super().__init__(value1, value2)
        self.value3 = value3


obj = Child('v1', 'v2', 'v3')
print(obj.value1)  # 输出结果为v1
print(obj.value2)  # 输出结果为v2
print(obj.value3)  # 输出结果为v3

2.3.2 总结

  • 在上述示例中,Child继承了Parent的所有属性,并且在其中添加了额外的value3 属性。调用 super().init(value1, value2) 可以访问父类的__init__方法,并将其初始化为value1 和value2。
  • 25
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值