做一个精通Python规则的玩家

前言

本文转自“Python工匠”,也非常感谢“Python猫”的极力推荐,感兴趣的同学可以关注一下这两个公众号。之所以会post出这篇文章,因为它不仅能够让我们学习成为在Python世界里的骨灰级玩家,还能让我们在工作生活中获益匪浅。

说到底,语言不仅是一个工具箱,而我们这些使用者,更不应是流水线上的站桩工人。

编程,其实和玩电子游戏有一些相似之处。你在玩不同游戏前,需要先学习每个游戏的不同规则,只有熟悉和灵活运用游戏规则,才更有可能在游戏中获胜。

而编程也一样,不同编程语言同样有着不一样的“规则”。大到是否支持面向对象,小到是否可以定义常量,编程语言的规则比绝大多数电子游戏要复杂的多

当我们编程时,如果直接拿一种语言的经验套用到另外一种语言上,很多时候并不能取得最佳结果。这就好像一个 CS(反恐精英) 高手在不了解规则的情况下去玩 PUBG(绝地求生),虽然他的枪法可能万中无一,但是极有可能在发现第一个敌人前,他就会倒在某个窝在草丛里的敌人的伏击下。

正文

Python里的规则

Python 是一门初见简单、深入后愈觉复杂的语言。拿 Python 里最重要的“对象”概念来说,Python 为其定义了多到让你记不全的规则,比如:

  • 定义了 __str__ 方法的对象,就可以使用 str() 函数来返回可读名称;

  • 定义了 __next____iter__ 方法的对象,就可以被循环迭代;

  • 定义了 __bool__ 方法的对象,在进行布尔判断时就会使用自定义的逻辑;

  • … …

熟悉规则,并让自己的代码适应这些规则,可以帮助我们写出更地道的代码,事半功倍的完成工作。下面,让我们来看一个有关适应规则的故事。

案例:从两份旅游数据中获取人员名单

某日,在一个主打新西兰出境游的旅游公司里,商务同事突然兴冲冲的跑过来找到我,说他从某合作伙伴那里,要到了两份重要的数据:

  1. 所有去过“泰国普吉岛”的人员及联系方式

  2. 所有去过“新西兰”的人员及联系方式

数据采用了 JSON 格式,如下所示:

# 去过普吉岛的人员数据

users_visited_puket = [
	{"first_name": "Sirena", "last_name": "Gross", "phone_number": "650-568-0388", "date_visited": "2018-03-14"},
	{"first_name": "James", "last_name": "Ashcraft", "phone_number": "412-334-4380", "date_visited": "2014-09-16"},
   ... ...
]

# 去过新西兰的人员数据

users_visited_nz = [
	{"first_name": "Justin", "last_name": "Malcom", "phone_number": "267-282-1964", "date_visited": "2011-03-13"},
	{"first_name": "Albert", "last_name": "Potter", "phone_number": "702-249-3714", "date_visited": "2013-09-11"},
	... ...
]  

每份数据里面都有着 姓、 名、 手机号码、 旅游时间 四个字段。基于这份数据,商务同学提出了一个(听上去毫无道理)的假设:“去过普吉岛的人,应该对去新西兰旅游也很有兴趣。我们需要从这份数据里,找出那些去过普吉岛但没有去过新西兰的人,针对性的卖产品给他们(实际上是对潜在客户推送可能感兴趣的产品)。

简单的尝试

有了原始数据和明确的需求,接下来的问题就是如何写代码了。依靠直觉,我很快就写出了第一个方案:

def find_potential_customers_v1():
	"""
	找到去过普吉岛但是没去过新西兰的人
	"""
	for puket_record in users_visited_puket:
		is_potential = True
		for nz_record in users_visited_nz:
			if puket_record['first_name'] == nz_record['first_name'] and puket_record['last_name'] == nz_record['last_name'] and puket_record['phone_number'] == nz_record['phone_number']:
				is_potential = False
				break
		if is_potential:
			yield puket_record  

