Python-VBA函数之旅-staticmethod函数

目录

一、staticmethod函数的常见应用场景

二、staticmethod函数使用注意事项

三、如何用好staticmethod函数?

1、staticmethod函数:

1-1、Python:

1-2、VBA:

2、推荐阅读:

个人主页: https://blog.csdn.net/ygb_1024?spm=1010.2135.3001.5421

一、staticmethod函数的常见应用场景

        staticmethod函数在Python中用于定义静态方法,这些方法属于类的一部分,但不依赖于类的实例或类本身的状态,静态方法主要用于将工具函数或与类紧密相关的辅助函数与类相关联,但又不需要访问或修改类的实例或类级别的状态。该函数的常见应用场景有:

1、设计模式中的实现:在设计模式中,静态方法可以用于实现如工厂方法模式、单例模式等,工厂方法模式允许子类决定实例化哪一个类,而单例模式确保一个类只有一个实例,并提供一个全局访问点。

2、类级别的缓存:静态方法可以用于实现类级别的缓存,这样所有实例都可以共享缓存的数据,而不是每个实例都有自己的缓存。例如,一个 API 调用类可能使用静态方法来缓存 API 响应,以减少对同一资源的重复请求。

3、工具函数和实用程序:当需要在多个类中重复使用某些工具函数或实用程序时,可以将它们定义为静态方法,这样,这些函数就可以与类一起被导入和使用,而无需单独导入它们。

4、类的初始化或配置:静态方法可以用于执行与类相关的初始化或配置任务,这些任务通常不需要在类的每个实例中重复执行。例如,一个数据库连接类可能使用静态方法来建立与数据库的连接,并将连接对象存储在类变量中,供所有实例共享。

5、与类相关的计算:有时,某些计算或操作与类紧密相关,但并不涉及类的实例状态,这些计算或操作可以定义为静态方法。例如,一个数学类可能包含用于计算特定数学函数(如阶乘、斐波那契数列等)的静态方法。

6、模拟或模拟对象:在测试或模拟环境中,静态方法可以用于模拟类或对象的行为,通过覆盖类的静态方法,可以模拟类的某些行为,以便在测试中验证代码的正确性。

7、与框架或库的集成:当与某些框架或库集成时,可能需要使用静态方法来遵循特定的接口或约定,这些静态方法可能是框架或库期望的回调或钩子函数,用于执行特定的操作或处理特定的事件。

8、函数式编程风格:虽然Python主要是一种面向对象的编程语言,但它也支持函数式编程风格,静态方法可以被视为一种将函数与类相关联的方式,以便在函数式编程和面向对象编程之间实现更平滑的过渡。

9、多线程或异步编程中的回调函数:在多线程或异步编程中,回调函数通常与类相关,但不需要访问类的实例状态,在这种情况下,静态方法可以用作回调函数。

        注意,虽然静态方法在某些高级应用场景中很有用,但它们也应该谨慎使用;过度使用静态方法可能会导致代码难以理解和维护,因为它们破坏了面向对象编程中的封装和继承原则,因此,在决定是否使用静态方法时,应该仔细考虑其优点和缺点,并权衡其对代码质量和可维护性的影响。

二、staticmethod函数使用注意事项

        在Python中,staticmethod()是一个内置函数,用于将一个方法转换为一个静态方法。静态方法不需要类的实例作为第一个参数(即通常的self参数),它们可以通过类本身直接调用,也可以通过类的实例调用,使用staticmethod()函数时,需注意以下事项:

1、不需要实例:静态方法不需要类的实例来调用,因此它们不会接收self参数,如果你尝试在静态方法的定义中包含self参数,它将被视为一个普通的参数,而不是对类实例的引用。

2、可以通过类和实例访问:静态方法可以通过类本身或类的实例来访问。例如,如果你有一个名为MyClass的类,并且它有一个静态方法my_static_method(),你可以通过 MyClass.my_static_method()或my_instance.my_static_method()(其中my_instance是MyClass的一个实例)来调用它。

