【Python设计模式02】设计原则

1.单一职责原则

单一职责原则(Single Responsibility Principle, SRP)是面向对象编程中SOLID原则的第一个原则。它强调每个类应该只有一个引起变化的原因,即一个类只负责一项职责。这一原则有助于提高代码的可维护性、可读性和可复用性。

单一职责原则的定义

单一职责原则的定义是:

  • 每个类应该只有一个引起变化的原因。

这意味着,一个类应该仅有一个明确的职责。当职责过多时,类的修改可能会影响到多个方面,导致代码难以维护和扩展。

单一职责原则的优点

  1. 提高可维护性:职责单一的类更容易理解和维护。
  2. 增强可读性:职责明确的类有助于其他开发者快速理解其功能和作用。
  3. 提高复用性:职责单一的类可以在不同的上下文中复用,而不需要担心副作用。
  4. 降低耦合度:遵循单一职责原则的类通常耦合度较低,修改一个类的实现不会影响到其他类。

示例

假设我们有一个类负责用户的所有操作,包括保存用户信息和发送电子邮件。这违反了单一职责原则,因为这个类有两个职责:数据处理和发送邮件。

违反单一职责原则的示例
class User:def __init__(self, name, email):self.name = nameself.email = emaildef save(self):print(f"Saving user {self.name}")def send_email(self, message):print(f"Sending email to {self.email}: {message}")

在这个示例中,User类负责保存用户信息和发送电子邮件,这违反了单一职责原则。

遵循单一职责原则的示例

我们可以将保存用户信息和发送电子邮件的职责分离到不同的类中:

class User:def __init__(self, name, email):self.name = nameself.email = emailclass UserRepository:def save(self, user: User):print(f"Saving user {user.name}")class EmailService:def send_email(self, email: str, message: str):print(f"Sending email to {email}: {message}")

在这个示例中,User类只负责存储用户信息,UserRepository类负责保存用户信息,EmailService类负责发送电子邮件。这样,每个类都有明确的职责,符合单一职责原则。

实践中的单一职责原则

在实践中,遵循单一职责原则可以分为以下几个步骤:

  1. 识别职责:识别当前类中有哪些不同的职责。
  2. 职责分离:将每个职责提取到单独的类中。
  3. 依赖注入:使用依赖注入或其他设计模式,确保类之间的交互不会引入新的耦合。

单一职责原则的适用场景

  1. 类的职责过多:当一个类承担了多项职责时,可以考虑将其职责分离到不同的类中。
  2. 代码难以维护:当修改一个类的某个职责会影响到其他职责时,可以考虑应用单一职责原则进行重构。
  3. 代码复用困难:当一个类的职责过多,导致复用困难时,可以通过分离职责提高代码的复用性。

总结

单一职责原则是面向对象编程中的重要原则之一,强调每个类应该只有一个引起变化的原因。通过遵循单一职责原则,可以提高代码的可维护性、可读性和复用性,降低代码的耦合度。合理应用单一职责原则,可以显著提升代码质量和设计水平。

2.松耦合 vs 紧耦合

在软件设计中,耦合(Coupling)指的是模块或类之间的依赖程度。根据耦合的紧密程度,可以将耦合分为紧耦合(Tight Coupling)和松耦合(Loose Coupling)。理解和控制耦合对构建高质量、可维护和可扩展的软件系统至关重要。

紧耦合(Tight Coupling)

紧耦合是指模块或类之间有很强的依赖关系。一个模块的变化可能会引起另一个模块的变化。这种耦合通常使得系统难以维护和扩展。

特点
  1. 高依赖性:一个类依赖于另一个类的具体实现。
  2. 低可维护性:改变一个类可能需要修改许多依赖类。
  3. 低复用性:紧耦合的类通常难以在其他系统中复用。
示例
class Engine:def start(self):print("Engine started")class Car:def __init__(self):self.engine = Engine()  # 直接依赖具体的 Engine 类def start(self):self.engine.start()print("Car started")car = Car()
car.start()

在这个示例中,Car类直接依赖于Engine类的具体实现。如果需要更换Engine的实现,必须修改Car类的代码。

松耦合(Loose Coupling)

