零基础入门学习Python第二阶02面向对象,迭代器生成器,并发编程
Python语言进阶
面向对象相关知识
-
三大支柱:封装、继承、多态
例子:工资结算系统。
"""月薪结算系统 - 部门经理每月15000 程序员每小时200 销售员1800底薪加销售额5%提成"""from abc import ABCMeta, abstractmethodclass Employee(metaclass=ABCMeta):"""员工(抽象类)"""def __init__(self, name):self.name = name@abstractmethoddef get_salary(self):"""结算月薪(抽象方法)"""passclass Manager(Employee):"""部门经理"""def get_salary(self):return 15000.0class Programmer(Employee):"""程序员"""def __init__(self, name, working_hour=0):self.working_hour = working_hoursuper().__init__(name)def get_salary(self):return 200.0 * self.working_hourclass Salesman(Employee):"""销售员"""def __init__(self, name, sales=0.0):self.sales = salessuper().__init__(name)def get_salary(self):return 1800.0 + self.sales * 0.05class EmployeeFactory:"""创建员工的工厂(工厂模式 - 通过工厂实现对象使用者和对象之间的解耦合)"""@staticmethoddef create(emp_type, *args, **kwargs):"""创建员工"""all_emp_types = {'M': Manager, 'P': Programmer, 'S': Salesman}cls = all_emp_types[emp_type.upper()]return cls(*args, **kwargs) if cls else Nonedef main():"""主函数"""emps = [EmployeeFactory.create('M', '曹操'), EmployeeFactory.create('P', '荀彧', 120),EmployeeFactory.create('P', '郭嘉', 85), EmployeeFactory.create('S', '典韦', 123000),]for emp in emps:print(f'{emp.name}: {emp.get_salary():.2f}元')if __name__ == '__main__':main()
-
类与类之间的关系
- is-a关系:继承
- has-a关系:关联 / 聚合 / 合成
- use-a关系:依赖
例子:扑克游戏。
"""经验:符号常量总是优于字面常量,枚举类型是定义符号常量的最佳选择"""from enum import Enum, uniqueimport random@uniqueclass Suite(Enum):"""花色"""SPADE, HEART, CLUB, DIAMOND = range(4)def __lt__(self, other):return self.value < other.valueclass Card:"""牌"""def __init__(self, suite, face):"""初始化方法"""self.suite = suiteself.face = facedef show(self):"""显示牌面"""suites = ['♠︎', '♥︎', '♣︎', '♦︎']faces = ['', 'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']return f'{suites[self.suite.value]}{faces[self.face]}'def __repr__(self):return self.show()class Poker:"""扑克"""def __init__(self):self.index = 0self.cards = [Card(suite, face)for suite in Suitefor face in range(1, 14)]def shuffle(self):"""洗牌(随机乱序)"""random.shuffle(self.cards)self.index = 0def deal(self):"""发牌"""card = self.cards[self.index]self.index += 1return card@propertydef has_more(self):return self.index < len(self.cards)class Player:"""玩家"""def __init__(self, name):self.name = nameself.cards = []def get_one(self, card):"""摸一张牌"""self.cards.append(card)def sort(self, comp=lambda card: (card.suite, card.face)):"""整理手上的牌"""self.cards.sort(key=comp)def main():"""主函数"""poker = Poker()poker.shuffle()players = [Player('东邪'), Player('西毒'), Player('南帝'), Player('北丐')]while poker.has_more:for player in players:player.get_one(poker.deal())for player in players:player.sort()print(player.name, end=': ')print(player.cards)if __name__ == '__main__':main()
说明:上面的代码中使用了Emoji字符来表示扑克牌的四种花色,在某些不支持Emoji字符的系统上可能无法显示。
-
对象的复制(深复制/深拷贝/深度克隆和浅复制/浅拷贝/影子克隆)
-
垃圾回收、循环引用和弱引用
Python使用了自动化内存管理,这种管理机制以引用计数为基础,同时也引入了标记-清除和分代收集两种机制为辅的策略。
typedef struct _object {/* 引用计数 */int ob_refcnt;/* 对象指针 */struct _typeobject *ob_type; } PyObject;
/* 增加引用计数的宏定义 */ #define Py_INCREF(op) ((op)->ob_refcnt++) /* 减少引用计数的宏定义 */ #define Py_DECREF(op) \ //减少计数if (--(op)->ob_refcnt != 0) \; \else \__Py_Dealloc((PyObject *)(op))
导致引用计数+1的情况:
- 对象被创建,例如
a = 23
- 对象被引用,例如
b = a
- 对象被作为参数,传入到一个函数中,例如
f(a)
- 对象作为一个元素,存储在容器中,例如
list1 = [a, a]
导致引用计数-1的情况:
- 对象的别名被显式销毁,例如
del a
- 对象的别名被赋予新的对象,例如
a = 24
- 一个对象离开它的作用域,例如f函数执行完毕时,f函数中的局部变量(全局变量不会)
- 对象所在的容器被销毁,或从容器中删除对象
引用计数可能会导致循环引用问题,而循环引用会导致内存泄露,如下面的代码所示。为了解决这个问题,Python中引入了“标记-清除”和“分代收集”。在创建一个对象的时候,对象被放在第一代中,如果在第一代的垃圾检查中对象存活了下来,该对象就会被放到第二代中,同理在第二代的垃圾检查中对象存活下来,该对象就会被放到第三代中。
# 循环引用会导致内存泄露 - Python除了引用技术还引入了标记清理和分代回收 # 在Python 3.6以前如果重写__del__魔术方法会导致循环引用处理失效 # 如果不想造成循环引用可以使用弱引用 list1 = [] list2 = [] list1.append(list2) list2.append(list1)
以下情况会导致垃圾回收:
- 调用
gc.collect()
gc
模块的计数器达到阀值- 程序退出
如果循环引用中两个对象都定义了
__del__
方法,gc
模块不会销毁这些不可达对象,因为gc模块不知道应该先调用哪个对象的__del__
方法,这个问题在Python 3.6中得到了解决。也可以通过
weakref
模块构造弱引用的方式来解决循环引用的问题。 - 对象被创建,例如
-
魔法属性和方法(请参考《Python魔法方法指南》)
有几个小问题请大家思考:
- 自定义的对象能不能使用运算符做运算?
- 自定义的对象能不能放到
set
中?能去重吗? - 自定义的对象能不能作为
dict
的键? - 自定义的对象能不能使用上下文语法?
-
混入(Mixin)
例子:自定义字典限制只有在指定的key不存在时才能在字典中设置键值对。
```Pythonclass SetOnceMappingMixin:"""自定义混入类"""__slots__ = ()def __setitem__(self, key, value):if key in self:raise KeyError(str(key) + ' already set')return super().__setitem__(key, value)class SetOnceDict(SetOnceMappingMixin, dict):"""自定义字典"""passmy_dict= SetOnceDict()try:my_dict['username'] = 'jackfrued'my_dict['username'] = 'hellokitty'except KeyError:passprint(my_dict)
-
元编程和元类
对象是通过类创建的,类是通过元类创建的,元类提供了创建类的元信息。所有的类都直接或间接的继承自
object
,所有的元类都直接或间接的继承自type
。例子:用元类实现单例模式。
import threadingclass SingletonMeta(type):"""自定义元类"""def __init__(cls, *args, **kwargs):cls.__instance = Nonecls.__lock = threading.RLock()super().__init__(*args, **kwargs)def __call__(cls, *args, **kwargs):if cls.__instance is None:with cls.__lock:if cls.__instance is None:cls.__instance = super().__call__(*args, **kwargs)return cls.__instanceclass President(metaclass=SingletonMeta):"""总统(单例类)"""pass
-
面向对象设计原则
- 单一职责原则 (SRP)- 一个类只做该做的事情(类的设计要高内聚)
- 开闭原则 (OCP)- 软件实体应该对扩展开发对修改关闭
- 依赖倒转原则(DIP)- 面向抽象编程(在弱类型语言中已经被弱化)
- 里氏替换原则(LSP) - 任何时候可以用子类对象替换掉父类对象
- 接口隔离原则(ISP)- 接口要小而专不要大而全(Python中没有接口的概念)
- 合成聚合复用原则(CARP) - 优先使用强关联关系而不是继承关系复用代码
- 最少知识原则(迪米特法则,LoD)- 不要给没有必然联系的对象发消息
说明:上面加粗的字母放在一起称为面向对象的SOLID原则。
-
GoF设计模式
- 创建型模式:单例、工厂、建造者、原型
- 结构型模式:适配器、门面(外观)、代理
- 行为型模式:迭代器、观察者、状态、策略
例子:可插拔的哈希算法(策略模式)。
class StreamHasher():"""哈希摘要生成器"""def __init__(self, alg='md5', size=4096):self.size = sizealg = alg.lower()self.hasher = getattr(__import__('hashlib'), alg.lower())()def __call__(self, stream):return self.to_digest(stream)def to_digest(self, stream):"""生成十六进制形式的摘要"""for buf in iter(lambda: stream.read(self.size), b''):self.hasher.update(buf)return self.hasher.hexdigest()def main():"""主函数"""hasher1 = StreamHasher()with open('Python-3.7.6.tgz', 'rb') as stream:print(hasher1.to_digest(stream))hasher2 = StreamHasher('sha1')with open('Python-3.7.6.tgz', 'rb') as stream:print(hasher2(stream))if __name__ == '__main__':main()
迭代器和生成器
-
迭代器是实现了迭代器协议的对象。
- Python中没有像
protocol
或interface
这样的定义协议的关键字。 - Python中用魔术方法表示协议。
__iter__
和__next__
魔术方法就是迭代器协议。
- Python中没有像
class Fib(object):"""迭代器"""def __init__(self, num):self.num = numself.a, self.b = 0, 1self.idx = 0def __iter__(self):return selfdef __next__(self):if self.idx < self.num:self.a, self.b = self.b, self.a + self.bself.idx += 1return self.araise StopIteration()
- 生成器是语法简化版的迭代器。
def fib(num):"""生成器"""a, b = 0, 1for _ in range(num):a, b = b, a + byield a
-
生成器进化为协程。
生成器对象可以使用
send()
方法发送数据,发送的数据会成为生成器函数中通过yield
表达式获得的值。这样,生成器就可以作为协程使用,协程简单的说就是可以相互协作的子程序。
def calc_avg():"""流式计算平均值"""total, counter = 0, 0avg_value = Nonewhile True:value = yield avg_valuetotal, counter = total + value, counter + 1avg_value = total / countergen = calc_avg()next(gen)print(gen.send(10))print(gen.send(20))print(gen.send(30))
并发编程
Python中实现并发编程的三种方案:多线程、多进程和异步I/O。并发编程的好处在于可以提升程序的执行效率以及改善用户体验;坏处在于并发的程序不容易开发和调试,同时对其他程序来说它并不友好。
- 多线程:Python中提供了
Thread
类并辅以Lock
、Condition
、Event
、Semaphore
和Barrier
。Python中有GIL来防止多个线程同时执行本地字节码,这个锁对于CPython是必须的,因为CPython的内存管理并不是线程安全的,因为GIL的存在多线程并不能发挥CPU的多核特性。
"""面试题:进程和线程的区别和联系?进程 - 操作系统分配内存的基本单位 - 一个进程可以包含一个或多个线程线程 - 操作系统分配CPU的基本单位并发编程(concurrent programming)1. 提升执行性能 - 让程序中没有因果关系的部分可以并发的执行2. 改善用户体验 - 让耗时间的操作不会造成程序的假死"""import globimport osimport threadingfrom PIL import ImagePREFIX = 'thumbnails'def generate_thumbnail(infile, size, format='PNG'):"""生成指定图片文件的缩略图"""file, ext = os.path.splitext(infile)file = file[file.rfind('/') + 1:]outfile = f'{PREFIX}/{file}_{size[0]}_{size[1]}.{ext}'img = Image.open(infile)img.thumbnail(size, Image.ANTIALIAS)img.save(outfile, format)def main():"""主函数"""if not os.path.exists(PREFIX):os.mkdir(PREFIX)for infile in glob.glob('images/*.png'):for size in (32, 64, 128):# 创建并启动线程threading.Thread(target=generate_thumbnail, args=(infile, (size, size))).start()if __name__ == '__main__':main()
多个线程竞争资源的情况。
"""多线程程序如果没有竞争资源处理起来通常也比较简单当多个线程竞争临界资源的时候如果缺乏必要的保护措施就会导致数据错乱说明:临界资源就是被多个线程竞争的资源"""import timeimport threadingfrom concurrent.futures import ThreadPoolExecutorclass Account(object):"""银行账户"""def __init__(self):self.balance = 0.0self.lock = threading.Lock()def deposit(self, money):# 通过锁保护临界资源with self.lock:new_balance = self.balance + moneytime.sleep(0.001)self.balance = new_balancedef main():"""主函数"""account = Account()# 创建线程池pool = ThreadPoolExecutor(max_workers=10)futures = []for _ in range(100):future = pool.submit(account.deposit, 1)futures.append(future)# 关闭线程池pool.shutdown()for future in futures:future.result()print(account.balance)if __name__ == '__main__':main()
修改上面的程序,启动5个线程向账户中存钱,5个线程从账户中取钱,取钱时如果余额不足就暂停线程进行等待。为了达到上述目标,需要对存钱和取钱的线程进行调度,在余额不足时取钱的线程暂停并释放锁,而存钱的线程将钱存入后要通知取钱的线程,使其从暂停状态被唤醒。可以使用threading
模块的Condition
来实现线程调度,该对象也是基于锁来创建的,代码如下所示:
"""多个线程竞争一个资源 - 保护临界资源 - 锁(Lock/RLock)多个线程竞争多个资源(线程数>资源数) - 信号量(Semaphore)多个线程的调度 - 暂停线程执行/唤醒等待中的线程 - Condition"""from concurrent.futures import ThreadPoolExecutorfrom random import randintfrom time import sleepimport threadingclass Account:"""银行账户"""def __init__(self, balance=0):self.balance = balancelock = threading.RLock()self.condition = threading.Condition(lock)def withdraw(self, money):"""取钱"""with self.condition:while money > self.balance:self.condition.wait()new_balance = self.balance - moneysleep(0.001)self.balance = new_balancedef deposit(self, money):"""存钱"""with self.condition:new_balance = self.balance + moneysleep(0.001)self.balance = new_balanceself.condition.notify_all()def add_money(account):while True:money = randint(5, 10)account.deposit(money)print(threading.current_thread().name, ':', money, '====>', account.balance)sleep(0.5)def sub_money(account):while True:money = randint(10, 30)account.withdraw(money)print(threading.current_thread().name, ':', money, '<====', account.balance)sleep(1)def main():account = Account()with ThreadPoolExecutor(max_workers=15) as pool:for _ in range(5):pool.submit(add_money, account)for _ in range(10):pool.submit(sub_money, account)if __name__ == '__main__':main()
- 多进程:多进程可以有效的解决GIL的问题,实现多进程主要的类是
Process
,其他辅助的类跟threading
模块中的类似,进程间共享数据可以使用管道、套接字等,在multiprocessing
模块中有一个Queue
类,它基于管道和锁机制提供了多个进程共享的队列。下面是官方文档上关于多进程和进程池的一个示例。
"""多进程和进程池的使用多线程因为GIL的存在不能够发挥CPU的多核特性对于计算密集型任务应该考虑使用多进程time python3 example22.pyreal 0m11.512suser 0m39.319ssys 0m0.169s使用多进程后实际执行时间为11.512秒,而用户时间39.319秒约为实际执行时间的4倍这就证明我们的程序通过多进程使用了CPU的多核特性,而且这台计算机配置了4核的CPU"""import concurrent.futuresimport mathPRIMES = [1116281,1297337,104395303,472882027,533000389,817504243,982451653,112272535095293,112582705942171,112272535095293,115280095190773,115797848077099,1099726899285419] * 5def is_prime(n):"""判断素数"""if n % 2 == 0:return Falsesqrt_n = int(math.floor(math.sqrt(n)))for i in range(3, sqrt_n + 1, 2):if n % i == 0:return Falsereturn Truedef main():"""主函数"""with concurrent.futures.ProcessPoolExecutor() as executor:for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):print('%d is prime: %s' % (number, prime))if __name__ == '__main__':main()
重点:多线程和多进程的比较。
以下情况需要使用多线程:
- 程序需要维护许多共享的状态(尤其是可变状态),Python中的列表、字典、集合都是线程安全的,所以使用线程而不是进程维护共享状态的代价相对较小。
- 程序会花费大量时间在I/O操作上,没有太多并行计算的需求且不需占用太多的内存。
以下情况需要使用多进程:
- 程序执行计算密集型任务(如:字节码操作、数据处理、科学计算)。
- 程序的输入可以并行的分成块,并且可以将运算结果合并。
- 程序在内存使用方面没有任何限制且不强依赖于I/O操作(如:读写文件、套接字等)。
- 异步处理:从调度程序的任务队列中挑选任务,该调度程序以交叉的形式执行这些任务,我们并不能保证任务将以某种顺序去执行,因为执行顺序取决于队列中的一项任务是否愿意将CPU处理时间让位给另一项任务。异步任务通常通过多任务协作处理的方式来实现,由于执行时间和顺序的不确定,因此需要通过回调式编程或者
future
对象来获取任务执行的结果。Python 3通过asyncio
模块和await
和async
关键字(在Python 3.7中正式被列为关键字)来支持异步处理。
"""异步I/O - async / await"""import asynciodef num_generator(m, n):"""指定范围的数字生成器"""yield from range(m, n + 1)async def prime_filter(m, n):"""素数过滤器"""primes = []for i in num_generator(m, n):flag = Truefor j in range(2, int(i ** 0.5 + 1)):if i % j == 0:flag = Falsebreakif flag:print('Prime =>', i)primes.append(i)await asyncio.sleep(0.001)return tuple(primes)async def square_mapper(m, n):"""平方映射器"""squares = []for i in num_generator(m, n):print('Square =>', i * i)squares.append(i * i)await asyncio.sleep(0.001)return squaresdef main():"""主函数"""loop = asyncio.get_event_loop()future = asyncio.gather(prime_filter(2, 100), square_mapper(1, 100))future.add_done_callback(lambda x: print(x.result()))loop.run_until_complete(future)loop.close()if __name__ == '__main__':main()
说明:上面的代码使用
get_event_loop
函数获得系统默认的事件循环,通过gather
函数可以获得一个future
对象,future
对象的add_done_callback
可以添加执行完成时的回调函数,loop
对象的run_until_complete
方法可以等待通过future
对象获得协程执行结果。
Python中有一个名为aiohttp
的三方库,它提供了异步的HTTP客户端和服务器,这个三方库可以跟asyncio
模块一起工作,并提供了对Future
对象的支持。Python 3.6中引入了async
和await
来定义异步执行的函数以及创建异步上下文,在Python 3.7中它们正式成为了关键字。下面的代码异步的从5个URL中获取页面并通过正则表达式的命名捕获组提取了网站的标题。
import asyncioimport reimport aiohttpPATTERN = re.compile(r'\<title\>(?P<title>.*)\<\/title\>')async def fetch_page(session, url):async with session.get(url, ssl=False) as resp:return await resp.text()async def show_title(url):async with aiohttp.ClientSession() as session:html = await fetch_page(session, url)print(PATTERN.search(html).group('title'))def main():urls = ('https://www.python.org/','https://git-scm.com/','https://www.jd.com/','https://www.taobao.com/','https://www.douban.com/')loop = asyncio.get_event_loop()cos = [show_title(url) for url in urls]loop.run_until_complete(asyncio.wait(cos))loop.close()if __name__ == '__main__':main()
重点:异步I/O与多进程的比较。
当程序不需要真正的并发性或并行性,而是更多的依赖于异步处理和回调时,
asyncio
就是一种很好的选择。如果程序中有大量的等待与休眠时,也应该考虑asyncio
,它很适合编写没有实时数据处理需求的Web应用服务器。
Python还有很多用于处理并行任务的三方库,例如:joblib
、PyMP
等。实际开发中,要提升系统的可扩展性和并发性通常有垂直扩展(增加单个节点的处理能力)和水平扩展(将单个节点变成多个节点)两种做法。可以通过消息队列来实现应用程序的解耦合,消息队列相当于是多线程同步队列的扩展版本,不同机器上的应用程序相当于就是线程,而共享的分布式消息队列就是原来程序中的Queue。消息队列(面向消息的中间件)的最流行和最标准化的实现是AMQP(高级消息队列协议),AMQP源于金融行业,提供了排队、路由、可靠传输、安全等功能,最著名的实现包括:Apache的ActiveMQ、RabbitMQ等。
要实现任务的异步化,可以使用名为Celery
的三方库。Celery
是Python编写的分布式任务队列,它使用分布式消息进行工作,可以基于RabbitMQ或Redis来作为后端的消息代理。
相关文章:
零基础入门学习Python第二阶02面向对象,迭代器生成器,并发编程
Python语言进阶 面向对象相关知识 三大支柱:封装、继承、多态 例子:工资结算系统。 """月薪结算系统 - 部门经理每月15000 程序员每小时200 销售员1800底薪加销售额5%提成"""from abc import ABCMeta, abstractmethodcl…...
Unity | Shader基础知识(第十三集:编写内置着色器阶段总结和表面着色器的补充介绍)
目录 前言 一、表面着色器的补充介绍 二、案例viewDir详解 1.viewDir是什么 2.viewDir的作用 3.使用viewDir写shader 前言 注意观察的小伙伴会发现,这组教程前半部分我们在编写着色器的时候,用的是顶点着色器和片元着色器的组合。 SubShader{CGPRO…...
JavaScript map对象/set对象详解
文章目录 一、map对象二、map对象应用场景1. 数组元素转换2. 对象数组的属性提取或转换3. 数组元素的复杂转换4. 与其他数组方法结合使用5. 与异步操作结合(使用 Promise)6. 生成新的数据结构7. 数学和统计计算 三、set对象1. 基本使用2. 特性3. 注意事项…...
【kettle017】kettle访问DB2数据库并处理数据至execl文件(最近完善中)
1.一直以来想写下基于kettle的系列文章,作为较火的数据ETL工具,也是日常项目开发中常用的一款工具,最近刚好挤时间梳理、总结下这块儿的知识体系。 2.熟悉、梳理、总结下DB2数据库(IBM公司开发的一套关系型数据库管理系统…...
Spring Cloud原理详解和作用特点
当涉及到构建和管理分布式系统的微服务架构时,Spring Cloud 是一个备受欢迎的选择。它提供了一套强大的工具和组件,使开发者能够轻松地构建、部署和管理微服务应用程序。本文将深入探讨 Spring Cloud 的原理和作用特点。 1. Spring Cloud 的原理 Sprin…...
Linux —— 进程间通信
目录 一、进程间通信的介绍二、管道三、匿名管道四、命名管道五、system V进程间通信 一、进程间通信的介绍 1.进程间通信的概念 进程通信(Interprocess communication),简称:IPC; 本来进程之间是相互独立的。但是…...
ASP.NET信息安全研究所设备管理系统的设计与实现
摘 要 以研究所的设备管理系统为背景,以研究所设备管理模式为研究对象,开发了设备管理系统。设备管理系统是设备管理与计算机技术相结合的产物,根据系统的功能需求分析与定义的数据模式,分析了应用程序的主要功能和系统实现的主…...
<网络安全>《81 微课堂<安全产品微简介(1)>》
1 简单的了解复杂的安全产品 产品简要防火墙网络区域边界上部署,主要作用是隔离阻断。安全审计一般包括网络日志的分析、网络流量的监控和用户行为的跟踪等。发现网络中的潜在问题和漏洞。入侵检测IDS实时监控和检测网络中的异常活动和入侵行为。入侵防御IPS防病毒…...
【6D位姿估计】FoundationPose 跑通demo 训练记录
前言 本文记录在FoundationPose中,跑通基于CAD模型为输入的demo,输出位姿信息,可视化结果。 然后分享NeRF物体重建部分的训练,以及RGBD图为输入的demo。 1、搭建环境 方案1:基于docker镜像(推荐…...
Python 中 “yield“ 的不同行为
在我们使用Python编译过程中,yield 关键字用于定义生成器函数,它的作用是将函数变成一个生成器,可以迭代产生值。yield 的行为在不同的情况下会有不同的效果和用途。 1、问题背景 在 Python 中,“yield” 是一种生成器࿰…...
迅睿CMS中实现关键词搜索高亮
在迅睿CMS系统中实现关键词搜索高亮是提升用户体验和搜索效果的重要手段。当用户搜索某个关键词时,将搜索结果中的关键词高亮显示,可以帮助用户更快速地定位到所需信息。 关键词高亮的实现 在迅睿CMS中,你可以使用内置的dr_keyword_highlig…...
晶振的精度与稳定性有什么关系?
晶振的精度和稳定性是电子设备中非常重要的参数,它们受到多种因素的影响,主要包括: 精度的影响因素: 温度变化:晶体的温度系数会使得频率随温度变化而变化,通常在0C到55C的工业标准温度范围内,…...
【C】137 只出现一次的数字
给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。 解法一 #include <stdio.h>int singleNumber(i…...
51单片机入门:DS1302时钟
51单片机内部含有晶振,可以实现定时/计数功能。但是其缺点有:精度往往不高、不能掉电使用等。 我们可以通过DS1302时钟芯片来解决以上的缺点。 DS1302时钟芯片 功能:DS1302是一种低功耗实时时钟芯片,内部有自动的计时功能&#x…...
Redis-5 分布式锁
一.为什么要使用分布式锁? 传统的互斥锁synchronized只能作用于同一台虚拟机上的线程,在使用服务器集群部署的情况下,互斥锁就会失效,因此要采用分布式锁来处理不同服务器上的线程访问同一资源的情况。 二.redis的分布式锁是如何…...
音转文工具,9.8k star! 【送源码】
我们经常会遇到将音频转为文字的情况,比如在开会时录音的会议纪要、上课时录下的老师讲课内容。虽然网上也有一些在线的工具可以将音频转为文字,但是考虑到数据安全和费用问题,使用起来也不是很方便。 今天了不起给大家介绍一款开源工具——…...
【首次发布】华为 OD 机试 C卷抽中题库清单(真题库),目前华为OD机考以C卷为主,特殊情况会发送D卷
本篇博客为大家整理华为 OD 考友反馈 C 卷抽中题,经过 1 个的考友复盘,目前已经收录 100 题目,预计在有 2 周可以收集完整。 所有题目,都有考友截图反馈,同时欢迎大家机考过后,提供橡皮擦真题,获…...
【进程等待】waitpid的参数pid | status的位图位操作WIFEXITEDWEXITSTATUS宏
目录 waitpid pid status status位图 status按位操作 输入型参数和输入型参数 宏WIFEXITED&WEXITSTATUS options&非阻塞等待 上篇进程等待我们介绍到怎样去进程等待。我们介绍了wait函数&阻塞等待。本篇我们将介绍waitpid函数的参数pid和status。 waitp…...
unity---常用API
1. Vector3:结构体由x、y、z这3个数值组成,表示一个向量 magnitude变量返回该向量的长度normalized变量返回 magnitude 为 1 时的该向量zero静态变量Vector3(0, 0, 0)one静态变量Vector3(1, 1, 1)forward静态变量Vector3(0, 0, 1)back静态变量Vector3(0…...
设计模式: 模板模式
目录 一,模板模式 二,特点 三,组成部分 四,实现步骤 五,案例 一,模板模式 模板模式(Template Pattern)是一种行为型设计模式,它在超类中定义了一个算法的骨架&#…...
[虚拟机+单机]梦幻契约H5修复版_附GM工具
本教程仅限学习使用,禁止商用,一切后果与本人无关,此声明具有法律效应!!!! 教程是本人亲自搭建成功的,绝对是完整可运行的,踩过的坑都给你们填上了 视频演示 [虚拟机单…...
头文件相互包含 前向声明
当两个类需要相互访问对方的成员或方法时,通常意味着它们之间存在某种依赖关系。这种依赖关系可能源于类的设计或功能需求。以下是一个简单的例子,展示了当两个类需要相互访问对方成员或方法时,如何使用包含对方头文件的方式来解决循环包含的…...
七款好用的上网行为管理软件推荐 |有没有好用的上网行为管理系统
七款好用的上网行为管理软件推荐 |有没有好用的上网行为管理系统 员工上班刷视频! 员工上班炒股! 员工上班干副业! 碰见这种情况怎么办?当然是用电脑监控软件来监视员工的一举一动了,那么这样的软件有哪些呢&#…...
centos7-bcc 安装
检查 内核信息 确保安装的kernel-dev 和内核版本一致!!! rpm -qa|grep kernel kernel-tools-3.10.0-1160.92.1.el7.x86_64 kernel-devel-3.10.0-1160.92.1.el7.x86_64 kernel-headers-3.10.0-1160.92.1.el7.x86_64 kernel-3.10.0-1160.92.1.el7.x86_64 kernel-tools-libs-3.1…...
5.06号模拟前端面试8问
5.06号模拟前端面试8问 1.promise如何实现then处理 在JavaScript中,Promise 是一个代表异步操作最终完成或失败的对象。它有三种状态:pending(等待),fulfilled(完成),rejected&…...
解读Inscode AI:开启代码智能化的新时代
导语: 近年来,人工智能技术的迅猛发展已经深刻地影响着各个行业,而在软件开发领域,Inscode AI的出现无疑将给代码智能化带来一场革命。本文将为大家解读Inscode AI的特点和应用,探索其如何改变我们的软件开发方式。 一…...
快速了解Vuex
Vuex Vuex使用Vuex Vuex 📌vuex 是一个专为 Vue.js 应用程序开发的状态管理库 📌vuex 可以在多个组件之间共享数据,并且共享的数据是响应式的,即数据的变更能及时渲染到模板 📌vuex 采用集中式存储管理所有组件的状态…...
vue管理系统导航中添加新的iconfont的图标
1.在官网上将需要的图标,加入项目中,下载 2.下载的压缩包中,可以选择这两个,复制到项目目录中 3.如果和之前的iconfont有重复,那么就重新命名 4.将这里的.ttf文件,也重命名为自己的 5.在main文件中导入 6.在…...
Docker的介绍及与传统虚拟化技术的区别
Docker是一个开源的应用容器引擎,它使得开发者可以将应用及其依赖包打包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上。Docker基于Go语言开发,它的出现极大地简化了应用程序的部署、管理和扩展。 以下是Docker…...
06.Git远程仓库
Git远程仓库 #仓库种类,举例说明 github gitlab gitee #以这个仓库为例子操作登录码云 https://gitee.com/projects/new 创建仓库 选择ssh方式 需要配置ssh公钥 在系统上获取公钥输入命令:ssh-keygen 查看文件,复制公钥信息内…...
php工具箱是直接做网站的吗/郴州网站seo外包
综合实验 实验要求: 1、添加vlan10,vlan20,vlan30,vlan40,SW1与SW2之间做以太网通道,与交换机SW3、4、5、6之间做trunk链路。 2、vpcs1分配vlan10,真机分配vlan20,vpcs2分配vlan30&a…...
做网站需要的图片去哪找/网络营销怎么做
默认安装完毕wordpress后,需要完善的地方很有很多,首选就是选择一个符合网站风格的模版,面对众多免费worpress模版,肯定会挑花了你眼。这真是worpress强大之初,所有你想到或没想到的,wp团队都为你想到和做到…...
使用循环视频做背景的网站/seo网络推广课程
参考:List of HTTP header fields 翻译 标准要求字段 字段名说明例子状态A-IM可接受实例操作的请求A-IM: feed永久的Accept对于响应来说是(/是)可接受的媒体类型。看到内容协商。Accept: text/html永久的Accept-Charset可接受的字符集。Accept-Charset: utf-8永久的…...
安卓app开发实验报告/seo优化技术招聘
偶然得知中国有一种火星坐标系统。其原理是这样的:保密局开发了一个系统,能将实际的坐标转换成虚拟的坐标。所有在中国销售的数字地图必须使用这个系统进行坐标转换之后方可上市。这是生产环节,这种电子地图被称为火星地图。在使用环节&#…...
北京网站首页排名公司/企业培训课程
心态炸裂 昨晚忙活到半夜照着攻略,一顿操作,中间虽然有几个小错误还都纠正过来了,成功搭建好了博客。结果今天下午想着去给博客换个好点的theme,结果照着一顿操作,各种报错,关键是我也不懂也找不到如何解决…...
展厅设计案例100例/全国最好网络优化公司
ARM开发经典学习网站推荐 1. EG3 关于嵌入式开发的站点,提供非常多关于嵌入式开发的资料。包括开发公司,技术文档,免费资源等等。版面包括busses & boards,embedded software,dsp,embedded systems,opensource,rtos,embedded chips,system-on-a-chip 等等。 强烈推荐…...