当前位置: 首页 > news >正文

Python教程(三):类对象、闭包、装饰器、类型注解、MRO

Python总结(三)

本系列其他教程:

Python教程(一):基本语法、流程控制、数据容器
Python教程(二):函数、异常、模块&包、文件读取、常用模块

文章目录

  • Python总结(三)
    • 一、类&对象
      • 1.1 成员方法
      • 1.2 构造方法
      • 1.3 类属性&类方法&静态方法
      • 1.4 魔术方法
      • 1.5 私有成员
      • 1.6 继承
        • 1.6.1 单继承&多继承
        • 1.6.2 复写
        • 1.6.3 调用父类同名属性
        • 1.6.4 多态和抽象
      • 1.7 自定义属性
    • 二、类型注解
      • 2.1 基本用法
      • 2.2 容器类型注解
      • 2.3 type定义类型注解
      • 2.4 Union联合类型
    • 三、闭包
    • 四、装饰器
    • 五、构造方法重写补充
      • 5.1 子类单继承没有定义构造方法
      • 5.2 子类单继承重写构造方法
      • 5.3 MRO
        • 5.3.1 子类多继承没有定义构造方法
        • 5.3.2 子类多继承重写构造方法

一、类&对象

使用 class 关键字来定义类,通过 对象=类名称() 来创建对象。

  • 对象也像变量一样,不用声明类型。
  • 创建对象的写法就像调用 “类函数” 一样。

1.1 成员方法

  • 类中定义的成员方法必须要有一个形参 self,且必须放在所有参数的第一位。
    • self 表示类对象自身的意思,在成员方法内想要访问成员变量必须使用 self 来访问。
    • 使用类对象调用成员方法的时候,可以当 self 参数不存在。
      • 当使用类对象调用成员方法时,self 会自动被 Python 传入。
# 定义类
class Student:# 成员变量name = None# 成员方法,必须要有self参数def myMethod(self, address):# 通过self来访问成员变量print(f"大家好,我叫{self.name},我的地址是{address}")# 创建对象
s1 = Student()
# 定义成员变量值
s1.name = 'Jay'
# 调用成员方法(当作self参数不存在)
s1.myMethod('Taiwan') # 大家好,我叫Jay,我的地址是Taiwan

1.2 构造方法

  • 构造方法在创建类对象的时候会自动调用。
    • Python中构造方法的名称固定为 __init__() ,前后各两个下划线。
    • 如果自己不定义构造方法,默认会有一个空参的构造方法;如果自己定义了构造方法,则默认的空参构造方法会失效。
  • 构造方法也属于成员方法,也必须有 self 参数。
  • 经常用构造方法在创建对象的时候给成员变量赋值。
    • 以下代码在类中并没有定义三个属性而构造方法直接使用了,下面会解释。
class Student:# 构造方法def __init__(self, name, age, address):self.name = nameself.age = ageself.address = addressdef myInformation(self):print(self.name, self.age, self.address)# 创建对象自动调用构造方法,self当作不存在
stu1 = Student('Jay', 30, 'Taiwan')
stu1.myInformation() # Jay 30 Taiwan