松耦合是指模块或类之间的依赖关系较弱。一个模块的变化不太可能引起另一个模块的变化。这种耦合使得系统更易于维护和扩展。

特点
  1. 低依赖性:一个类依赖于另一个类的抽象,而不是具体实现。
  2. 高可维护性:改变一个类通常不会影响其他类。
  3. 高复用性:松耦合的类通常更容易在其他系统中复用。
示例

通过依赖注入(Dependency Injection)和接口/抽象类,可以实现松耦合。

from abc import ABC, abstractmethodclass Engine(ABC):@abstractmethoddef start(self):passclass GasEngine(Engine):def start(self):print("Gas engine started")class ElectricEngine(Engine):def start(self):print("Electric engine started")class Car:def __init__(self, engine: Engine):self.engine = engine  # 依赖于抽象的 Engine 类def start(self):self.engine.start()print("Car started")gas_engine = GasEngine()
electric_engine = ElectricEngine()car_with_gas_engine = Car(gas_engine)
car_with_electric_engine = Car(electric_engine)car_with_gas_engine.start()
car_with_electric_engine.start()

在这个示例中,Car类依赖于抽象的Engine类,而不是具体的引擎实现。这样,如果需要更换引擎实现,只需提供不同的引擎实例,而不需要修改Car类的代码。

如何实现松耦合

  1. 使用接口或抽象类:通过依赖于接口或抽象类而不是具体实现,减少类之间的依赖。
  2. 依赖注入:通过构造函数注入、方法注入或属性注入,将依赖传递给类,而不是在类内部创建依赖实例。
  3. 使用设计模式:例如策略模式、观察者模式和工厂模式等,可以帮助实现松耦合。
  4. 模块化设计:将系统划分为独立的模块,每个模块只暴露必要的接口,隐藏内部实现细节。

总结

紧耦合和松耦合是软件设计中的重要概念。紧耦合导致高依赖性、低可维护性和低复用性,而松耦合通过减少类之间的依赖,提高系统的可维护性和可扩展性。通过使用接口、依赖注入和设计模式等技术,可以实现松耦合,构建高质量的软件系统。理解和应用这些概念,有助于设计和开发更具弹性和可维护性的代码。

3.开放封闭原则

开放封闭原则(Open/Closed Principle, OCP)是面向对象设计中SOLID原则的第二个原则。由Bertrand Meyer在1988年提出,这一原则的核心思想是:

  • 软件实体(类、模块、函数等)应该对扩展开放,对修改封闭

原则定义

开放封闭原则强调,软件系统应该能够在不修改现有代码的情况下,通过扩展来实现新的功能。这可以通过以下方式实现:

  1. 对扩展开放:允许软件实体的行为通过增加新代码来扩展。
  2. 对修改封闭:软件实体的源代码不应被修改,以保证已有功能的稳定性和可靠性。

如何实现开放封闭原则

实现开放封闭原则的关键在于使用多态性和抽象,通过抽象类或接口定义系统的扩展点,并在具体实现中进行扩展。

使用抽象类和接口

通过定义抽象类或接口,可以在不修改现有代码的情况下,增加新的实现来扩展系统功能。

from abc import ABC, abstractmethodclass Shape(ABC):@abstractmethoddef area(self) -> float:passclass Circle(Shape):def __init__(self, radius: float):self.radius = radiusdef area(self) -> float:return 3.14 * self.radius * self.radiusclass Rectangle(Shape):def __init__(self, width: float, height: float):self.width = widthself.height = heightdef area(self) -> float:return self.width * self.height

在这个示例中,Shape是一个抽象类,定义了一个抽象方法areaCircleRectangle类继承了Shape并实现了area方法。通过这种方式,可以添加新的形状类而不需要修改现有的代码。

使用策略模式

策略模式是一种实现开放封闭原则的设计模式,通过定义一系列算法,并将每个算法封装起来,使它们可以互相替换。