因为原始数据里没有“用户 ID”之类的唯一标识,所以我们只能把“姓名和电话号码完全相同”作为判断是不是同一个人的标准。

函数 find_potential_customers_v1 通过循环的方式,先遍历所有去过普吉岛的人,然后再遍历新西兰的人,如果在新西兰的记录中找不到完全匹配的记录,就把它当做“潜在客户”返回。

这个函数虽然可以完成任务,但是相信不用我说你也能发现。它存在着非常严重的性能问题。对于每一条去过普吉岛的记录,我们都需要遍历所有新西兰访问记录,尝试找到匹配。整个算法的时间复杂度是可怕的 O(n*m),如果新西兰的访问条目数很多的话,那么执行它将耗费非常长的时间。

为了优化内层循环性能,我们需要减少线性查找匹配部分的开销

尝试使用集合优化函数

如果你对 Python 有所了解的话,那么你肯定知道,Python 里的字典和集合对象都是基于 哈希表(Hash Table) 实现的。判断一个东西是不是在集合里的平均时间复杂度是 O(1) ,非常快。

所以,对于上面的函数,我们可以先尝试针对新西兰访问记录初始化一个集合,之后的查找匹配部分就可以变得很快,函数整体时间复杂度就变为 O(n+m)

让我们看看新的函数:

def find_potential_customers_v2():
	"""
	找到去过普吉岛但是没去过新西兰的人,性能改进版
	"""
	# 首先,遍历所有新西兰访问记录,创建查找索引
	nz_records_idx = {
		(rec['first_name'], rec['last_name'], rec['phone_number'])
		for rec in users_visited_nz
	}

	for rec in users_visited_puket:
		key = (rec['first_name'], rec['last_name'], rec['phone_number'])
		if key not in nz_records_idx:
			yield rec  

使用了集合对象后,新函数在速度上相比旧版本 find_potential_customers_v1 有了飞跃性的突破。但是,对这个问题的优化并不是到此为止,不然文章标题就应该改成:“如何使用集合提高程序性能” 了。

对问题的重新思考

让我们来尝试重新抽象思考一下问题的本质。首先,我们有一份装了很多东西的容器 A(普吉岛访问记录),然后给我们另一个装了很多东西的容器 B(新西兰访问记录),之后定义相等规则:“姓名与电话一致”。最后基于这个相等规则,求 AB 之间的“差集”。

如果你对 Python 里的集合不是特别熟悉,我就稍微多介绍一点。假如我们拥有两个集合 AB,那么我们可以直接使用 A-B 这样的数学运算表达式来计算二者之间的 差集

>>> a = {1, 3, 5, 7}
>>> b = {3, 5, 8}

# 产生新集合:所有在 a 但是不在 b 里的元素
>>> a - b
{1, 7}  

所以,计算“所有去过普吉岛但没去过新西兰的人”,其实就是一次集合的求差值操作。那么要怎么做,才能把我们的问题套入到集合的游戏规则里去呢?

利用集合的游戏规则

在 Python 中,如果要把某个东西装到集合或字典里,一定要满足一个基本条件:“这个东西必须是可被哈希(Hashable)的” 。什么是 “Hashable”?

举个例子,Python 里面的所有可变对象,比如字典,就 不是 Hashable 的。当你尝试把字典放入集合中时,会发生这样的错误:

>>> s = set()
>>> s.add({'foo': 'bar'})
Traceback(most recent call last):
	File "<stdin>", line 1, in <module>  
TypeError: unhashable type: 'dict'  

所以,如果要利用集合解决我们的问题,就首先得定义我们自己的 “Hashable” 对象: VisitRecord。而要让一个自定义对象变得 Hashable,唯一要做的事情就是定义对象的 __hash__ 方法。