1.3 类属性&类方法&静态方法

  • 类属性:

    • 对象是从类创造的,它们的属性和方法是各个对象独有的,互相不能共享。
    • 而类也有属性和方法,且它们可以和类创建的所有对象共享,并且类本身不用创建对象也能访问。
    • 以下代码定义了类属性,而不是对象属性:
      • 访问类属性要使用类名,而不是self,self表示对象。
    class Student:# 以下都是类属性name = Noneage = Nonecount = 0def __init__(self, name, age):# 访问类属性要使用类名,而不是self,self表示对象Student.count += 1print(Student.count) # 0
    stu1 = Student('Tom', 12)
    print(stu1.count) # 1
    stu2 = Student('Jack', 18)
    print(stu2.count) # 2
    print(Student.count) # 2
    # 可以发现所有对象和类本身都共享类属性count
    
  • 对象属性:

    • 使用 self 定义在 __init__ 构造方法中,每个对象独有。
    • 以下代码定义了对象属性,而不是类属性:
      • 访问对象属性要使用self,而不是类名。
    class Student:def __init__(self, name, age, address):self.name = nameself.age = ageself.address = address
    
    • 注意:定义了对象属性后一般不会再定义同名的类属性,这也是为什么第1.2节代码中没有定义类属性的原因。
  • 类方法:

    • 类方法也不需要创建对象,通过类名就可以访问,通过对象也可以访问。
    • 使用 @classmethod 装饰器定义,第一个参数是 cls,而不是 selfcls 表示类本身而不是对象本身,类方法中访问类中的其他类方法类属性必须使用 cls
    class MyClass:# 类属性class_attribute = 2@classmethoddef class_method(cls):# 类方法通过cls访问类属性return cls.class_attribute# 调用类方法
    print(MyClass.class_method()) # 2# 也可以通过实例调用类方法,但效果相同
    obj = MyClass()
    print(obj.class_method()) # 2
    
  • 对象方法:

    • 定义在类中,第一个参数是self,可以访问对象属性。
  • 静态方法:

    • 静态方法通过 @staticmethod 装饰器在类中定义。
    • 静态方法不使用 clsself 作为第一个参数。
    • 静态方法类和对象都可以访问。
    • 静态方法用于实现一些与类相关的功能,但在实现过程中不需要访问或修改类或对象的成员(不使用cls、self参数也没法访问),一般只是用来做与本类相关的一些逻辑运算。
    class MyClass:@staticmethoddef static_method(arg1, arg2):return arg1 + arg2# 调用静态方法
    result = MyClass.static_method(5, 10)
    print(result)  # 输出: 15# 也可以通过实例调用静态方法,但效果相同
    obj = MyClass()
    result = obj.static_method(5, 10)
    print(result)  # 输出: 15
    

综合案例:

class Car:# 类属性wheels = 4def __init__(self, brand, model, year):# 对象属性self.brand = brandself.model = modelself.year = year# 类方法@classmethoddef is_motor_vehicle(cls):return cls.wheels == 4# 对象方法def car_details(self):return f"{self.brand} {self.model} ({self.year})"# 静态方法# 不访问类或对象中的任何成员@staticmethoddef calculate_mileage(distance, fuel_used):return distance / fuel_used# 创建实例
car1 = Car("Toyota", "Camry", 2020)
car2 = Car("Honda", "Accord", 2019)# 调用对象方法
print(car1.car_details())  # 输出: Toyota Camry (2020)
print(car2.car_details())  # 输出: Honda Accord (2019)# 调用类方法
print(Car.is_motor_vehicle())  # 输出: True# 调用静态方法
print(Car.calculate_mileage(500, 25))  # 输出: 20.0# 访问类属性
print(Car.wheels)  # 输出: 4# 访问对象属性
print(car1.brand)  # 输出: Toyota
print(car2.model)  # 输出: Accord

1.4 魔术方法

Python内置的对象方法称为魔术方法(第一个参数是self):

__str__

  • 用于控制输出对象的时候输出的内容,而不是输出没什么用的内存地址。
  • 该方法必须返回一个字符串,这个返回的字符串就是打印对象时输出的内容。
# 没有定义__str__魔术方法
class Student1:def __init__(self, name, age):self.name = nameself.age = agestu1 = Student1('Jack', 12)
print(stu1) # <__main__.Student object at 0x0000016A8BDE5810># 使用__str__魔术方法
class Student2:def __init__(self, name, age):self.name = nameself.age = agedef __str__(self):return f'{self.name} {self.age}'stu2 = Student2('Jack', 12)
# 输出魔术方法返回的内容
print(stu2) # Jack 12

__lt__

  • 直接进行对象的比较是会报错的,该方法用于支持对象之间的比较。
  • 该方法传入的第二个参数 other 指的是另一个参与比较的对象,而 self 参数指的是对象本身。
  • 该方法的返回值是 True 或 False。
class Student1:def __init__(self, name, age):self.name = nameself.age = agedef __lt__(self, other):return self.age < other.agestu1 = Student1('Jack', 12)
stu2 = Student1('Jack', 15)
# stu2对应方法中的other参数
print(stu1 < stu2) # True

其他魔术方法:

  • __le__:用于支持对象之间进行比较的 <=>= 两种运算符。
    • 用法和 __lt__ 一模一样。
  • __eq__:用于支持对象之间进行比较的 == 运算符。
    • 用法和 __lt__ 一模一样。

1.5 私有成员

  • 私有成员不能被类对象访问和使用。
  • 私有成员能被类中的其他成员访问和使用。
  • 私有成员的定义只需要在方法或变量名之前加 __ 两个下划线即可。