from abc import ABC, abstractmethodclass DiscountStrategy(ABC):@abstractmethoddef apply_discount(self, price: float) -> float:passclass NoDiscount(DiscountStrategy):def apply_discount(self, price: float) -> float:return priceclass PercentageDiscount(DiscountStrategy):def __init__(self, percentage: float):self.percentage = percentagedef apply_discount(self, price: float) -> float:return price * (1 - self.percentage / 100)class PriceCalculator:def __init__(self, strategy: DiscountStrategy):self.strategy = strategydef calculate_price(self, price: float) -> float:return self.strategy.apply_discount(price)# 使用不同的策略
calculator = PriceCalculator(NoDiscount())
print(calculator.calculate_price(100))  # 输出:100calculator.strategy = PercentageDiscount(10)
print(calculator.calculate_price(100))  # 输出:90

在这个示例中,DiscountStrategy是一个抽象类,定义了一个抽象方法apply_discount。具体的折扣策略类如NoDiscountPercentageDiscount实现了这个方法。PriceCalculator类通过策略模式可以在不修改其代码的情况下应用

不同的折扣策略,从而实现了对扩展开放,对修改封闭。

实现开放封闭原则的好处

  1. 提高可维护性:代码修改减少,降低了引入新错误的风险。
  2. 增强可扩展性:通过增加新类或方法来扩展系统功能,而不需要修改已有代码。
  3. 提升灵活性:可以轻松地替换或添加新的行为,而无需大规模修改代码。
  4. 便于测试:单一职责和封闭原则使得代码更加模块化,测试覆盖面更广。

违反开放封闭原则的示例

下面的示例展示了一个违反开放封闭原则的代码,在添加新功能时需要修改已有的代码:

class PaymentProcessor:def process_payment(self, payment_type, amount):if payment_type == "credit":self.process_credit_card_payment(amount)elif payment_type == "paypal":self.process_paypal_payment(amount)else:raise ValueError("Unknown payment type")def process_credit_card_payment(self, amount):print(f"Processing credit card payment of {amount}")def process_paypal_payment(self, amount):print(f"Processing PayPal payment of {amount}")# 使用示例
processor = PaymentProcessor()
processor.process_payment("credit", 100)
processor.process_payment("paypal", 200)

如果要添加新的支付方式,需要修改PaymentProcessor类中的process_payment方法,这违反了开放封闭原则。

遵循开放封闭原则的改进示例

通过使用策略模式和多态性,可以将不同的支付方式封装为独立的类,避免修改PaymentProcessor类:

from abc import ABC, abstractmethodclass PaymentStrategy(ABC):@abstractmethoddef process_payment(self, amount: float):passclass CreditCardPayment(PaymentStrategy):def process_payment(self, amount: float):print(f"Processing credit card payment of {amount}")class PayPalPayment(PaymentStrategy):def process_payment(self, amount: float):print(f"Processing PayPal payment of {amount}")class PaymentProcessor:def __init__(self, strategy: PaymentStrategy):self.strategy = strategydef process_payment(self, amount: float):self.strategy.process_payment(amount)# 使用示例
processor = PaymentProcessor(CreditCardPayment())
processor.process_payment(100)processor = PaymentProcessor(PayPalPayment())
processor.process_payment(200)

在这个改进的示例中,添加新的支付方式只需要实现PaymentStrategy接口,并且不需要修改PaymentProcessor类的代码,从而实现了开放封闭原则。

总结

开放封闭原则是面向对象设计中的重要原则之一,它通过鼓励扩展而不是修改已有代码来提高系统的可维护性和可扩展性。通过使用抽象类、接口、策略模式等设计模式,可以实现对扩展开放、对修改封闭的设计,提高代码的质量和设计水平。理解并应用开放封闭原则,有助于构建灵活、可扩展的软件系统。

4.依赖倒转原则

依赖倒转原则(Dependency Inversion Principle, DIP)是面向对象设计中的SOLID原则之一,旨在减少高层模块和低层模块之间的耦合,促进代码的可维护性和可扩展性。依赖倒转原则的核心思想是:

  • 高层模块不应该依赖于低层模块,两者都应该依赖于抽象。
  • 抽象不应该依赖于细节,细节应该依赖于抽象。

依赖倒转原则的定义

依赖倒转原则的主要目的是通过引入抽象层(如接口或抽象类)来使得高层模块和低层模块之间的依赖关系逆转,从而减少模块之间的耦合。