3、无法访问或修改实例状态:由于静态方法不接收self参数,因此它们无法直接访问或修改类的实例状态,如果你需要在方法中访问或修改实例状态,你应该使用实例方法(即包含self参数的方法)。

4、可用于工厂方法:静态方法经常用作工厂方法,用于创建并返回类的实例,工厂方法可以根据需要创建并配置类的实例,而无需直接调用类的构造函数。

5、不要误用:虽然静态方法在Python中是合法的,但过度使用它们可能会导致代码结构不清晰,在大多数情况下,如果你可以通过实例方法或类方法来实现某个功能,那么最好不要使用静态方法。

6、装饰器语法:从Python 2.6开始,你可以使用@staticmethod装饰器来定义静态方法,而不是使用staticmethod()函数,这通常会使代码更简洁、更易于阅读。

7、静态方法与类方法:虽然静态方法和类方法都不需要实例参数,但类方法会接收类本身作为第一个参数(通常命名为 `cls`),而静态方法则不会;类方法通常用于修改类状态或执行与类本身相关的操作,而静态方法则更常用于执行与类无关的操作。

三、如何用好staticmethod函数?

        在Python中,staticmethod()函数(或更常见的@staticmethod装饰器)通常用于定义那些与类本身紧密相关但不需要访问或修改类实例状态的方法,这些静态方法通常用于执行与类相关的实用功能,但不需要访问类的内部状态或实例

以下是关于如何用好staticmethod()函数的一些建议:

1、明确用途:首先,确定你确实需要一个静态方法,如果方法需要访问或修改实例状态,那么它应该是一个实例方法;如果方法需要访问或修改类状态,那么它应该是一个类方法。

2、使用装饰器语法:Python提供了@staticmethod装饰器,这使得定义静态方法更加简洁,尽可能使用装饰器语法,而不是显式地调用staticmethod()函数。

3、避免不必要的静态方法:如果一个方法既不需要访问类状态也不需要访问实例状态,并且它完全独立于类的其他部分,那么考虑是否应该将其定义为一个模块级别的函数,而不是类的静态方法。

4、使用有意义的名称:为静态方法选择清晰、描述性的名称,以便其他开发者能够理解该方法的作用和用途。

5、避免在静态方法中引用实例属性或方法:静态方法不应该引用实例属性或方法,因为它们不接收实例作为参数,如果静态方法需要访问实例数据,那么它可能更适合作为实例方法。

6、作为工厂方法:静态方法的一个常见用途是作为工厂方法,用于创建并返回类的实例;工厂方法可以根据不同的参数创建和配置类的实例,从而提供更大的灵活性。

7、文档化:为静态方法编写文档字符串(docstring),解释方法的作用、参数、返回值和可能的副作用,这将有助于其他开发者理解如何使用你的静态方法。

8、测试:编写针对静态方法的单元测试,以确保它们按预期工作,测试将帮助你验证方法的正确性,并在未来修改代码时防止引入错误。

        总之,只有通过遵循这些建议,你才能更好地利用Python中的staticmethod()函数,并编写出清晰、可维护和可测试的代码。

1、staticmethod函数:
1-1、Python:
# 1.函数:staticmethod
# 2.功能:用于标示方法为静态方法的装饰器
# 3.语法:
# 3-1、staticmethod(function)
# 3-2、@staticmethod
#      def f(arg1, arg2, ...): ...
# 4.参数:
# 4-1、function:方法名
# 4-2、arg1:方法的参数1
# 4-3、arg2:方法的参数2
# 5.返回值:返回函数的静态方法
# 6.说明:
# 7.示例:
# 用dir()函数获取该函数内置的属性和方法
print(dir(staticmethod))
# ['__call__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__func__',
# '__ge__', '__get__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__',
# '__isabstractmethod__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
# '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__wrapped__']

# 用help()函数获取该函数的文档信息
help(staticmethod)

# 应用一:设计模式中的实现
class Product:
    def __init__(self, name):
        self.name = name
    def use(self):
        print(f"Using product: {self.name}")
class ProductFactory:
    @staticmethod
    def create_product(product_type):
        if product_type == "A":
            return ProductA("Product A")
        elif product_type == "B":
            return ProductB("Product B")
        else:
            raise ValueError("Invalid product type")