class Student1:#成员变量也可以有默认值__address = '北京'def __init__(self, name, age):self.name = nameself.age = agedef myAddress(self):# 访问私有成员return self.__addressstu1 = Student1('Jack', 12)
print(stu1.__address) # 对象访问私有成员会报错
print(stu1.myAddress()) # 北京

1.6 继承

1.6.1 单继承&多继承
  • 继承表示子类从父类继承成员变量和方法(不含私有),然后子类拥有了继承下来的成员,可以直接使用(就当成子类中也定义了相同的成员)。
  • 写法:class 类名(父类名)
    • 可以多继承,多个父类名在括号中使用逗号隔开。
    • 如果继承下来的多个父类有同名的成员变量或方法,则以括号中从左到右的顺序来排优先级。

单继承:

# 定义父类
class Phone:IMEI = NonesimCard = Nonedef callBy4G(self):print('父类Phone的成员方法被调用')# 子类继承父类
class XIAOMI(Phone):color = 'green'x1 = XIAOMI()
print(x1.color) # green
# 子类对象可以直接调用继承下来的父类方法
x1.callBy4G() # 父类Phone的成员方法被调用

多继承:

class Phone:IMEI = NonesimCard = Nonedef callBy4G(self):print('父类Phone的成员方法被调用')class NFCReader:producer = 'NVINDA'def readNFC(self):print('读取了NFC')class HUAWEI(Phone, NFCReader):# 拥有了继承下来的两个父类的所有成员pass
1.6.2 复写
  • 子类可以复写和父类同名的变量或方法,重写后子类再调用就会调用重写后的而不是父类的。
  • 重写的方式是直接定义一个和父类中同名的新方法或新变量。
class Phone:IMEI = NonesimCard = Nonename = "手机大王"def callBy4G(self):print('父类Phone的成员方法被调用')# 子类继承父类
class XIAOMI(Phone):color = 'green'def __init__(self, name):# 从父类继承下来的属性被修改self.name = name# 进行了重写def callBy4G(self):print('子类XIAOMI的成员方法被调用')x1 = XIAOMI("小米手机")
x1.callBy4G() # 调用的是重写后的方法而不是父类的
print(x1.name) # 小米手机
1.6.3 调用父类同名属性
  • 子类中调用父类属性有2种方式(仅针对属性,调用父类方法见下述):
    • 父类名.属性名
    • super().属性名
class Phone:IMEI = NonesimCard = '父类的sim卡'def callBy4G(self):print('父类Phone的成员方法被调用')class XIAOMI(Phone):color = 'green'simCard = '子类重写的sim卡'# 进行了重写def callBy4G(self):# 调用父类成员print(super().simCard)x1 = XIAOMI()
x1.callBy4G() # 父类的sim卡
1.6.4 多态和抽象
  • 抽象指的是父类来确定有哪些方法和成员,但什么都不做(pass),具体的实现由子类重写决定。
  • 多态指的是参数接收父类,但其实传递的是子类对象,也就是父类抽象,子类实际工作。
# 抽象类中定义抽象方法
class Animal:def noise(self):pass# 定义子类
class Dog(Animal):def noise(self):print("I am a dog")# 参数接受一个父类对象
def makeNoise(animal: Animal):animal.noise()# 实际传递子类对象
makeNoise(Dog()) # I am a dog

1.7 自定义属性

  • 对于一些不需要任何参数,然后返回一个值的成员函数,可以使用 @property 装饰器来将它们变成“属性”,以后这些方法就可以当作属性来使用,而不用调用函数。
  • 定义后函数名就是属性名。
class Student:baseAge = 12@propertydef age(self):return self.baseAge * 2stu1 = Student()
# 把age函数当成一个属性来使用了
print(stu1.age) # 24

二、类型注解

2.1 基本用法

  • 对代码实际执行没有任何影响,只是帮助第三方IDE工具做类型提示,如自动补全和类型检查。
  • 支持的范围:
    • 变量、对象的类型注解。
    • 函数的形参和返回值的类型注解。
  • 写法:
    • 变量、对象的注解直接在原本的代码基础上,变量或者对象之后加 : 类型 即可,其他赋值等代码都不动。
      • 对象的类型注解就是所属的类。
    • 方法的返回值注解:def 函数名() -> 返回值类型

2.2 容器类型注解

  • 元组类型设置类型详细注解,需要将每一个元素都标记出来。
  • 字典类型设置类型详细注解,需要2个类型,第一个是key第二个是value。

2.3 type定义类型注解

  • 除了使用 变量: 类型 这种语法做注解外,也可以在注释中进行类型注解。
    • 语法:# type: 类型