如何实现依赖倒转原则

  1. 使用接口或抽象类:定义抽象层,将高层模块和低层模块的依赖关系转移到抽象层上。
  2. 依赖注入:通过构造函数、属性或方法注入,将依赖的具体实现传递给高层模块,而不是在高层模块中直接创建依赖对象。

示例

假设我们有一个简单的应用程序,展示消息的内容。最初的设计中,高层模块直接依赖于低层模块。

违反依赖倒转原则的示例
class ConsoleLogger:def log(self, message: str):print(f"Logging to console: {message}")class Application:def __init__(self):self.logger = ConsoleLogger()  # 直接依赖具体实现def run(self):self.logger.log("Application has started.")# 使用示例
app = Application()
app.run()

在这个示例中,Application类直接依赖于具体的ConsoleLogger实现。如果我们想要改变日志记录方式(例如,记录到文件),就需要修改Application类,这违反了依赖倒转原则。

遵循依赖倒转原则的示例

通过引入抽象层和依赖注入,我们可以遵循依赖倒转原则。

from abc import ABC, abstractmethodclass Logger(ABC):@abstractmethoddef log(self, message: str):passclass ConsoleLogger(Logger):def log(self, message: str):print(f"Logging to console: {message}")class FileLogger(Logger):def __init__(self, file_path: str):self.file_path = file_pathdef log(self, message: str):with open(self.file_path, 'a') as f:f.write(f"Logging to file: {message}\n")class Application:def __init__(self, logger: Logger):self.logger = logger  # 依赖于抽象def run(self):self.logger.log("Application has started.")# 使用示例
console_logger = ConsoleLogger()
app = Application(console_logger)
app.run()file_logger = FileLogger("app.log")
app_with_file_logger = Application(file_logger)
app_with_file_logger.run()

在这个改进的示例中,我们通过引入Logger接口,使得Application类依赖于抽象而不是具体实现。同时,通过依赖注入的方式,将具体的ConsoleLoggerFileLogger实例传递给Application类,实现了依赖倒转原则。

依赖注入的方式

  1. 构造函数注入:通过构造函数传递依赖对象。
  2. 属性注入:通过设置对象属性传递依赖对象。
  3. 方法注入:通过方法参数传递依赖对象。
构造函数注入
class Application:def __init__(self, logger: Logger):self.logger = logger
属性注入
class Application:def set_logger(self, logger: Logger):self.logger = loggerapp = Application()
app.set_logger(ConsoleLogger())
方法注入
class Application:def run(self, logger: Logger):logger.log("Application has started.")app = Application()
app.run(ConsoleLogger())

依赖倒转原则的好处

  1. 降低耦合:高层模块和低层模块之间的依赖关系通过抽象层解耦,降低了系统的耦合度。
  2. 提高可维护性:通过依赖抽象,可以更容易地更改和扩展系统的功能,而不需要修改高层模块。
  3. 增强可测试性:可以更容易地替换依赖对象进行单元测试,提高代码的测试覆盖率和测试效果。

总结

依赖倒转原则是面向对象设计中的重要原则之一,通过引入抽象层和依赖注入,可以实现高层模块和低层模块的解耦,降低系统的耦合度,提高代码的可维护性和可扩展性。合理应用依赖倒转原则,可以显著提升软件系统的设计质量和代码的可靠性。

5.迪米特法则

迪米特法则(Law of Demeter, LoD),又称最少知识原则(Principle of Least Knowledge),是面向对象设计中的一个原则。该原则的核心思想是:

  • 一个对象应该对其他对象有最少的了解

定义

迪米特法则可以简单理解为:

  • 只与直接的朋友通信:一个对象只应该调用它直接持有的对象的方法,而不应该调用间接获取的对象的方法。

更具体地说,一个对象的方法只能调用以下几类对象的方法:

  1. 当前对象自身
  2. 方法参数
  3. 当前对象的属性
  4. 当前对象创建的对象
  5. 当前对象的全局变量(如果有)

为什么使用迪米特法则

迪米特法则通过限制对象之间的交互范围,减少了对象之间的耦合度,增加了系统的模块化和可维护性。遵循该原则可以带来以下好处:

  1. 降低耦合:减少对象之间的依赖,避免一个对象的变化影响到其他对象。
  2. 提高内聚:促使对象更多地依赖自己的内部状态和行为,提高类的内聚性。
  3. 增强可维护性:减少代码的复杂性,使得系统更容易理解和维护。