class VisitRecord:  
	'''  
	旅游记录  
	'''  
	def __init__(self, first_name, last_name, phone_number, date_visited):  
		self.first_name = first_name  
		self.last_name = last_name  
		self.phone_number = phone_number  
		self.date_visited = date_visited  

一个好的哈希算法,应该让不同对象之间的值尽可能的唯一,这样可以最大程度减少“哈希碰撞”发生的概率,默认情况下,所有 Python 对象的哈希值来自它的内存地址

在这个问题里,我们需要自定义对象的 __hash__ 方法,让它利用 (姓,名,电话)元组作为 VisitRecord 类的哈希值来源。

def __hash__(self):  
	return hash(
		(self.first_name, self.last_name, self.phone_number)
		)  

自定义完 __hash__ 方法后, VisitRecord 实例就可以正常的被放入集合中了。但这还不够,为了让前面提到的求差值算法正常工作,我们还需要实现 __eq__ 特殊方法。

__eq__ 是 Python 在判断两个对象是否相等时调用的特殊方法。默认情况下,它只有在自己和另一个对象的内存地址完全一致时,才会返回 True。但是在这里,我们复用了 VisitRecord 对象的哈希值,当二者相等时,就认为它们一样。

def __eq__(self, other):  
	# 当两条访问记录的名字和手机号相等时,则判断为同一个人  
	if isinstance(other, VisitRecord) and hash(self) == hash(other):  
		return True  
	return False  

完成了恰当的数据建模后,之后的求差值运算便算是水到渠成了。新版本的函数只需要一行代码就能完成操作:

def find_potential_customers_v3():  
	return set(VisitRecord(**r) for r in users_visited_puket) - set(VisitRecord(**r) for r in users_visited_nz)  

Hint:如果你使用的是 Python 2,那么除了 __eq__ 方法外,你还需要自定义类的 __ne__(判断不相等时使用) 方法。

使用dataclass简化代码

故事到这里并没有结束。在上面的代码里,我们手动定义了自己的 数据类 VisitRecord,实现了 __init____eq__ 等初始化方法。但其实还有更简单的做法

因为定义数据类这种需求在 Python 中实在太常见了,所以在 3.7 版本中,标准库中新增了 dataclasses 模块,专门帮你简化这类工作。

如果使用 dataclasses 提供的特性,我们的代码可以最终简化成下面这样:

@data_class(unsafe_hash=True)  
class VisitRecordDC:  
	first_name: str  
	last_name: str  
	phone_number: str  
	# 访问时间我们在这里不做约束,不作为对比条件  
	date_visited: str = field(hash=False, compare=False)  
	
def find_potential_customers_v4():  
	return set(VisitRecord(**r) for r in users_visited_puket) - set(VisitRecord(**r) for r in users_visited_nz)  

不用干任何脏活累活,只要不到十行代码就完成了工作。

案例总结

问题解决以后,让我们再做一点小小的总结。在处理这个问题时,我们一共使用了三种方案:

  1. 使用普通的两层循环筛选符合规则的结果集;

  2. 利用哈希表结构(set 对象)创建索引,提升处理效率;

  3. 将数据转换为自定义对象,利用规则,直接使用集合运算。

为什么第三种方式会比前面两种好呢?

首先,第一个方案的性能问题过于明显,所以很快就会被放弃。那么第二个方案呢?仔细想想看,方案二其实并没有什么明显的缺点。甚至和第三个方案相比,因为少了自定义对象的过程,它在性能与内存占用上,甚至有可能会微微强于后者。

但请再思考一下,如果你把方案二的代码换成另外一种语言,比如 Java,它是不是基本可以做到 1:1 的完全翻译?换句话说,它虽然效率高、代码直接,但是它没有完全利用好 Python 世界提供的规则,最大化的从中受益。