2.4 Union联合类型

  • 对于可以存放各种类型的容器来说,如果一个一个的把所有元素的类型都按顺序写出来会比较麻烦,可以使用联合类型指出所有可能的类型即可。

  • 用法:先从typing导包,然后 Union[所有可能的类型逗号隔开]

from typing import Union# data可能是int, str种的一种
def process_data(data: Union[int, str]) -> None:if isinstance(data, int):print(f"Processing integer: {data}")elif isinstance(data, str):print(f"Processing string: {data}")process_data(42)
process_data("Hello")
  • isinstance 用来判断对象和类的关系,返回 True 或 False:
    • 第一个参数写对象,第二个参数写类。

三、闭包

  • 闭包指的是函数进行嵌套,内部函数使用外层函数的参数,并且外层函数返回值是内层函数本身
  • 如果一个变量只是用来传递给仅一个函数使用,可以使用闭包增加安全性。
def outer(num1: str):def inner(num2: str):# 内部函数可直接使用外层函数的参数print(f'我是{num2},我引用了外层的参数{num1}')# 外层函数直接返回内部函数本身return inner# 此时out1就相当于inner函数,当作函数来使用
out1 = outer('Jay')
out1('Tom') # 我是Tom,我引用了外层的参数Jay
  • 如果不使用闭包,直接在inner之外定义num1变量,会存在被导包后被其他模块篡改num1变量的风险,而使用闭包避免这种风险,增加安全性。

  • 可以在内部函数中使用 nonlocal 关键字修饰外层函数的参数,从而使得内部函数可以修改这个参数的值。

    def outer(num1: int):def inner(num2: int):# 使用nonlocal关键字修饰外层函数的参数,从而可以修改他nonlocal num1num1 += num2return num1return innerfn = outer(10)
    print(fn(20)) # 30
    print(fn(20)) # 50
    
    • 注意:观察上方代码的最后两行,并不是两次输出都是30,那么得出结论:外层函数的变量在内层函数是共用的,也就是一旦外层函数的参数被修改,那么对内层函数不论调用几次都整体生效,不会重置。
  • 闭包优缺点:

    • 优点:
      • 无需定义全局变量即可通过内层函数持续访问、修改它的参数。
      • 增加代码安全性。
    • 缺点:
      • 内部函数持续引用外部函数的值,会导致这一部分内存空间不释放,占用内存(但是几个变量不释放的内存可以忽略不计)。

四、装饰器

  • 装饰器也是闭包,其作用是在不改变原有函数功能的基础上,为函数增加新功能。
  • 装饰器本质上是一个接受函数作为参数并返回内层函数的函数。也就是上述闭包模块的外层函数的参数不再是一个变量,而是一个函数。

举例:想要在调用sleep函数前后各执行一些代码:

# 外层函数的参数接收一个函数
def outerFunc(func):def inner():print('睡觉前做的事情')func()print('睡觉后做的事情')return innerdef sleep():print('我要睡觉了啊')inner = outerFunc(sleep)
inner()
"""
睡觉前做的事情
我要睡觉了啊
睡觉后做的事情
"""

代码可使用装饰器的语法糖来写:

def outerFunc(func):def inner():print('睡觉前做的事情')func()print('睡觉后做的事情')return inner# 使用@+外层函数名的方式
@outerFunc
def sleep():print('我要睡觉了啊')# 直接调用sleep函数即可实现上述功能
sleep()
"""
睡觉前做的事情
我要睡觉了啊
睡觉后做的事情
"""
  • 在这个例子中,自定义的 @outerFunc 就是一个装饰器,sleep() 是被装饰器修饰的函数。调用 sleep() 其实是在调用外层函数 outerFunc() 的内层方法 inner(),且外层方法的参数是被修饰的 sleep() 函数。
  • sleep() 函数被修饰,所以调用 sleep() 函数就是修饰后的内容,而不是函数原本的内容。

总结一下具体写法:

  1. 想要修饰哪个函数就给哪个函数加装饰器。
  2. 定义一个与装饰器同名的外层函数,并接收一个参数(这个参数实际就是被修饰的函数)。
  3. 定义内层函数(这是将要被实际执行的函数),并在内层函数中使用外层函数的参数(被修饰的函数)。
  4. 直接调用被修饰的函数,运行结果就是被修饰后的代码(内层函数)。