示例

违反迪米特法则的示例

下面的代码示例展示了一个违反迪米特法则的情况,一个对象通过多层调用访问其他对象的方法:

class Engine:def get_horsepower(self):return 200class Car:def __init__(self):self.engine = Engine()def get_engine(self):return self.engineclass Driver:def __init__(self):self.car = Car()def get_car_horsepower(self):return self.car.get_engine().get_horsepower()driver = Driver()
print(driver.get_car_horsepower())  # 输出:200

在这个示例中,Driver类通过car.get_engine().get_horsepower()多层调用来获取发动机的马力,这违反了迪米特法则。

遵循迪米特法则的示例

通过引入中介方法,我们可以减少对象之间的直接交互,从而遵循迪米特法则:

class Engine:def get_horsepower(self):return 200class Car:def __init__(self):self.engine = Engine()def get_engine_horsepower(self):return self.engine.get_horsepower()class Driver:def __init__(self):self.car = Car()def get_car_horsepower(self):return self.car.get_engine_horsepower()driver = Driver()
print(driver.get_car_horsepower())  # 输出:200

在这个改进的示例中,Car类增加了get_engine_horsepower方法,Driver类通过调用car.get_engine_horsepower()方法来获取马力,这样就避免了直接调用多层对象的方法。

迪米特法则的适用场景

  1. 复杂系统:在大型复杂系统中,遵循迪米特法则可以减少模块之间的耦合度,提高系统的可维护性和可扩展性。
  2. 高内聚性要求:当需要高内聚性和低耦合度的设计时,迪米特法则可以帮助实现这一目标。
  3. 敏感数据隔离:通过最少的了解原则,可以有效地隔离敏感数据,增强系统的安全性。

迪米特法则的注意事项

虽然迪米特法则有许多优点,但在实际应用中需要注意以下几点:

  1. 过度封装:过度应用迪米特法则可能导致过度封装,增加不必要的中介方法,反而降低了系统的效率和可读性。
  2. 合理平衡:在实践中,需要在遵循迪米特法则和保持系统简单性之间找到一个合理的平衡点。

总结

迪米特法则(最少知识原则)是面向对象设计中的一个重要原则,强调对象之间的低耦合和高内聚。通过限制对象之间的交互范围,迪米特法则可以提高系统的模块化、可维护性和可扩展性。在实际开发中,合理应用迪米特法则,可以显著提升代码质量和系统设计水平。

5.组合优于继承

“组合优于继承”(Composition over Inheritance)是面向对象设计中的一个重要原则。它提倡优先使用组合(Composition)来构建对象的行为,而不是通过继承(Inheritance)来扩展类的功能。这个原则可以帮助我们创建更加灵活和可维护的代码。

组合和继承的概念

  • 继承:继承是一个类(子类)从另一个类(父类)继承属性和方法,从而使得子类拥有父类的行为和状态。继承是一种“is-a”的关系。
  • 组合:组合是一个类包含另一个类的实例作为其成员变量,从而通过委托这些成员变量来获得新的行为和功能。组合是一种“has-a”的关系。

为什么组合优于继承

  1. 降低耦合:继承会在子类和父类之间产生强耦合,使得子类依赖于父类的实现细节。组合通过接口或成员变量进行组合,可以减少类之间的耦合。
  2. 提高灵活性:组合允许在运行时动态地改变行为,而继承只能在编译时确定。组合可以使用不同的组件来构建不同的对象行为。
  3. 遵循单一职责原则:通过组合,可以将不同的职责分配给不同的类,而继承可能会导致子类承担过多的职责。
  4. 更好的代码复用:组合可以复用现有的类,而无需修改类的内部实现。继承可能会导致代码重复和难以维护。
  5. 避免继承层次复杂性:继承层次过深会导致代码复杂性增加,而组合可以通过组合不同的组件来避免这种复杂性。

示例

以下是一个通过继承和组合实现相同功能的示例。

使用继承

假设我们有一个动物类,并希望通过继承实现不同的动物行为:

class Animal:def make_sound(self):passclass Dog(Animal):def make_sound(self):return "Woof!"class Cat(Animal):def make_sound(self):return "Meow!"
使用组合

