一 类对象的内置属性
在python中,万物皆为对象。对象是类创建的,且类本身存在于内存中,类本身也是一个对象,一般称之为类对象。类本身存在着一些内置的属性
属性 | 类型 | 描述 | 示例 |
---|---|---|---|
__dict__ |
类 | 返回类的类方法、实例方法、静态方法和类属性组成字典 |
"""类的内置属性""" |
__doc__ |
类 | 类的说明文档 |
# # 返回类的说明文档 |
__name__ |
类 | 类名 |
# # 类名 |
__module__ |
类 | 类定义所在的模块,__main__ 表示当前主模块 |
# # 类定义所在的模块,`__main__`表示当前主模块(主程序文件) |
__bases__ |
类 | 类的所有父类构成的元组(注意:仅仅是父类,不是祖先类) |
# # 类的所有父类构成元素(注意:仅仅是父类,不是祖先类) |
__mro__ |
类 | 类的所有父辈构成的元组(注意:不仅是父类,还包括祖先类) |
# # mro获取类的继承顺序 |
__slots__ |
类 | 限制类实例对象的属性,不允许外界新增__slots__ 成员以外的实例属性 |
class Person(object): |
__dict__ |
实例对象 | 返回对象的实例属性组成的字典 |
xm = Person("小明", 16) |
__class__ |
实例对象 | 返回创建当前实例对象的类 |
# 返回创建当前实例对象的类 |
__module__ |
实例对象 | 对象所在的模块 |
# 对象所在的模块 |
__doc__ |
实例对象 | 对象所属类的说明文档 |
# 对象所属类的说明文档 |
二 反射机制
方法 | 描述 | 对象 | 示例 |
---|---|---|---|
getattr(object,name[,default]) | 获取object对象的name属性的值,如果不存在,则返回默认值default,如果没有设置default,则抛出异常 | 类 |
class Person(object): """getattr 获取类属性/类方法""" |
实例对象 |
class Student(object): """getattr 获取对象中的属性/方法""" |
||
模块文件对象 |
import random |
||
setattr(object,name,value) | 设置object对象的name属性的值,如name属性存在则覆盖,name属性不存在则新增name属性 | 类 |
"""设置类属性""" |
实例对象 |
"""setattr 为对象设置属性""" |
||
模块文件对象 |
# 设置属性 |
||
hasattr(object,name) | 判断object对象的name属性是否存在,返回布尔值 | 类 |
# 判断属性/方法是否存在 |
实例对象 |
"""hasattr 判断对象中是否存在 属性/方法""" |
||
模块文件对象 |
# 设置属性 |
||
delattr(object,name) | 删除object对象的name属性 | 类 |
# 刪除类属性 |
实例对象 |
"""delattr 删除对象属性""" |
||
模块文件对象 |
print(hasattr(random,"name")) #True |
"""反射指定路径的模块""" #基于字符串路径反射模块的方式,导入loggings.handle的RotatingFileHandler对象,并打印当前对象的所有属性和方法。 """方式1""" module = __import__('logging.handlers', fromlist=True) #也可通过from logging.handlers import RotatingFileHandler直接导入。表达方式不同
print(module.RotatingFileHandler.__dict__)
"""方式2"""
import importlib module = importlib.import_module('logging.handlers') print(module.RotatingFileHandler.__dict__)
三 异常处理
自定义异常:需要自定义异常类即可
目的:输出定义的报错信息,不只是输出内置的报错类型
"""自定义异常类,只要继承Exception异常基类,改动类型"""# import time class RegsiterFailException(Exception): pass class NetWorkException(Exception): """自定义异常类""" def __init__(self, message): self.message = message self.time = time.time()
try: # raise NetWorkException("抛出一个自定义异常") #__main__.NetWorkException: 抛出一个自定义异常. 不做处理的输出 raise RegsiterFailException("用户注册失败!") except NetWorkException as e: print(e.message) print(e.time) except RegsiterFailException as e: print(e)
#处理后的输出:抛出一个自定义异常 1650977515.629212
四 元类(很少使用。底层代码存在着元类的使用)
1 元类:类的类。
class A(object): pass a = A() """查看一个对象的类型,也就是查看当前对象是谁实例化出来""" print(type(a)) # <class '__main__.A'> """所以既然类也是一个对象,那么当然也可以通过type函数查看类是谁创建出来的""" print(type(A)) # <class 'type'># 可以看到A这个类是由 type类创建出来的 #type是Python的一个内建元类,在python当中任何class定义的类其实都是type类实例化的结果
2 元类应用一:元类动态创建类
在Python当中,使用class关键字创建一个类的本质其实在python解释器内部会自动转化为使用type元类实例化一个类对象。
"""通过class声明类,其实是告诉Python解释器使用type元类创建类而已""" country = 'China' def constructor(self, name, age): self.name = name self.age = age def introduction(self): print(f"我叫{self.name},今年{self.age}岁!") Person = type("Person", (object,), { 'country': country, '__init__': constructor, 'introduction': introduction }) xm = Person("小明", 17) print(xm.country) #China xm.introduction() #我叫小明,今年17岁! # 基于现有类,扩充类成员 def speak(self): return "hello! 我是新人类!" NewPerson = type("NewPerson", Person.__bases__, { "speak": speak, **Person.__dict__ #打散 }) p1 = NewPerson("小明", 17) print(p1.speak()) #hello! 我是新人类!
例如:我们需要不断的生产不同类型的汽车,那么不使用元类的话,代码如下
# 因为有不同类型的汽车要求,所以我们需要提前声明各种类型的汽车类 class SUV(object): """越野车""" name = "SUV" def run(cls): return f"{cls.name}汽车在飞奔..." class Sports(object): #如果后面需要生产其他类型的汽车,则需要不断的提前声明 """跑车""" name = "Sports" def run(cls): return f"{cls.name}汽车在飞奔..." def car_factory(name): #每增加一个种类的汽车,要对car_factory函数代码进行修改 if name == 'SUV': return SUV # 返回的是类,不是类的实例 else: return Sports Car = car_factory('SUV') print(Car) # <class '__main__.SUV'> print(Car().run()) # SUV汽车在飞奔...
使用元类动态创建类方法,代码如下
@classmethod # 类方法
def stop(cls):
return f"{cls.name}停车..."
def run(self): # 实例方法 return f"{self.name}汽车在飞奔..." class Car(object): def add_oid(self): return "加油..." # car_factory函数中只传入一个参数name仅为举例子,实际上开发中,可以传递更多用于定制动态创建类对象的参数。 def car_factory(name): return type(name, (Car,), { "name": name, "run": run, "stop": stop }) SUV = car_factory('SUV') print(SUV) # <class '__main__.SUV'> suv1 = SUV() # 你可以通过这个类创建实例对象 #不需要定义SUV类
print(suv1) #<__main__.SUV object at 0x109495fa0>
print(SUV.stop()) #SUV停车... print(suv1.run()) #SUV汽车在飞奔... print(suv1.add_oid()) #加油...
3 元类应用二:自定义元类
"""基于自定义元类实现单例模式""" class Singleton(type): """基于自定义元类实现单例模式""" #实现单例模式:1自定义元类 2__call__ 3__new__ def __init__(self, *args, **kwargs): print("元类的.__init__执行了") super().__init__(*args, **kwargs) self.__instance = None # 保存实例化对象 def __call__(self, *args, **kwargs): print("元类的.__call__执行了") if self.__instance is None: # 因为,元类是通过__call__创建类的,而普通类是通过__new__创建对象的 self.__instance = super().__call__(*args, **kwargs) return self.__instance # 方式1:通过元类Singleton动态创建类 # Log = Singleton("Log", (object,),{}) # 方式2:通过class关键字创建类,指定Log的元类是Singleton,也就是接下来,Log类会被Singleton元类创建 class Log(object, metaclass=Singleton): def __init__(self): print("类的__init__执行了") super().__init__() def __new__(cls, *args, **kwargs): print("类的__new__执行了") return object.__new__(cls) # 使用类实例化创建对象,所以我们在实例化对象时,给类的后面加上()小括号就会调用元类的__call__方法 logger1 = Log() logger2 = Log() print(logger1 is logger2) # True """ 元类的.__init__执行了 20行创建了一个类对象 元类的.__call__执行了 30行把类对象当成函数调用 类的__new__执行了 30行把类进行了实例化,会先创建对象,__new__会出发 类的__init__执行了 __new__执行完了以后,Python """
4 元类应用三:基于元类的特点,保证代码规范问题
"""基于自定义元类约束类在创建时的代码规范""" class MetaClass(type): """基于自定义元类约束类在创建时的代码规范""" def __init__(self, cls_name, cls_bases, cls_dict): """ 元类实例化创建类的构造函数 :param cls_name: 类名 :param cls_bases: 类的父类元组 :param cls_dict: 类的属性方法成员(不包括实例属性) """ if cls_name != cls_name.title(): raise TypeError(f"类名必须首字母大写!") # len(cls_dict['__doc__'].strip()) == 0 把文档说明的左右两边空格字符去除以后,判断文档字符串长度是否 等于 0 if '__doc__' not in cls_dict or len(cls_dict['__doc__'].strip()) == 0: raise TypeError(f"类:{cls_name} 必须有文档说明,不能为空!") for key, value in cls_dict.items(): if key.startswith('__'): # 以2个下划线开头的是私有属性/私有方法 continue if not callable(value): # 属性是不可调用的 continue if not value.__doc__ or len(value.__doc__.strip()) == 0: raise TypeError(f"公有方法:{key} 必须有文档说明,不能为空!") super().__init__(cls_name, cls_bases, cls_dict) # 重用父类的功能. class Person(metaclass=MetaClass): """ 人类 """ def speak(self, message): """ 说话 :param message: 内容 :return: 返回值 """ print(f"说话:{message}")
注意:
1 object是所有类的基类,type是所有类的元类,但type本质上还是类,那么object就是type的基类。如何理解两者的关系?
object 和 type 在 CPython 解释器底层中都是用c代码同时生成的,并非在Python创建的,所以并没有先后关系,并且它们的依赖关系也是通过底层C代码由官方人员人为规定的。
五 抽象类(很少使用。底层代码存在着抽象类的使用)
定义:
操作 | 说明 | 示例 |
---|---|---|
@abc.abstractmethod | 标记一个方法为抽象方法,只定义方法名和参数,而要求子类继承时必须实现具体代码,是个装饰器。 |
import abc |
abc.ABC | 定义当前类为抽象类,本质上就是一个经过元类实例化的父类 | |
abc.ABCMate | 定义当前类为抽象元类,abc.ABC的父类的元类。Python3.4以后建议使用上面的abc.ABC。 |
六 设计模式
1 定义:是前人针对特定场景特定问题所总结出来的解决方案。不是语法规定,而是一套用来提高代码复用性、维护性、可读性、稳健性以及安全性的解决方案。
1995 年,GoF(Gang of Four,四人组/四人帮)合作出版了《设计模式:可复用面向对象软件的基础》一书,共收录了 23 种设计模式,人称「GoF设计模式」)。这 23 种设计模式的本质是对面向对象设计原则五大原则的实际运用,是对面向对象的封装、继承和多态的充分理解。
范围/目的 | 创建型模式 | 结构型模式 | 行为型模式 |
---|---|---|---|
类模式 | 工厂(Factory Pattern) | 适配器(Adapter Pattern) | 模板方法(Template Method Pattern) 解释器(Interpreter Pattern) |
对象模式 | 单例(Singleton Pattern) 原型(Prototype Pattern) 抽象工厂(Abstract Factory Pattern) 建造者(Builder Pattern) | 代理(Proxy Pattern) 适配器(Adapter Pattern) 桥接(Bridge Pattern) 装饰器(Decorator Pattern) 外观(Facade Pattern) 享元(Flyweight Pattern) 组合(Composite Pattern) | 策略(Strategy Pattern) 命令(Command Pattern) 职责链(Chain of Responsibility Pattern) 状态(State Pattern) 观察者(Observer Pattern) 中介者(Mediator Pattern) 迭代器(Iterator Pattern) 访问者(Visitor Pattern) 备忘录(Memento Pattern) |
除了23种GoF设计模式,还有其他的常用新型设计模式,如:MVC模式(Model-View-Controller Pattern)、链式模式(Chain Pattern)、发布订阅模式(Publish-Subscribe Pattern)、反应堆模式(Reactor Pattern)
简单工厂模式 | 工厂方法模式 | 抽象工厂模式 |
import abc #创建一个工厂对象,这个对象存在的作用就是根据用户的选择不同实例化出不同的支付对象给调用方 factory = PaymentFactory() |
import abc |
import abc '''可以一次性生产多个产品或可以完成多个动作步骤'''
|
2.2 外观模式
也叫门面模式。
示例:一个运维监控系统,在服务器宕机时发出警报通知管理员
import abc class AbstractAlarm(abc.ABC): @abc.abstractmethod def get(self, message): """接受并整理警报信息""" pass @abc.abstractmethod def send(self, user): """发送警报内容给管理员""" pass class MailAlarm(AbstractAlarm): """邮件发送警报类""" def get(self, message): print(f"接受并整理警报信息{message}成邮件格式") def send(self, user): print(f"通过邮件发送警报内容给管理员{user}") class SMSAlarm(AbstractAlarm): """邮件发送警报类""" def get(self, message): print(f"接受并整理警报信息{message}成短信格式") def send(self, user): print(f"通过短信发送警报内容给管理员{user}") class VoiceAlarm(AbstractAlarm): """语音发送警报类""" def get(self, message): print(f"接受并整理警报信息{message}成语音内容") def send(self, user): print(f"通过语言电话发送警报内容给管理员{user}") class Log(object): def write(self, message): """记录警报信息到日志中""" class AlarmFacade(object): # 定义一个外观类,其中封装对子系统的复杂操作 def __init__(self): self.logger = Log() self.voice_alarm = VoiceAlarm() self.sms_alarm = SMSAlarm() self.mail_alarm = MailAlarm() def alarm(self, user, message, level): if level == 1: self.mail_alarm.get(message) self.mail_alarm.send(user) elif level == 2: self.sms_alarm.get(message) self.sms_alarm.send(user) elif level == 3: self.voice_alarm.get(message) self.voice_alarm.send(user) self.logger.write(message) if __name__ == '__main__':
# 门面模式的最主要特点就是,提供一个外部统一调用接口,在门面类的内部实现复杂的实现功能
facade = AlarmFacade()
facade.alarm("小明", "IP: 192.168.3.101,服务器宕机", 3) #接受并整理警报信息IP: 192.168.3.101,服务器宕机成语音内容 #通过语言电话发送警报内容给管理员小明
2.3 链式模式
class Person(object): def __init__(self): self.range = 0 #模式移动距离为0 def walk(self, step): print(f"走{step}步") self.range += step return self def run(self, step): print(f"跑{step}步") self.range += step return self def get_range(self): return self.range p1 = Person() '''p1.run(5)返回值'return self。即p1 = p1.run(5),p1 = p1.run(5).walk(5)''' ret = p1.run(5).walk(5).walk(5).run(5).get_range() #跑5步 走5步 走5步 跑5步 20 print(ret)
2.4 策略模式
属于一种对象的行为型模式,指对象有某个行为,但是在不同业务或不同场景中,该行为有不同的实现算法。
import abc class Item(object): """商品类""" def __init__(self, product, unit_price, quantity): self.product = product # 商品名称/商品唯一标记 self.quantity = quantity # 数量 self.unit_price = unit_price # 单价 def total(self): # 单品总价 = 单价 * 数量 return round(self.unit_price * self.quantity, 2) class Promotion(abc.ABC): @abc.abstractmethod def discount(self, order): """计算优惠,统计订单中所有商品的优惠比例,返回折扣价格""" pass class FidelityPromo(Promotion): # 折扣策略 """拥有1000个以上积分的老客户可享受5%的折扣""" def discount(self, order): return order.total() * .05 if order.user["credit"] >= 1000 else 0 class BulkItemPromo(Promotion): # 折扣策略 """每件商品20件或以上可享受10%的折扣""" def discount(self, order): discount = 0 for item in order.cart: # 计算每件商品的数量是否达到优惠门槛:20件 if item.quantity >= 20: discount += item.total() * .1 return discount class LargeOrderPromo(Promotion): # 折扣策略 """订购10件或10件以上不同商品可享受7%的折扣""" def discount(self, order): distinct_items = {item.product for item in order.cart} if len(distinct_items) >= 10: return order.total() * .07 return 0 class Order(object): """订单""" def __init__(self, user, cart, promotion=None): self.user = user # 购买商品的用户 self.cart = list(cart) # 本次购买的商品列表,也叫购物车 self.promotion = promotion # 优惠策略对象 self.__total = 0 # 本次购买商品的总价格 def total(self): """商品列表[购物车]的总金额""" # 总金额 = 单品总价 * 商品种类数量 self.__total = sum(item.total() for item in self.cart) return self.__total def due(self): """经过优惠以后,用户实际应支付金额""" if self.promotion is None: discount = 0 else: discount = self.promotion.discount(self) return self.total() - discount def __str__(self): return f"<Order total: {self.total():.2f} due: {self.due():.2f}>" # 用户数据格式 xm = {"name":"小明", "credit": 3500} item1 = Item("鞋子", 200, 2) item2 = Item("裙子", 600, 1) item3 = Item("袜子", 30, 5) cart = [item1, item2, item3] order1 = Order(xm, cart, FidelityPromo()) print(order1) #<Order total: 1150.00 due: 1092.50> order2 = Order(xm, cart, BulkItemPromo()) print(order2) #<Order total: 1150.00 due: 1150.00> order3 = Order(xm, cart, LargeOrderPromo()) print(order3) #<Order total: 1150.00 due: 1150.00> # 查找最优惠策略 ret = min([(order.due(), order.promotion) for order in [order1, order2, order3]]) print(ret) #(1092.5, <__main__.FidelityPromo object at 0x105cb8670>)
2.5 装饰器模式
装饰器模式就是在现有的函数、类外层,套上一段逻辑代码,对其功能进行扩展和延伸,而且不会影响现有函数、类的本身结构。
import time """装饰器模式 = 高阶函数+闭包函数+嵌套函数""" def decorator(fun): def wrapper(*args, **kwargs): start = time.time() result = fun(*args, **kwargs) end = time.time() print(f"fun run time is {end - start}") return result return wrapper # 返回内函数,但是没有调用 def fn(user, message): time.sleep(2) print(f"fn is running: {user}: {message}") return 100 ret = decorator(fn) # 返回值就是之前的内函数wrapper,它是在被装饰的函数fn的基础上增加了功能的新函数 r = ret("xiaoming","一段话") print(r) '''fn is running: xiaoming: 一段话 fun run time is 2.0028302669525146 100'''
七 装饰器
基本使用
装饰器嵌套 | 函数装饰器 | 类装饰器 | |||
被装饰对象是函数 | 被装饰对象是类 | 被装饰对象是方法 | |||
def decorator1(fun): |
def decorator(func): |
'''实现单例模式''' |
def decorator1(fun): |
""""基于__call__方法,实现装饰器效果""" |
"""基于对象方法实现装饰器""" |
装饰器的2种写法:函数装饰器与类装饰器。而被装饰的3种对象:函数、类、类方法三种。都大同小异。 |
八 垃圾回收机制
垃圾回收机制(Garbage collection,简称GC)是Python解释器自带一种机制,专门用来回收不可用的变量值所占用的内存空间,主要由gc模块实现。
a = "A" # 数据"A"被变量名a关联了,所以数据"A"的引用次数+1 b = "a" # 数据"a"被变量名b关联了,所以数据"a"的引用次数+1
引用计数法的原理是每个数据对象维护一个变量ob_refcnt,叫引用计数器(整型),用来记录当前对象被引用的次数,也就是来追踪到底有多少变量引用指向了这个数据对象。#c
typedef struct_object { int ob_refcnt; struct_typeobject *ob_type } PyObject;
当发生以下4种情况的时候,数据对象的引用计数器ob_refcnt+1:
条件 | 举例 |
---|---|
对象被创建赋值 | a="A" |
对象被引用 | b=a |
对象被作为参数,传到函数中 | func(a) |
对象作为一个元素,保存在容器类型的数据中 | data=[a,2] |
当发生以下4种情况时,该对象的引用计数器ob_refcnt-1,当指向该对象的内存的引用计数器为0的时候,该内存将会被Python虚拟机销毁:
条件 | 举例 |
---|---|
当该对象的别名被显式删除时 | del a |
当该对象的引别名被赋予新的对象 | a="a" |
当该对象离开它的作用域,如func函数执行完毕,函数中的局部变量的引用计数-1,但是全局变量与闭包不会。 | |
当该对象从容器中删除时,或容器本身被销毁时。 | del data |
import sys class Person(object): pass p = Person() print(sys.getrefcount(Person())) # 1,Person()本身代表1个对象,但是该对象并没有进行赋值,所以此处的1是因为把对象作为参数传入sys.getrefcount而增加的 print(sys.getrefcount(p)) # 2,p经过赋值引用了Person的实例对象,然后把p作为参数传递给sys.getrefcount,所以此处引用了2次。 # 因为小数据池和Python内存驻留机制的原因,所以针对数字、字符串、空元祖等小数据在系统属于常驻内存,为公用对象, # 所以他们的引用次数,无法得知 print(sys.getrefcount('10202-222')) # 3 print(sys.getrefcount(1)) # 168
引用计数机制的优缺点:
优点 | 缺点 |
---|---|
简单 | 每一个数据对象都需要维护自己的引用计数器消耗资源 引用次数的增加或减少,都会引发引用计数机制的执行 |
实时,一旦没有引用(也就是ob_refcnt==0),内存就直接释放了。 处理回收内存的时间分散,而其他两种机制需要等待特定时机,时间相对集中。 | 容易出现容器数据类型循环引用的情况 |
2 标记-清除
示例:
import sys import ctypes """容器数据类型的循环引用""" list1 = [] list2 = [] list1.append(list2) list2.append(list1) # 你中有我,我中有你,这就是循环引用了,也就是无限循环嵌套了。 # print(list1) # [[[...]]] list1_addr = id(list1) list2_addr = id(list2) del list1 del list2 # id就是内存地址,可以通过id值查找到内存中保存的数据 print(sys.getrefcount(ctypes.cast(list1_addr, ctypes.py_object).value)) # 2 print(sys.getrefcount(ctypes.cast(list1_addr, ctypes.py_object).value)) # 2 # 除了本次作为getrefcount的参数的1次引用以外,还有1个引用次数。而这个引用次数就是它们双方之间的循环引用导致的。
栈区(也叫堆栈区),主要保存变量名、变量名与变量数据的映射关系
堆区:主要保存数据
标记-清除优缺点:
优点 | 缺点 |
---|---|
可以解决循环引用的问题 |
3 分代回收
基于标记-清除这种回收机制,每次gc回收内存时,都需要把所有容器对象的引用计数都遍历一遍,这是非常消耗时间的,于是引入了分代回收来提高回收效率。
分代指的是根据存活时间来把变量划分不同等级(也是不同的代
-
-
每执行 11 次新生代 GC ,触发一次青春代 GC
-
通俗来说,就是每新增701个引用计数为0的变量,就会对内存中所有的新生代数据进行gc遍历,每11次遍历新生代的数据以后,就会对青春代的数据进行gc遍历,每11次遍布青春代的数据以后,就会对老年代的数据进行gc遍历。
import gc """获取的gc模块中自动执行垃圾回收的频率。""" print(gc.get_threshold()) # (700, 10, 10) # 当然,我们也可以临时设置gc模块自动执行垃圾回收机制的频率 # gc.set_threshold(threshold0[, threshold1[, threshold2]) 设置自动执行垃圾回收的频率。(最好不要自己设置) class A(): pass # 计算3代变量的引用次数的变化统计 print(gc.get_count()) # (584, 5, 1) a = A() print(gc.get_count()) # (585, 5, 1) del a print(gc.get_count()) # (584, 5, 1)
注:
当计数器从(699,2,1)增加到(700,2,1),gc模块就会执行一次垃圾回收gc.collect(0), 即检查0代(新生代)对象中的垃圾,并重置引用计数器为(0,3,1)
当计数器从(699,9,1)增加到(700,9,1),gc模块就会执行一次垃圾回收gc.collect(1), 即检查0代(新生代)、1代(青春代)对象的垃圾,并重置计数器为(0,0,2)
当计数器从(699,9,9)增加到(700,9,9),gc模块就会执行一次垃圾回收gc.collect(2), 即检查0(新生代)、1(青春代)、2(老年代)三代对象的垃圾,并重置计数器为(0,0,0)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现