如果要具体化这个问题里的“规则”,那就是 “Python 拥有内置结构集合,集合之间可以进行差值等四则运算” 这个事实本身。匹配规则后编写的方案三代码拥有下面这些优势:

  • 为数据建模后,可以更方便的定义其他方法;

  • 如果需求变更,做反向差值运算、求交集运算都很简单;

  • 理解集合与 dataclasses 逻辑后,代码远比其他版本更简洁清晰;

  • 如果要修改相等规则,比如“只拥有相同姓的记录就算作一样”,只需要继承 VisitRecord 并覆盖 __eq__ 方法即可。

其它规则如何影响我们

在前面,我们花了很大的篇幅讲了如何利用“集合的规则”来编写事半功倍的代码。除此之外,Python 世界中还有着很多其他规则。如果能熟练掌握这些规则,就可以设计出符合 Python 惯例的 API,让代码更简洁精炼

下面是两个具体的例子。

使用__format__方法让对象完成字符串的格式化

如果你的自定义对象需要定义多种字符串表示方式,就像下面这样:

class Student:  
	def __init__(self, name, age):  
		self.name = name  
		self.age = age  

	def get_simple_display(self):  
		return f'{self.name}({self.age})'  

	def get_long_display(self):  
		return f'{self.name} is {self.age} years old now.'  

PUBG = Student('pubg', 3)  

if __name__ == '__main__':  
print(PUBG.get_simple_display())  # 输出:pubg(3)  
print(PUBG.get_long_display())  # 输出:pubg is 3 years old now.  

那么除了增加这种 get_xxx_display() 额外方法外,你还可以尝试自定义 Student 类的 __format__ 方法,因为那才是将对象变为字符串的标准规则。

class Student:  
	def __init__(self, name, age):  
		self.name = name  
		self.age = age  
	
	def __format__(self, format_spec):  
		if format_spec == 'simple':  
			return f'{self.name}({self.age})'  
		elif format_spec == 'long':  
			return f'{self.name} is {self.age} years old now.'   
		raise ValueError('Invalid format_spec.')  

PUBG = Student('pubg', 3)   

if __name__ == '__main__':  
print('{0:simple}'.format(PUBG))  # 输出:pubg(3)  
print('{0:long}'.format(PUBG))  # 输出:pubg is 3 years old now.  
使用__getitem__定义对象的切片操作

如果你要设计某个可以装东西的容器类型,那么你很可能会为它定义“是否为空”、“获取第 N 个对象”等方法:

class Events:  
	def __init__(self, events):  
		self.events = events  
	def is_empty(self):
		return not bool(self.events)  
	def list_events_by_range(self, start, end):  
		return self.events[start: end]  

events = Events([
	'computer started', 
	'os launched', 
	'docker started', 
	'os stopped'
])  

if __name__ == '__main__':  
# 查看创建的容器是否为空,否则打印出它的第二个和第三个对象  
if not events.is_empty():  
	print(events.list_events_by_range(1, 3))  
	
# 输出:['os launched', 'docker started']  

但是,这样并非最好的做法。因为 Python 已经为我们提供了一套对象规则,所以我们不需要像写其他语言的 OO(面向对象) 代码那样去自己定义额外方法。我们有更好的选择:

class Events:  
	def __init__(self, events):
		self.events = events  
		
	def __len__(self):  
		'''自定义长度,将会被用来做布尔判断'''  
		return len(self.events)  
	
	def __getitem__(self, index):  
		'''自定义切片方法'''  
		# 直接将slice切片对象透传给events处理  
		return self.events[index]  

events = Events([
	'computer started', 
	'os launched', 
	'docker started', 
	'os stopped'
])  

if __name__ == '__main__':  
	# 判断容器是否为空,否则打印切片后的数据  
	if events:  
		print(events[1: 3])
	
	# 输出:['os launched', 'docker started']  

新的写法相比旧代码,更能适配进 Python 世界的规则,API 也更为简洁