通过组合,可以将行为抽象出来并进行组合:

class SoundBehavior:def make_sound(self):passclass Bark(SoundBehavior):def make_sound(self):return "Woof!"class Meow(SoundBehavior):def make_sound(self):return "Meow!"class Animal:def __init__(self, sound_behavior: SoundBehavior):self.sound_behavior = sound_behaviordef make_sound(self):return self.sound_behavior.make_sound()dog = Animal(Bark())
cat = Animal(Meow())print(dog.make_sound())  # 输出:Woof!
print(cat.make_sound())  # 输出:Meow!

在这个示例中,通过组合,我们可以在不修改Animal类的情况下,轻松添加新的行为。

组合优于继承的应用场景

  1. 动态行为改变:当需要在运行时动态地改变对象的行为时,组合比继承更加灵活。
  2. 避免继承层次复杂性:当继承层次过深,导致代码难以维护时,可以使用组合来简化设计。
  3. 代码复用和模块化:通过组合,可以将不同的功能模块化,并在多个类中复用这些模块。
  4. 遵循设计原则:组合有助于遵循单一职责原则和开闭原则,减少类之间的耦合。

总结

“组合优于继承”是面向对象设计中的一个重要原则,提倡优先使用组合来构建对象的行为,而不是通过继承来扩展类的功能。通过组合,可以降低类之间的耦合,提高代码的灵活性和可维护性。理解并应用这一原则,有助于在实际开发中构建高效、灵活、易维护的系统。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql锁表查看

命令 : show full processlist;//显示哪些线程正在运行

数字驱动,教育先行——低代码揭秘教育机构管理数字化转型

数字化时代为教育带来了许多变革和挑战,同时也为教育创新提供了无限可能。数字化转型可以帮助教育机构应对这些变革和挑战,提高教育效率和质量,满足学生个性化需求,优化教育管理和服务,并提高教育机构的竞争力。 并且…

docker 安装 yapi

文章目录 docker 安装 yapi一、拉取镜像二、创建目录三、添加配置文件四、初始化数据库表五、启动 yapi六、测试以及修改默认密码 没有 MongDB 的可以先看这个教程:MongDB安装教程 docker 安装 yapi 版本: 1.9.5 一、拉取镜像 docker pull yapipro/y…

以及Spring中为什么会出现IOC容器?@Autowired和@Resource注解?

以及Spring中为什么会出现IOC容器?Autowired和Resource注解? IOC容器发展史 没有IOC容器之前 首先说一下在Spring之前,我们的程序里面是没有IOC容器的,这个时候我们如果想要得到一个事先已经定义的对象该怎么得到呢?…

Flutter 中的 AnimatedSwitcher 小部件:全面指南

Flutter 中的 AnimatedSwitcher 小部件:全面指南 在 Flutter 中,动画是增强用户体验的重要工具。AnimatedSwitcher 是一个用于在两个 widget 之间执行平滑过渡动画的小部件。它可以自动处理两个状态之间的转换,提供丰富的动画效果。本文将详…

小白如何从零开始学新媒体运营三

最近有好多宝子私信问我是在哪里学习运营方面的相关知识的,那今天我就给大家整理了8个口碑较好的新媒体运营课程自学网站,帮大家快速入门新媒体运营. 1、考拉新媒体导航 实时热点、排版工具、运营干货、在线作图、高清图库、协作工具、数据平台&#xf…

三元组的最短距离

前言 个人小记 一、简介 定义三元组(a,b, c)(a,b,c 均为正数)的距离 D|a-b||b-c||c-a|。给定 3 个非空整数集合 S1, S2 ,S3, 按升序分别存储在 3 个数组中。请设计一个尽可能高效的算法,计算并输出所有可能的三元组&…

131. 面试中关于架构设计都需要了解哪些内容?

文章目录 一、社区系统架构组件概览1. 系统拆分2. CDN、Nginx静态缓存、JVM本地缓存3. Redis缓存4. MQ5. 分库分表6. 读写分离7. ElasticSearch 二、商城系统-亿级商品如何存储三、对账系统-分布式事务一致性四、统计系统-海量计数六、系统设计 - 微软1、需求收集2、顶层设计3、…