class ProductA(Product):
    def __init__(self, name):
        super().__init__(name)
        print(f"Creating {name} of type A")
class ProductB(Product):
    def __init__(self, name):
        super().__init__(name)
        print(f"Creating {name} of type B")
# 使用工厂方法创建产品
product_a = ProductFactory.create_product("A")
product_a.use()
product_b = ProductFactory.create_product("B")
product_b.use()
# Creating Product A of type A
# Using product: Product A
# Creating Product B of type B
# Using product: Product B
# 尝试创建一个无效类型的产品
# ValueError: Invalid product type
# product_c = ProductFactory.create_product("C")
# product_c.use()

# 应用二:类级别的缓存
class CachedClass:
    _cache = {}  # 类级别的缓存字典
    @staticmethod
    def get_cached_value(key):
        """从缓存中获取值"""
        return CachedClass._cache.get(key)
    @staticmethod
    def set_cached_value(key, value):
        """将值存储到缓存中"""
        CachedClass._cache[key] = value
    @staticmethod
    def compute_expensive_operation(key):
        """执行一个昂贵的操作,并缓存结果"""
        if key not in CachedClass._cache:
            print(f"Computing value for key {key}...")
            # 假设这是一个昂贵的操作
            value = key * 2  # 示例操作
            CachedClass.set_cached_value(key, value)
        return CachedClass.get_cached_value(key)
# 使用缓存的示例
print(CachedClass.compute_expensive_operation(1))  # 输出: Computing value for key 1... 和 2
print(CachedClass.compute_expensive_operation(1))  # 直接从缓存中获取,不重新计算
print(CachedClass.compute_expensive_operation(2))  # 输出: Computing value for key 2... 和 4
# Computing value for key 1...
# 2
# 2
# Computing value for key 2...
# 4

# 应用三:工具函数和实用程序
class MathUtilities:
    @staticmethod
    def add_numbers(a, b):
        """简单的加法工具函数"""
        return a + b
    @staticmethod
    def multiply_numbers(a, b):
        """简单的乘法工具函数"""
        return a * b
    @staticmethod
    def is_prime(n):
        """检查一个数是否为质数的实用程序"""
        if n <= 1:
            return False
        elif n == 2:
            return True
        elif n % 2 == 0:
            return False
        else:
            for i in range(3, int(n ** 0.5) + 1, 2):
                if n % i == 0:
                    return False
            return True
# 使用工具函数和实用程序
print(MathUtilities.add_numbers(5, 3))  # 输出: 8
print(MathUtilities.multiply_numbers(4, 6))  # 输出: 24
print(MathUtilities.is_prime(7))  # 输出: True
print(MathUtilities.is_prime(10))  # 输出: False
# 8
# 24
# True
# False

# 应用四:类的初始化或配置
class MyClass:
    _config = {}  # 类的配置字典,作为类变量存储
    @staticmethod
    def set_config(key, value):
        """设置类的配置值"""
        if key not in MyClass._config:
            print(f"Setting new config value for {key}")
        MyClass._config[key] = value
    @staticmethod
    def get_config(key):
        """获取类的配置值"""
        return MyClass._config.get(key)
    def __init__(self, value, use_default_config=True):
        """初始化方法,可以使用默认配置或自定义配置"""
        if use_default_config:
            # 如果要使用默认配置,可以从_config中获取
            self.value = value * MyClass.get_config('multiplier')
        else:
            # 否则,直接使用给定的值
            self.value = value
# 设置类的配置
MyClass.set_config('multiplier', 2)
# 创建类的实例,使用默认配置
instance1 = MyClass(5, use_default_config=True)
print(instance1.value)  # 输出: 10 (因为5 * 2 = 10)
# 创建类的另一个实例,不使用默认配置
instance2 = MyClass(5, use_default_config=False)
print(instance2.value)  # 输出: 5 (因为直接使用给定的值)
# 修改类的配置
MyClass.set_config('multiplier', 3)
# 创建类的另一个实例,使用新的默认配置
instance3 = MyClass(5, use_default_config=True)
print(instance3.value)  # 输出: 15 (因为5 * 3 = 15)
# Setting new config value for multiplier
# 10
# 5
# 15