注意:外层函数要在被修饰的函数之前定义,因为Python代码从上往下执行,否则Python识别不到当前行之后的内容。

五、构造方法重写补充

注意事项:

  • 在Python中,如果子类没有显式定义构造函数(__init__方法),当实例化子类对象时,Python 会自动调用父类的构造函数。这是 Python 的默认行为,以使用父类的构造方法提供的功能。
  • 如果需要在子类中添加更多的初始化逻辑,可以定义子类自己的 __init__ 方法,并且一定要在其中调用父类的 __init__ 方法,确保父类的初始化逻辑也能够执行。
  • 调用父类的属性(两种方式无差别):
    • 父类名.属性名
    • super().属性名
  • 调用父类的方法(无论构造方法还是普通方法都要遵守以下两个规则):
    • 父类名.方法名一定需要显式传递 self 作为第一个参数。
    • super().方法名一定不需要显示传递 self 作为第一个参数。因为 super() 会自动处理这个参数。在多继承情况下更有用,所以推荐以后都使用这种方式。

5.1 子类单继承没有定义构造方法

class Base1:def __init__(self):print("父类1构造方法执行了!")class Child(Base1):# 没有显示调用父类的构造方法pass# 创建 Child 类的实例
child = Child()

输出:

父类1构造方法执行了!

5.2 子类单继承重写构造方法

使用super()调用:

class Base1:def __init__(self):print("父类1构造方法执行了!")def normalMethod(self):print("调用了父类的普通方法")class Child(Base1):def __init__(self):super().__init__()super().normalMethod()print("子类构造方法执行了!")# 创建 Child 类的实例
child = Child()

输出:

父类1构造方法执行了!
调用了父类的普通方法
子类构造方法执行了!

使用父类名调用:

class Base1:def __init__(self):print("父类1构造方法执行了!")def normalMethod(self):print("调用了父类的普通方法")class Child(Base1):def __init__(self):Base1.__init__(self)Base1.normalMethod(self)print("子类构造方法执行了!")# 创建 Child 类的实例
child = Child()

5.3 MRO

  • 在Python中,使用 super() 函数来调用父类的构造方法遵循了方法解析顺序(Method Resolution Order,MRO)。MRO是Python确定方法继承顺序的一种方式,它是基于C3线性化算法。
  • super() 的工作方式:在构造方法中使用 super().__init__() 时,Python会查找当前类的MRO来确定下一个类,并调用下一个类的构造方法
  • 通过 类名.__mro__ 可以得到一个类的MRO顺序。

如何确定一个类的MRO呢?比如这段代码:

class Base1:def __init__(self):print("父类1构造方法执行了!")def normalMethod(self):print("调用了父类1的普通方法")class Base2:def __init__(self):print("父类2构造方法执行了!")def normalMethod(self):print("调用了父类2的普通方法")class Child(Base1, Base2):def __init__(self):super().__init__()print(Child.__mro__)
# 输出:(<class '__main__.Child'>, <class '__main__.Base1'>, <class '__main__.Base2'>, <class 'object'>)

1. 首先确定大方向

  • 当前基类一定是排在第一位的,然后考虑当前类的父类,按照父类引用的顺序,从左到右给父类排序。
  • 如果一个基类有多个父类,那么这个父类的MRO也会按照和子类相同的算法(C3线性化算法)来计算。
  • 所有的Python类最终都继承自 object 类,所以 object 是MRO中的最后一个元素。
  • 最后,Python将当前类、父类的MRO、以及 object 合并起来,形成当前类的MRO。

目前的MRO顺序:Child、Base1的MRO、Base2的MRO、object

2. 根据C3线性化算法,以下是确定两个父类MRO的详细步骤:

  • 对每个父类,列出它的MRO(这俩父类都没继承其他类):

    • Base1的MRO是[Base1, object]
    • Base2的MRO是[Base2, object]
  • 从两个父类列表的第一个元素开始,如果这个元素在其他列表中也是第一个元素,或者不在其他列表中,那么它就被添加到最终的MRO中。然后从所有包含这个元素的列表中移除这个元素。(可以简单的认为是在剔除重复已有元素)

  • 重复上述步骤,直到所有列表都为空。

故最终可以得到以下顺序:

  1. 选择 Base1(因为它在第一个列表中,并且不在其他列表中),最终MRO得到 [Child, Base1]。第一个列表的Object不做处理,因为它不满足条件。
  2. 然后选择第二个列表的 Base2(因为它不在其他列表中),最终MRO得到 [Child, Base1, Base2]
  3. 最后选择 object得到最终的MRO[Child, Base1, Base2, object]