【Django】从零开始学Django(持续更新中)

PyCharm的版本必须为专业版,社区版不具备Web开发功能的。 一. Django建站基础 Django采用MTV的框架模式,即模型(Model)、模板(Template)和视图(Views),三者之间各自负责不同的职责。 ●模型:数据存取层,处理与数据相关…

【网络】cookie

cookie 的组成 cookie是浏览器中特有的一个概念,它就像浏览器的专属卡包,管理着各个网站的身份信息。 每个cookie就相当于是属于某个网站的一个卡片,它记录了下面的信息: key: 键,比如「身份编号」value: 值&#x…

vivado Miscellaneous Net-Related Constraints

Miscellaneous Net-Related Constraints KEEP Applied To Nets Constraint Values • TRUE • FALSE UCF Example net x_int KEEP TRUE; XDC Example set_property DONT_TOUCH true [get_nets x_int] SAVE NET FLAG Applied To Nets Constraint Values N/A …

Element-UI快速入门指南

一、引言 在前端开发领域,Vue.js以其简洁的API和灵活的组件系统受到了广泛的欢迎。Element-UI则是一套基于Vue.js 2.0的桌面端组件库,它提供了丰富的组件和友好的API,帮助开发者快速构建出美观且功能强大的Web应用。本文将带你快速入门Eleme…

信号:MSK调制和GMSK调制

目录 一、MSK信号 1. MSK信号的第k个码元 2.MSK信号的频率间隔 3.MSK信号的相位连续性 3.1 相位路径 3.2初始相位ψk 4.MSK信号的产生 原理框图 5.MSK信号的频谱图 二、高斯最小频移键控(GMSK) 1.频率响应 2.GMSK调制产生方式 2.1 高斯滤波器法 2.2 正交调制器法…

海外私人IP和原生IP有什么区别,谁更有优势?

一、什么是海外私人IP?什么是原生IP? 1、海外私人IP: 海外私人IP是由专门的服务提供商提供的IP地址,这些IP地址通常与特定地理位置或国家相关联。这些IP地址独享私人而不用与其他用户共享。海外私人IP广泛应用与跨境电商中&#x…

【Qt】修改QToolButton图标颜色

1. 目的 修改QToolButton的图标颜色,单一颜色,效果类似于Qt Creator左边选项卡。 2. 代码 QIcon MainWindow::setIconColor(QIcon icon, QColor color) {QPixmap pixmap icon.pixmap(QSize(64,64));QPainter painter(&pixmap);painter.setCompo…

DockerK8s

Docker&K8s 1. Docker 1.1 Docker是什么 用于构建容器化平台的软件,进程管理软件,主要用于部署应用程序并守护应用进程。容器是由docker软件启动的业务集成,该进程由docker全权管理。容器是进程,由内核机制来完成容器隔离。…

汇编:函数以及函数参数传递

汇编语言中的函数(或过程)是指一段可以被调用和执行的代码块;它们用于组织和重用代码,并使程序结构更加清晰;由于汇编语言没有高层次语言的语法糖,编写和调用函数涉及直接的堆栈操作和寄存器管理&#xff1…

c++网络开发笔记

1、第一节 1、阻塞模型 2、非阻塞IO 1)忙等待 2)IO复用模式(select,管理多个文件描述符号) 3)信号驱动IO,通过信号的方式 4)异步模型aio_read 3、select模型 int select(int nfds, fd_set *readfds, fd_set* writefds,fd_set* exceptfds, struct timeval* timeout);n…

Docker打包nginx镜像丢失挂载的配置文件

一般来说,Docker镜像构建过程中,如果没有正确地将配置文件复制到镜像中,那么在运行容器时就会丢失挂载的配置文件。 所以有2种解决办法: 第一种: 将挂载在宿主机上的配置文件复制到镜像中,可以参考这位老铁的文章《D…

多项式重构的平滑和法线估计-------PCL

多项式重构的平滑和法线估计 /// <summary> /// 多项式重构的平滑和法线估计 /// </summary> /// <param name"cloud"></param> /// <returns>输出一个包含平滑后的点云数据以及相应法线信息的数据结构</returns> pcl::PointCl…