# 应用五:与类相关的计算
import math
class Circle:
    pi = math.pi  # 圆的π值,作为类变量存储
    @staticmethod
    def area(radius):
        """计算圆的面积"""
        return Circle.pi * (radius ** 2)
    @staticmethod
    def circumference(radius):
        """计算圆的周长"""
        return 2 * Circle.pi * radius
# 使用静态方法进行计算
radius = 5
area_result = Circle.area(radius)
circumference_result = Circle.circumference(radius)
print(f"圆的面积为: {area_result}")
print(f"圆的周长为: {circumference_result}")
# 圆的面积为: 78.53981633974483
# 圆的周长为: 31.41592653589793

# 应用六:模拟或模拟对象
class BankAccount:
    def __init__(self, balance):
        self.balance = balance
    @staticmethod
    def calculate_interest(balance, interest_rate):
        """模拟计算利息的静态方法"""
        return balance * (interest_rate / 100)
    def add_interest(self, interest_rate):
        """给账户增加利息的方法"""
        interest = BankAccount.calculate_interest(self.balance, interest_rate)
        self.balance += interest
        print(f"Interest added: {interest}")
        print(f"New balance: {self.balance}")
# 创建一个银行账户实例
account = BankAccount(1000)
# 使用静态方法计算利息(但通常这步是在add_interest方法内部完成的)
# 这里只是为了演示静态方法的使用
interest = BankAccount.calculate_interest(account.balance, 5)
print(f"Calculated interest: {interest}")
# 使用实例方法给账户增加利息
account.add_interest(5)
# Calculated interest: 50.0
# Interest added: 50.0
# New balance: 1050.0

# 应用七:与框架或库的集成
class MessageQueueClient:
    # 假设有一个全局的消息队列连接或配置
    # 这里只是示意,实际情况中可能需要更复杂的配置和连接管理
    QUEUE_CONNECTION = None  # 模拟的消息队列连接
    @staticmethod
    def configure_queue(connection_details):
        """配置消息队列连接(静态方法)"""
        MessageQueueClient.QUEUE_CONNECTION = connection_details
        print(f"Configured message queue with details: {connection_details}")
    @staticmethod
    def send_message(message):
        """发送消息到消息队列(静态方法)"""
        if MessageQueueClient.QUEUE_CONNECTION is None:
            raise RuntimeError("Message queue is not configured.")
        # 这里只是模拟发送消息,实际情况中会使用QUEUE_CONNECTION发送消息
        print(f"Sending message to queue: {message}")
        # 假设消息成功发送
        return True
# 使用静态方法配置消息队列
MessageQueueClient.configure_queue("localhost:1068")
# 使用静态方法发送消息
success = MessageQueueClient.send_message("Hello, Message Queue!")
if success:
    print("Message sent successfully.")
# Configured message queue with details: localhost:1068
# Sending message to queue: Hello, Message Queue!
# Message sent successfully.

# 应用八:函数式编程风格
class MathTools:
    @staticmethod
    def add(a, b):
        """函数式风格的加法"""
        return a + b
    @staticmethod
    def multiply(a, b):
        """函数式风格的乘法"""
        return a * b
    @staticmethod
    def factorial(n):
        """函数式风格的阶乘"""
        if n == 0 or n == 1:
            return 1
        return n * MathTools.factorial(n - 1)
# 使用静态方法进行计算
result_add = MathTools.add(3, 4)
result_multiply = MathTools.multiply(5, 6)
result_factorial = MathTools.factorial(5)
print(f"Addition result: {result_add}")
print(f"Multiplication result: {result_multiply}")
print(f"Factorial of 5: {result_factorial}")
# Addition result: 7
# Multiplication result: 30
# Factorial of 5: 120