如果父类也有继承的类:

class BaseA:def __init__(self):print("BaseA init")class BaseB:def __init__(self):print("BaseB init")class Base1(BaseA):def __init__(self):super().__init__()print("Base1 init")class Base2(BaseB):def __init__(self):super().__init__()print("Base2 init")class Child(Base1, Base2):def __init__(self):super().__init__()print("Child init")print(Child.__mro__)

输出:

(<class '__main__.Child'>, <class '__main__.Base1'>, <class '__main__.BaseA'>, <class '__main__.Base2'>, <class '__main__.BaseB'>, <class 'object'>)

注意:只有使用 super().__init__() 方式时才会使用到MRO的逻辑,如果通过父类名调用的话,和MRO无关。

5.3.1 子类多继承没有定义构造方法

如果子类没有定义构造方法,则子类会根据MRO的顺序,只有第一个父类的构造方法会被自动调用,其他父类的构造方法不会被调用:

class Base1:def __init__(self):print("父类1构造方法执行了!")class Base2:def __init__(self):print("父类2构造方法执行了!")class Child(Base1, Base2):passchild = Child()
#只会输出:父类1构造方法执行了!
5.3.2 子类多继承重写构造方法

注意:子类中如果通过父类名显示调用了父类的构造方法,则没有调用所有父类的构造方法也不会报错,因为Python支持选择性调用父类的构造方法。

多继承更推荐使用 super() 方式调用父类构造方法,因为只使用一个 super() 就可以自动加载所有的父类构造方法而不用一个个去调用:

class Base1:def __init__(self):print("父类1构造方法执行了!")class Base2:def __init__(self):print("父类2构造方法执行了!")class Child(Base2, Base1):def __init__(self):super().__init__()print("Child init")child = Child()

输出:

父类2构造方法执行了!
Child init

为什么子类使用了 super() 方式,但是只调用了一个父类的构造方法解释:

Child类的MRO顺序:(<class '__main__.Child'>, <class '__main__.Base2'>, <class '__main__.Base1'>, <class 'object'>)

  1. super().__init__() Child 的构造方法中被调用,它根据MRO调用 Base2 的构造方法。
  2. 但是 Base2 中没有使用 super() ,所以就不会再继续往上调用了(只有遇到了 super() 方法才会使用MRO逻辑)。

综合示例:

class BaseA:def __init__(self):super().__init__()print("BaseA init")class BaseB:def __init__(self):print("BaseB init")class Base1(BaseA):def __init__(self):super().__init__()print("Base1 init")class Base2(BaseB):def __init__(self):super().__init__()print("Base2 init")class Child(Base1, Base2):def __init__(self):super().__init__()print("Child init")# 创建 Child 类的实例
child = Child()

Child的MRO:

(<class '__main__.Child'>, <class '__main__.Base1'>, <class '__main__.BaseA'>, <class '__main__.Base2'>, <class '__main__.BaseB'>, <class 'object'>)

运行结果:

BaseB init
Base2 init
BaseA init
Base1 init
Child init

注意:调用完最上层的构造方法之后要开始回溯。

原文地址:https://blog.csdn.net/weixin_49343190/article/details/146287567
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mrgr.cn/news/94513.html

相关文章:

  • C++进阶——map和set的使用
  • 便捷搞定计算机名、IP 与 Mac 地址修改及网卡问题的软件
  • RxSwift 学习笔记第二篇之Observables
  • RxSwift 学习笔记之RxSwift的调试
  • 阿里巴巴发布 R1-Omni:首个基于 RLVR 的全模态大语言模型,用于情感识别
  • Linux内核实时机制18 - RT调度器1 - 数据结构
  • 【深度学习与大模型基础】第3章-张量
  • 探针泄露(WEB)
  • RTDETR融合[CVPR2025]ARConv中的自适应矩阵卷积
  • GolangTCP通信解决粘包问题
  • SQL Server查询优化
  • Android LeakCanary 使用 · 原理详解
  • 《TCP/IP网络编程》学习笔记 | Chapter 17:优于 select 的 epoll
  • Linux 安装 Oh My Zsh
  • Centos 7 安装达梦数据库
  • Odoo18 Http鉴权+调用后端接口
  • MySQL(事物上)
  • 学习15天:pytest
  • STM32配套程序接线图
  • linux磁盘和文件系统