关于如何适配规则、写出更好的 Python 代码。Raymond Hettinger 在 PyCon 2015 上有过一次非常精彩的演讲 “Beyond PEP8 - Best practices for beautiful intelligible code”。这次演讲长期排在我个人的 “PyCon 视频 TOP5” 名单上,如果你还没有看过,我强烈建议你现在就去看一遍~

Hint:更全面的 Python 对象模型规则可以在 官方文档 找到,有点难读,但值得一读。

总结

Python 世界有着一套非常复杂的规则,这些规则的涵盖范围包括“对象与对象是否相等“、”对象与对象谁大谁小”等等。它们大部分都需要通过重新定义“双下划线方法 __xxx__” 去实现

如果熟悉这些规则,并在日常编码中活用它们,有助于我们更高效的解决问题、设计出更符合 Python 哲学的 API。下面是本文的一些要点总结:

  • 永远记得对原始需求做抽象分析,比如问题是否能用集合求差集解决;

  • 如果要把对象放入集合,需要自定义对象的 __hash____eq__ 方法;

  • __hash__ 方法决定性能(碰撞出现概率), __eq__ 决定对象间相等逻辑;

  • 使用 dataclasses 模块可以让你少写很多代码;

  • 使用 __format__ 方法替代自己定义的字符串格式化方法;

  • 在容器类对象上使用 __len____getitem__ 方法,而不是自己实现。

注:本文转自 Python工匠Python猫 系列文章,仅供学习交流使用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
# 智慧旅游解决方案摘要 智慧旅游解决方案旨在通过新一代信息网络技术和装备,实现旅游服务、管理、营销和体验的智能化。该方案响应国家政策背景,如国家旅游局和工业信息化部的指导意见,以及国家发改委的发展规划,强调数字化、网络化、智能化在旅游业的应用,推动5G和移动互联网技术在旅游领域的创新应用。 方案的建设目标围绕“一个中心、四个方面、五大平台”展开,即以智慧旅游数据中心为核心,面向服务、管理、商务和营销构建智慧景区管理平台、智慧旅游服务平台、智慧旅游商务平台和智慧旅游营销平台。这五大平台将整合全域旅游资源,提升旅游设施,拓展旅游空间,融合旅游产业链,提升旅游服务,定制旅游产品,推进旅游改革。 建设内容涵盖了整体架构的构建,包括智慧服务、智慧管理、电子商务和智慧营销等方面。通过云计算、人工智能、大数据、物联网、5G等技术,实现“云-管-端”服务能力,打造集时间、空间、层次为一体的体验平台。此外,还包括智慧景区管理平台的多个子系统,如视频监控、应急指挥调度、流量监测、舆情监督、线路SOS一键呼救、GIS人车调度、停车场管理、语音广播、环境监测管理、多媒体发布、电子巡更以及指挥调度大屏建设等。 智慧旅游服务平台则包括自助票务系统、人脸识别、扫码购票、景区门户网站、机游、WIFI覆盖系统、数字全景VR、AI机器人、智慧座椅、智慧厕所等,旨在提升游客体验,实现景区的智能化管理和服务。通过这些服务,游客可以享受到便捷的购票、入园、导览和信息服务,同时景区管理者能够更有效地监控和管理景区运营。 智慧旅游商务平台则侧重于旅行社团队申报、电子商城、综合票务系统、分销管理系统、大会员系统和景区聚合支付系统,为旅游企业提供全面的商务服务和营销支持。这些平台和系统帮助旅游企业拓宽分销渠道,实现财务管理和订单管理,同时为游客提供便捷的支付和会员服务。 最后,智慧营销平台通过综合票务系统、分销管理系统、大会员系统和景区聚合支付系统,为旅游行业提供精准的营销工具和策略。这些工具和策略有助于整合旅游资源,拓宽销售渠道,提升游客体验,实现旅游业务的数字化和智能化。 智慧旅游解决方案通过这些综合性的技术和平台,不仅提升了游客的旅游体验,还为旅游行业的可持续发展提供了强有力的技术支持和数据驱动的决策依据。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值