# 应用九:多线程或异步编程中的回调函数
import threading
import time
class MultiThreadDemo:
    @staticmethod
    def worker(thread_name, delay):
        """静态方法作为线程的工作函数(回调函数)"""
        print(f"Thread {thread_name} starting...")
        time.sleep(delay)
        print(f"Thread {thread_name} finished.")
    @staticmethod
    def create_and_start_threads(num_threads, delay):
        """创建并启动多个线程"""
        for i in range(num_threads):
            t = threading.Thread(target=MultiThreadDemo.worker, args=(f"Thread-{i + 1}", delay))
            t.start()
# 使用静态方法创建并启动线程
MultiThreadDemo.create_and_start_threads(num_threads=3, delay=2)
# 主线程将等待所有其他线程完成(在这个例子中,我们只是简单地让主线程休眠以确保其他线程有机会运行)
time.sleep(5)  # 等待足够长的时间以确保所有线程都完成
print("All threads finished.")
# Thread Thread-1 starting...
# Thread Thread-2 starting...
# Thread Thread-3 starting...
# Thread Thread-1 finished.
# Thread Thread-3 finished.Thread Thread-2 finished.
#
# All threads finished.
1-2、VBA:
略,待后补。
2、推荐阅读:

2-1、Python-VBA函数之旅-property()函数

Python算法之旅:Algorithm

Python函数之旅:Functions

个人主页: https://blog.csdn.net/ygb_1024?spm=1010.2135.3001.5421

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/616117.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【EMQX实践】如何感知设备上下线?

序言 在智能物联时代&#xff0c;存设备需要联网上云场景。EMQX在此场景中属于设备连接网关关键节点&#xff0c;EMQX不紧紧只是消息中间件的作用&#xff0c;我们更需要监控哪些设备什么时候连接上线&#xff0c;又在什么时候断开下线。 为什么需要感知设备上下线 感知设备…

二叉树介绍

引入 定义 区别 定义不同 形态不同 基本形态

vscode默认终端设置为cmd的方法

vscode默认终端是powershell,执行某些命令时会提示权限等问题&#xff0c;如果更习惯使用cmd终端的话&#xff0c;可以将默认终端配置为cmd。 方法一&#xff1a; 方法二&#xff1a; 如果你想更改默认的终端&#xff0c;可以通过以下步骤操作&#xff1a; 打开 VSCode。使用…

Applied Spatial Statistics(五)线性回归 I

Applied Spatial Statistics&#xff08;五&#xff09;线性回归 I 该笔记本演示了&#xff1a; 线性回归系数估计在假设下是无偏的如何围绕系数估计构建 bootstrap 置信区间残差图Q-Q图 1. 线性回归系数估计在假设下是无偏的 import numpy as np import matplotlib.pyplot…

大数据比赛-环境搭建(一)

1、安装VMware Workstation 链接&#xff1a;https://pan.baidu.com/s/1IvSFzpnQFl3svWyCGRtEmg 提取码&#xff1a;ukpo 内有安装包及破解方式&#xff0c;安装教程。 2、下载Ubuntu系统 阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区 (aliyun.com) 点击下载&#xff…

掌握未来搜索的钥匙:深入解析 Milvus 向量搜索引擎的终极指南!

在大数据时代&#xff0c;向量搜索技术愈发重要。作为一个开源的向量相似性搜索引擎&#xff0c;Milvus 提供了基于向量的相似性搜索功能&#xff0c;广泛应用于机器学习、人工智能等领域。本文将深入介绍 Milvus 的基本概念&#xff0c;包括其介绍、主要作用、使用方法及注意事…

命令行工具部署达梦数据库 DMDPC(BP 多副本架构)

解达梦数据库DPC集群的主要使用场景&#xff1a; DMDPC 关注和解决的是大数据、计算与存储分离、高可用、支持全部的 SQL 标准、拥有完整的事务处理能力和集群规模能够动态伸缩的业务场景&#xff1a; 大量的复杂查询操作要求优化器能够生成优良的执行计划&#xff0c;并且执…

【北京迅为】《iTOP-3588从零搭建ubuntu环境手册》-第7章 安装VMwareTools

RK3588是一款低功耗、高性能的处理器&#xff0c;适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用&#xff0c;RK3588支持8K视频编解码&#xff0c;内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP&…

编程代码的舞者--Python循环语句

循环语句是编程中不可或缺的要素之一&#xff0c;它们能够让程序反复执行特定的任务&#xff0c;提高代码的重复利用性和效率。在本篇博客中&#xff0c;我们将深入探讨Python中常用的循环语句&#xff0c;包括for循环和while循环&#xff0c;以及控制循环流程的关键字break和c…

OBS插件--复合模糊

复合模糊 复合是一款滤镜插件&#xff0c;支持多种模糊类型和多种蒙版效果。支持模糊源的部分显示区域&#xff0c;可以反选区域进行模糊&#xff0c;这个功能对于场景部分区域需要遮盖非常实用。 下面截图演示下操作步骤&#xff1a; 首先&#xff0c;打开 OBS直播助手 在…

draw.io 网页版二次开发(3):打包和部署(war包)

目录 一 说明 二 环境配置 1. 下载并安装 Apache Ant 2. 下载并安装JDK和JRE 3. 下载tomcat 4. Ant、JDK和JRE 环境变量的配置 三 draw.io打包 四 部署 五 最后 一 说明 应公司项目要求&#xff0c;需要对draw.io进行二次开发&#xff0c;并将html界面通过iframe 嵌…

数据结构之——队列详解

目录 前言&#xff1a; 一、什么是队列 二、队列的实现 2.1 队列结构 2.2 队列初始化 2.3 队列销毁 2.4 入队列 2.5 出队列 2.6 获取队列头部元素 2.7 获取队列尾部元素 2.8 获取队列中有效元素个数 2.9 检测队列是否为空 三、 代码总览 Queue.h test.c 四、例题 前言…

SpringSecurity集成第三方登录

SpringSecurity 集成第三方登录 认证及自定义流程 首先我们提供一个实现了AbstractAuthenticationProcessingFilter抽象类的过滤器&#xff0c;用来代替UsernamePasswordAuthenticationFilter逻辑&#xff0c;然后提供一个AuthenticationProvider实现类代替AbstractUserDetail…

vue3vue3vue3vue3vue3vue3vue3vue3vue3vue3vue3vue3

纯vue3的语法 一.创建&#xff08;基于vite&#xff09; 1.在指定目录下运行 npm create vuelatest 项目名称&#xff1a;英文小写下划线数字回车表示确定是、否 左右切换路由、pina、单元测试、端到端的测试、开启eslint控制代码质量 先选择no&#xff0c;学的时候自己手动…

Golang | Leetcode Golang题解之第78题子集

题目&#xff1a; 题解&#xff1a; func subsets(nums []int) (ans [][]int) {set : []int{}var dfs func(int)dfs func(cur int) {if cur len(nums) {ans append(ans, append([]int(nil), set...))return}set append(set, nums[cur])dfs(cur 1)set set[:len(set)-1]df…

Reactor Netty 其他-响应式编程-018

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace The Nex…

triton编译学习

一 流程 Triton-MLIR: 从DSL到PTX - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/671434808Superjomns blog | OpenAI/Triton MLIR 迁移工作简介https://superjom

ctfshow SSRF 351-358

做题前,需要先学习关于ssrf漏洞的相关知识 小注意: 当使用 file_get_contents() 函数访问远程 URL 时&#xff0c;它会尝试获取该 URL 指向的资源的内容&#xff0c;并将内容以字符串的形式返回。 如果 b.php 文件是一个 PHP 文件&#xff0c;它包含的内容取决于该 PHP 文件…

【QT学习】补充:qt使用已经存在的类

1.右键项目--》添加现有文件 注意&#xff1a;不是添加新文件&#xff01;&#xff01;&#xff01; 2.添加配置

【Unity Shader入门精要 第6章】基础光照(二)

1. 获取环境光 unity shader中可以通过 UNITY_LIGHTMODEL_AMBIENT获取当前环境光颜色信息。 fixed4 frag(v2f i) : SV_Target {return UNITY_LIGHTMODEL_AMBIENT; }2. 漫反射 2.1 兰伯特模型 创建Chapter_6_Diffuse_Lambert作为测试材质创建Chapter_6_Diffuse_Lambert作为测…