-
AI编程实战营完结:为什么说这是2024年职场人最该掌握的"第二技能"写在前面当AI编程实战营的最后一节课落下帷幕,我翻了翻自己这段时间的学习笔记,内心涌上来的不是"终于学完了"的轻松,而是一种说不清的紧迫感——再不动手,可能真的来不及了。这不是贩卖焦虑,而是我作为一个普通职场人,最真实的感受。AI不会替代你,但会用AI的人会说实话,报名之前我也犹豫过。编程?那不是程序员的事吗?我一个做运营的、做产品的、做管理的,学这个有什么用?但学完之后我彻底改变了想法。AI编程的本质不是让你成为开发者,而是让你拥有一个"超级助理"。以前写个数据分析报告,要么求技术部门排期,要么自己在Excel里折腾半天。现在呢?我可以用自然语言描述我的需求,让AI帮我生成分析逻辑,甚至直接跑出可视化图表。这不是科幻,这是我这几周实实在在做到的事。职场中最残酷的真相就是:你的不可替代性,取决于你能调用多少资源。而AI,就是这个时代最大的资源。实战营到底教了什么?很多人一听"AI编程"就觉得很技术、很硬核。但这个实战营让我意外的是——它从第一天起就在打破"编程很难"这个幻觉。从最基础的AI对话技巧,到如何用AI辅助写方案、做表格、分析数据、生成内容,每一步都是围绕"职场真实场景"展开的。没有那些让人劝退的底层原理堆砌,而是直接告诉你:遇到这个问题,用这招,三步搞定。我特别喜欢里面一个观点:不要想着"学会编程",而是想着"学会提问"。 在AI时代,提问的能力就是编程的能力。你能把需求描述得越清晰,AI就能帮你干得越漂亮。这门课最值的不是技能,是思维如果只说技能层面,市面上AI工具那么多,自己摸索也能学会。但这个实战营真正让我觉得值的,是它帮我重建了一套工作思维。以前遇到复杂任务,第一反应是"这太难了,分解不了"。现在的第一反应变成了"这个任务可以拆成哪几块?哪几块能交给AI?"这种思维的转变,比掌握任何一个工具都重要。因为工具会更新、会迭代,但把大问题拆解成小问题、再逐一解决的能力,永远不会过时。给还在犹豫的人一句话我知道很多人和当初的我一样,觉得"等我有空了再学""等AI更成熟了再说"。但我想说,最好的学习时间永远是现在。 等所有人都学会了,你的竞争优势就归零了。而现在,你比身边80%的人多懂一点AI应用,你就已经跑在前面了。这个实战营虽然完结了,但AI的浪潮才刚刚开始。与其焦虑被淘汰,不如现在就行动起来。职场下半场,拼的不是谁更努力,而是谁更会借力。而AI,就是你此刻能借到的最大的力。
-
告别低效自学,AI 编程实战行动营手把手带你进阶:从技术视角拆解“高效学习”的真实路径在 AI 技术井喷的当下,有一个现象值得深思:技术学习的资源从未如此丰富,但学习者的焦虑也从未如此强烈。GitHub 上有数不清的开源项目,arXiv 上每天更新成百上千篇论文,B站和 YouTube 上堆满了免费教程。理论上,只要有网,任何人都可以自学成为 AI 工程师。然而现实是,绝大多数人在这片信息的汪洋中迷失了方向——收藏从未停止,学习从未开始;开始了也坚持不下去;坚持下去了却发现学的东西根本用不上。问题的根源不在于“资源不够”,而在于“路径缺失”。自学最大的陷阱,是把“看了”等同于“会了”,把“跑通 demo”等同于“能落地”。正因如此,“AI 编程实战行动营” 应运而生。它不是一门传统的视频课程,而是一套以“动手”为核心、以“进阶”为目标的行动体系。今天,我们从技术角度聊聊:为什么低效自学正在毁掉你的 AI 之路,以及这套行动营究竟做对了什么。一、低效自学的三大技术性误区在分析行动营的价值之前,有必要先看清自学这件事到底难在哪里。不是你不努力,而是你的努力可能用错了方向。误区一:线性学习,忽略知识图谱的结构技术知识不是线性的,不是学会 A 才能学 B、学完 B 才能学 C 的简单链条。它是一个复杂的网状结构。比如,想理解多模态模型,你可能需要同时了解 Transformer、对比学习、图像编码器三个知识块,它们相互依赖、相互支撑。自学者最容易犯的错误,是按照某本书或某门课的目录“顺序学习”。学到第五章发现需要第三章的某个概念,翻回去补,补完再回来——反复横跳,效率极低。更糟糕的是,很多知识是“用到了才真正理解”的,前置学习的效果大打折扣。误区二:被动输入,缺少反馈闭环看视频、读文章、记笔记——这些都是被动输入。它们能给你“我学会了”的错觉,但真正检验学习效果的,是主动输出。自学的人没有老师、没有助教、没有同学。写出来的代码没人 review,模型结果没人评估,错误认知没有人纠正。一个错误的理解可能在你的大脑里盘踞几个月,直到某一天在真实项目中暴露出来,届时付出的代价远比一开始就纠正要大得多。误区三:项目断层,零散知识点无法串联这是最致命的误区。很多人今天学一点 prompt 技巧,明天看一篇 RAG 教程,后天又研究某个框架的用法。每一个知识点单独看都懂,但到了真要做一个完整项目的时候,完全不知道从哪里下手。真实的项目不是知识点的累加,而是在一个完整的技术流程中,把各个环节的能力串联起来。缺少这种“串联训练”的自学者,永远停留在“知道”的层面,离“做到”还有很远。二、实战行动营的技术路径:从“知道”到“做到”的四步法AI 编程实战行动营正是针对这三大误区设计的。它不是一套课程,而是一套行动体系。其核心方法论可以概括为“目标驱动、项目串联、反馈闭环、持续行动”。第一步:目标分层——把“学 AI”拆成可执行的里程碑“我要学 AI”是一个没有可执行性的目标。行动营做的第一件事,是把宏大的学习愿望拆解成具体的技术里程碑。这套拆解方法论本身就是一套技术认知训练:你需要根据当前的技术水平和职业方向,确定下一阶段应该掌握的工程能力,再倒推出需要完成的核心项目,最后拆解到每周、每天的具体行动。没有这个拆解过程,所谓的“学习计划”只会是一张永远无法完成的任务清单。第二步:项目驱动——用完整项目串起技术盲区行动营最核心的设计理念是:项目不是学完之后的“练习题”,而是学习的“主线剧情”。每一个项目都对应真实场景中的一类技术问题——比如构建一个具备长期记忆的对话智能体、设计一套可配置的多工具调用系统、实现一个低延迟的 RAG 问答服务。在完成项目的过程中,你必然遇到各种障碍:框架的使用细节、模型的输出格式错乱、工具调用的超时处理、异步任务的回调管理……这些障碍不是课程的 bug,而是课程的 features。克服每一个障碍,你就填补了一个技术盲区。当盲区被逐一填补之后,你获得的不是一堆零散的知识点,而是一套完整的、经过验证的工程方案。第三步:反馈闭环——让错误被及时发现和纠正一个人自学最难解决的问题就是缺少反馈。行动营通过三种机制构建了完整的反馈闭环:同伴反馈:在小组中互相 review 代码、讨论技术方案。解释给别人听本身是最好的学习方式,而被人指出错误是最快的纠错方式。助教反馈:当你在某个技术卡点上耗费超过合理时间时,助教会介入,帮你定位问题根源,而不是直接给出答案。项目验收:每个项目都有明确的完成标准和验收机制。被认定为“完成”的项目不仅是学习的成果,更是信心的锚点。这套反馈体系的价值,在自学场景下几乎无法被替代。第四步:复利沉淀——让每一分努力都可复用很多自学者最大的痛点是:学完就忘,做完就丢。上一项目踩过的坑,下一个项目重新再踩一遍。行动营要求学员对所有完成的项目进行“技术复盘”和“方案沉淀”。每个项目都要产出:技术选型的决策记录、遇到的关键问题及解决方案、可复用的代码脚手架、后续优化的待办清单。这些沉淀下来的资产,不仅是个人技术能力的可视化证明,更是在未来工作中可以直接调用的“个人技术库”。随着项目数量的增加,学习的边际成本在下降,边际收益在上升——这就是学习的复利效应。三、技术启示:学习的本质是“认知重构”自学和行动营之间的区别,表面上看是有没有人带、有没有人陪。但从技术认知的角度看,本质区别在于:自学是在信息的海洋里做布朗运动。你可能会碰到有用的信息,但更大概率是在原地打转。而行动营提供了一条经过验证的“最小能量路径”——沿着这条路径,你的每一次行动都在靠近目标,你对技术的认知在持续地、结构化地重构。更重要的是,这套行动体系会内化为一种能力。当你完成足够多的项目、经历过足够多的卡点和克服之后,你会在任何新技术面前具备一种从容感——你知道怎么学、知道哪里可能会卡、知道怎么找答案。这种能力,才是“进阶”的真正含义。结语低效自学的代价,不是浪费几个月的时间那么简单。它真正剥夺的,是你在这个技术窗口期内本应抓住的机会。AI 编程实战行动营想做的,不是替你学习,而是给你一套真正有效的学习系统。有目标、有项目、有反馈、有沉淀——这套系统一旦建立起来,你就不再需要任何“训练营”了,因为你自己已经具备了高效获取任何技术的能力。而这一切,从告别低效自学、加入行动营开始。
-
编程范式(Programming Paradigm)是编程的“风格”或“方法论”,它定义了程序员如何组织代码、管理数据和控制流程。以下是 函数式、并发式、过程式和面向对象 四种常见编程范式的核心概念和示例:1. 函数式编程(Functional Programming, FP)核心思想函数是一等公民:函数可以像变量一样传递、返回或存储。避免副作用:函数不修改外部状态,仅依赖输入参数并返回输出。不可变数据:数据一旦创建就不能修改,避免意外变更。高阶函数:函数可以接受其他函数作为参数,或返回函数。示例(Python)# 高阶函数:map 遍历列表并应用函数 numbers = [1, 2, 3, 4] squared = list(map(lambda x: x ** 2, numbers)) # [1, 4, 9, 16] # 纯函数:无副作用,输入相同则输出相同 def add(a, b): return a + b # 不修改外部变量 # 递归代替循环(避免可变状态) def factorial(n): return 1 if n == 0 else n * factorial(n - 1) 适用场景数据处理(如 MapReduce、大数据分析)。并行计算(无副作用的函数易并行化)。函数组合(如前端 React 的 useState 钩子)。2. 并发式编程(Concurrent Programming)核心思想同时执行多个任务:通过多线程、多进程或异步 I/O 实现。共享资源管理:避免竞态条件(Race Condition)和数据竞争。同步机制:使用锁、信号量、通道(Channel)等协调任务。示例(Python 多线程)import threading # 共享资源 counter = 0 lock = threading.Lock() def increment(): global counter with lock: # 加锁避免竞态条件 counter += 1 threads = [] for _ in range(100): t = threading.Thread(target=increment) threads.append(t) t.start() for t in threads: t.join() print(counter) # 输出 100(无锁时可能小于 100) 其他并发模型异步编程(Async/Await):如 JavaScript 的 Promise 或 Python 的 asyncio。Actor 模型:如 Erlang/Elixir 的进程间通信。CSP(Communicating Sequential Processes):如 Go 的 goroutine 和 channel。适用场景高并发服务器(如 Web 后端、聊天应用)。I/O 密集型任务(如爬虫、文件处理)。实时系统(如游戏、金融交易)。3. 过程式编程(Procedural Programming)核心思想步骤化:将程序分解为一系列过程(函数)和语句。顺序执行:代码从上到下执行,通过函数调用组织逻辑。全局数据:变量可以全局访问(需谨慎管理)。示例(C 语言)#include <stdio.h> // 全局变量 int global_var = 10; // 过程(函数) void print_sum(int a, int b) { int result = a + b + global_var; printf("Sum: %d\n", result); } int main() { int x = 5, y = 3; print_sum(x, y); // 调用过程 return 0; } 特点自顶向下设计:先写主流程,再拆分函数。易理解:适合小型程序或脚本。缺点:数据与逻辑分离,大型项目易混乱。适用场景简单脚本(如 Bash、Python 脚本)。嵌入式系统(资源受限时)。教学(初学者易上手)。4. 面向对象编程(Object-Oriented Programming, OOP)核心思想对象:数据(属性)和操作(方法)的封装体。类:对象的模板,定义属性和方法。四大特性:封装:隐藏内部细节,暴露接口。继承:子类复用父类代码。多态:同一方法在不同类中有不同实现。抽象:提取关键特征,忽略非本质细节。示例(Python)# 类定义 class Animal: def __init__(self, name): self.name = name # 属性 def speak(self): # 方法 raise NotImplementedError("子类必须实现此方法") # 继承 class Dog(Animal): def speak(self): return f"{self.name} 说:汪汪!" class Cat(Animal): def speak(self): return f"{self.name} 说:喵喵!" # 多态 animals = [Dog("阿黄"), Cat("小花")] for animal in animals: print(animal.speak()) # 输出: # 阿黄 说:汪汪! # 小花 说:喵喵! 适用场景大型软件(如 GUI 应用、游戏引擎)。需要建模现实世界的系统(如银行账户、电商订单)。代码复用(通过继承和多态)。总结对比范式核心单位状态管理典型语言适用场景函数式函数不可变Haskell, Erlang数据处理、并行计算并发式任务/协程共享资源同步Go, Elixir高并发、实时系统过程式过程/函数全局变量C, Pascal简单脚本、嵌入式系统面向对象对象/类封装属性Java, Python大型软件、建模现实世界混合使用现代语言通常支持多种范式(如 Python 支持函数式、过程式和 OOP):# Python 混合范式示例 from functools import reduce # 函数式 numbers = [1, 2, 3] sum_func = reduce(lambda x, y: x + y, numbers) # 6 # 面向对象 class Calculator: def add(self, a, b): return a + b calc = Calculator() sum_oop = calc.add(1, 2) # 3 选择范式时,需根据 问题域(如数据处理用函数式,GUI 用 OOP)和 团队习惯 决定。
-
2025年5月10日在兰州理工大学彭家坪校区求是楼C205举办了一场仓颉语言编程培训,培训由布道师赵宏老师主持,学生布道师惠旭同,学生预备布道师陈康平、孙其翔协助。39名同学参加了培训,同学们在培训方搭建的Jupyter Lab平台上进行了仓颉编程实践,并完成培训测试。后续,培训方将继续组织同学们学习仓颉编程语言,并实践基于仓颉的鸿蒙应用开发。
-
技术核心优势:1. TVM 引擎支持 Lisp、JavaScript、Python、Ruby、Lua、Pascal、Basic 等多种语法。2. TVM 超微型内核引擎(不足500kb),拥有几百个实用函数。 内核模块非常紧凑,所需系统资源很小,因此与其他语言相比加载执行起来更加快速。3. TVM 建立在通用的UNIX系统的C语言库函数基础上, 可以运行在各种操作系统平台,如Windows,Linux,BSDs,Mac OS等。4. TVM 引擎可以进行源代码链接,生成独立的可执行文件。5. TVM 引擎以共享库库的方式可以嵌入到宿主系统中,可作为应用开发的语言平台。6. 动态脚本语言,简单易学,模块化集成,同时具有教学语言的优点: 透明和友好提示。7. 支持符号单元运算, 任何符号都可以用作定义计算的行为,突破了以往计算机编程汉字仅能作为字符串数据来处理的局面, 可将任何符号(例如:中文、简繁体汉字、少数民族语言文字)作为计算机代码来运行。8. 面向对象,基于原型继承。9. 函数式编程涵盖LISP语言抽象语法、独特的符号、表达式处理等突出特点。10. 同时拥有 C 语言的访问底层数据单元,执行系统操作的灵活快捷的特点,和 C 语言一样可以定义结构,访问结构成员和进行指针操作。11. 动态语言弱类型,数据使用前无需宣告声明。 而C语言在编译的过程中须明确操作数的内存单元大小和长度,因此使用前必须事先申明变量符号和函数符号的数据类型。12. 集中强化符号和表达式的处理和操作。包括修改,插入,删除复杂嵌套列表和多维数组结构中的元素。13. 具有多态函数的特点,参与函数运算的参数类型不限和参数个数不限,这使得定义函数有很强的灵活性。14. 函数是特殊的列表,可以象操作列表一样来对函数进行组合和拆分。 除了定义函数外,还可以用宏实现在重构表达式。15. 支持流的输入输出操作,可以包含控制字符的二进制数据访问。16. 支持Perl语言兼容的正则表达式(PCRE)文本处理。17. 具有内存垃圾自动收集的功能。当对象不再被引用时,它们所占用的内存空间自动被回收后再利用。18. 拥有对象、符号目录,供多人协作完成的大型软件项目,既可以引用他人的目标模块,又可以避免变量或函数重名的覆盖危险。19. 除了使用内建函数外,还可以通过导入共享库来进行功能扩展。 比如调用 windows 操作系统的库函数来实现GUI界面,使用 COM 对象、.NET 框架等等。20. TeaScript 可运用于分布计算、科学统计、图形与图像和人工智能领域。 HTTP、 TCP/IP 和UDP 套节字界面使得它很容易编写网络应用程序。
-
{ "status": 1, "data": { "category": [{ "title": "产经", "url": "", "subcat": [{ "title": "消费", "url": "", "type": "5" }, { "title": "医药", "url": "", "type": "5" } ], "type": 1 }] }}各位老师我刚开始接触arkts开发,我用http获取到了json数据,但是本地要使用的话得存起来,我想到的是存到对象里面,但是找了好多资料都没有搞定,哪位老师有时间帮忙教导一下,我用了class-transformer也没搞定,基础太差了,谢谢路过的老师
-
一、冒泡排序基本原理 冒泡排序是一种简单的排序算法。它重复地走访要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。 以一个简单的整数数组为例,假设数组为[5, 4, 3, 2, 1]。第一轮比较时,首先比较第一个元素5和第二个元素4,因为5>4,所以交换它们的位置,数组变为[4, 5, 3, 2, 1]。接着比较第二个元素5和第三个元素3,因为5>3,交换后数组变为[4, 3, 5, 2, 1],以此类推。经过第一轮比较(总共比较n-1次,n是数组元素个数),最大的元素5就会 “浮” 到数组的最后面。然后进行第二轮比较,此时不需要比较最后一个元素了,因为它已经是最大的。经过n-1轮这样的比较,数组就会排序完成。 二、C#实现冒泡排序的代码示例 以下是一个简单的C3方法来实现的冒泡排序,用于对一个整数数组进行排序: 在上述代码中: BubbleSort方法接受一个整数数组array作为参数。首先获取数组的长度n。 外层循环for (int i = 0; i < n - 1; i++)控制排序的轮数,总共需要n-1轮。 内层循环for (int j = 0; j < n - i - 1; j++)用于每一轮比较元素。在每一轮中,比较相邻的元素,如果array[j]>array[j + 1],就交换它们的位置。交换元素的操作通过一个临时变量temp来实现。 在Main方法中,首先定义了一个未排序的整数数组numbers,然后调用BubbleSort方法对其进行排序,最后使用foreach循环输出排序后的数组元素。 C#练习26 ———————————————— 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 原文链接:https://blog.csdn.net/2408_89166609/article/details/144719919
-
算术运算符运算符描述+两个数相加两个数相加,或是字符串连接-两个数相减*两个数相乘,或是返回一个重复若干次的字符串/两个数相除,结果为浮点数%取模,返回两个数相除的余数//两个数相除,返回商的整数部分**幂运算,返回乘方结果1234567print(1 + 2) # 3print(2 - 1) # 1print(2 * 3) # 6print(3 / 2) # 1.5print(6 % 5) # 1print(8 // 2) # 4print(3 ** 2) # 9如果想同时得到商和余数,可以用divmod这个方法该方法的返回值是tuple (x//y, x%y).1print(divmod(10,3)) # (3,1)因为浮点数精度的问题,Python还存在一些计算方面的小问题1print(0.1+0.1+0.1-0.3) # 5.551115123125783e-17要解决这个问题,可以导入decimal模块123from decimal import Decimal# 计算结果:0.0print(Decimal('0.1')+Decimal('0.1')+Decimal('0.1')-Decimal('0.3'))关系运算符运算符描述==比较对象是否相等!=比较对象是否不相等>大于,例如a>b,将比较a与b的大小,a>b返回True,否则返回False<小于,例如a<b,将比较a与b的大小,a<b返回True,否则返回False>=大于等于,例如a>=b,将比较a与b的大小,a>=b返回True,否则返回False<=小于等于,例如a<=b,将比较a与b的大小,a<=b返回True,否则返回False12345678a = 10b = 20print(a == b) # Falseprint(a != b) # Trueprint(a > b) # False print(a < b) # Trueprint(a >= b) # Falseprint(a <= b) # True1.返回值为bool值12print(True == 1) # Trueprint(False == 0) # True==比较数值(int与str不能直接比较)12print(2.0 == 2) # Trueprint('2' == 2) # False字符串与字符串之间是比较ASCII值12# Trueprint('abc' < 'xyz') # 97 98 99 < 120 121 122连续比较,python的解释机制123print(3 > 2 > 1) # Trueprint(3 > 2 > 2) # Falseprint((3 > 2) > 1) # False赋值运算符运算符描述=常规赋值运算符,将运算结果赋值给变量+=加法赋值运算符,例如 a+=b 等效于 a=a+b-=减法赋值运算符,例如 a-=b 等效于 a=a-b*=乘法法赋值运算符,例如 a*=b 等效于 a=a*b/=除法赋值运算符,例如 a/=b 等效于 a=a/b//=取整除赋值运算符,例如 a//=b 等效于 a=a//b%=取模赋值运算符,例如 a%=b 等效于 a=a%b**=幂运算赋值运算符,例如 a**=b 等效于 a=a*b123a = 1 # 将等号右边 赋值 等号左边a = a + 1 # 先等号右边计算 再赋值给 等号左边a += 1 # a = a + 1逻辑运算符运算符描述and与运算,如果a 为False,a and b返回False 否则返回y的计算值or或运算,如果a非0,返回a的值,否则返回b的值not非运算,如果a为True,返回False,如果a为False,返回True12345a = 10b = 20print(a and b) # 20print(a or b) # 10print(not a) # Falsea and b 两者都为True时结果才为Truea or b 两者有一个为True则结果就为True短路(懒惰)原则False and True 当and运算符时,遇到第一个为False则不会往后了True or False 当or运算符时,遇到第一个为True则不会往后了成员运算符运算符描述in如果在指定的序列中找到值返回True,否则返回Falsenot in如果在指定的序列中找到值返回True,否则返回False123456list1 = [1, 2, 3, 4, 5]a = 1if a in list1: print("a是list1的元素之一")else: print("a不是list1的元素")身份运算符运算符描述is判断两个标识符是不是引用自一个对象is not判断两个标识符是不是引用自不同对象 is 和比较运算符 == 的区别 is 用于判断两个变量是否引自同一个对象(可使用id()查看),而 ==用于判断变量的值是否相等!1234567a = [1, 2, 3]b = [1, 2, 3]# 可通过id()查看内存地址print(id(a)) # 2042443551304print(id(b)) # 2042443551816print(a is b) # Falseprint(a == b) # True1234567a = 2b = 2.0# 可通过id()查看内存地址print(id(a)) # 140722443350320print(id(b)) # 2336678499216print(a is b) # Falseprint(a == b) # True三目运算符三目运算符的表示方法:True_statements if expression else False_statements1234a = 1b = 2# a+b不大于3执行后面的else语句 b-a = 1print(a+b if a+b>3 else b-a)运算符优先级运算符描述**指数(最高优先级)*/%//乘,除,取模和取整除±加法减法<= >=比较运算符== !=等于运算符= %= 、= 、、=-= += *= **=赋值运算符is is not身份运算符in not in成员运算符not or and逻辑运算符
-
用于动态计算长度值。需要注意的是,运算符前后都需要保留一个空格,例如:width: calc(100% - 10px);任何长度值都可以使用计算值()函数进行计算;calc()函数支持“+”,“ - ”,“*”,“/”运算;计算值()函数使用标准的数学运算优先级规则;calc()不起作用应该是运算符前后没留空格导致,可以加空格测试
-
1. 概念多态是面向对象程序设计(OOP)的一个重要特征,指同一个实体同时具有多种形式,即同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。可以把不同的子类对象都当作父类来看,进而屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准。比如,你的女盆友让你买点水果回来,不管买回来的是苹果还是西瓜,只要是水果就行,这个就是生活中多态的体现再比如,小猫、小狗、小猪我们可以把他们都归纳成小动物,每种小动物都需要吃东西,所以我们可以统一设置他们都必须吃,但是每种小动物的习性不一样,那这个就可以设置成小动物自己特有的功能,多态对象只能调用父类中定义子类中重写的功能,并不能调用子类的特有功能,这样就实现了代码的统一2 . 特点多态的前提1:是继承多态的前提2:要有方法的重写父类引用指向子类对象,如:Animal a = new Cat();多态中,编译看左边,运行看右边3. 练习:多态入门案例创建包: cn.tedu.oop创建类: TestDemo.javapackage cn.tedu.oop2;/*本类用作多态的入门案例*/public class TestDemo { public static void main(String[] args) { //6.创建“纯纯的”对象用于测试 Animal a = new Animal(); Cat c = new Cat(); Dog d = new Dog(); a.eat();//小动物Animal吃啥都行~调用的是父类自己的功能 c.eat();//小猫爱吃小鱼干~调用的是子类重写后的功能 d.eat();//小狗爱吃肉骨头~调用的是子类重写后的功能 /*2.父类对象不可以使用子类的特有功能*/ //a.jump();//报错,Animal类里并没有这个方法 //a.run();//报错,Animal类里并没有这个方法 c.jump();//小猫Cat跳的老高啦~,子类可以调用自己的功能 d.run();//小狗Dog跑的老快啦~,子类可以调用自己的功能 //7.创建多态对象进行测试 /*3.口诀1:父类引用指向子类对象 * 解释:创建出来的子类对象的地址值,交给父类类型的引用类型变量来保存*/ Animal a2 = new Cat();//Cat类对象的地址值交给父类型变量a2来保存 Animal a3 = new Dog();//Dog类对象的地址值交给父类型变量a3来保存 //8.测试多态对象 /*4.口诀2:编译看左边,运行看右边 * 解释:必须要在父类定义这个方法,才能通过编译,把多态对象看作是父类类型 * 必须要在子类重写这个方法,才能满足多态,实际干活的是子类*/ a2.eat();//小猫爱吃小鱼干~,多态对象使用的是父类的定义,子类的方法体 }}/*1.多态的前提:继承+重写*///1.创建父类class Animal{ //3.创建父类的普通方法 public void eat(){ System.out.println("小动物Animal吃啥都行~"); }}//2.1创建子类1class Cat extends Animal{ //4.1添加重写的方法 public void eat(){ System.out.println("小猫爱吃小鱼干~"); } //5.1添加子类的特有功能 public void jump(){ System.out.println("小猫Cat跳的老高啦~"); }}//2.2创建子类2class Dog extends Animal{ //4.2添加重写的方法 @Override public void eat(){ System.out.println("小狗爱吃肉骨头~"); } //5.2添加子类的特有功能 public void run(){ System.out.println("小狗Dog跑的老快啦~"); }}4. 多态的好处多态可以让我们不用关心某个对象到底具体是什么类型,就可以使用该对象的某些方法提高了程序的可扩展性和可维护性5. 多态的使用前提:多态对象把自己看做是父类类型成员变量: 使用的是父类的成员方法: 由于存在重写现象,所以使用的是子类的静态成员: 随着类的加载而加载,谁调用就返回谁的6. 练习:多态成员使用测试创建包: cn.tedu.oop创建类: TestDemo2.javapackage cn.tedu.oop2;/*本类用于测试多态成员的使用情况*/public class TestDemo2 { public static void main(String[] args) { //7.创建纯纯的子类对象 Dog2 d = new Dog2(); System.out.println(d.sum);//20,子类自己的属性 d.eat();//小狗爱吃肉包子,子类自己的方法 //8.创建多态对象 /*口诀1:父类引用指向子类对象*/ /*口诀2:编译(保存)看左边,运行(效果)看右边*/ Animal2 a = new Dog2(); /*多态中,成员变量使用的是父类的*/ System.out.println(a.sum);//10 /*多态中,方法的声明使用的是父类的,方法体使用的是子类的*/ a.eat();//小狗爱吃肉包子 /*多态中,调用的静态方法是父类的,因为多态对象把自己看作是父类类型 * 直接使用父类中的静态资源*/ a.play();//没有提示,玩啥都行~ Animal2.play(); }}//1.创建父类class Animal2{ //3.创建父类的成员变量 int sum = 10; //4.创建父类的普通方法 public void eat(){ System.out.println("吃啥都行~"); } //9.1定义父类的静态方法play public static void play(){ System.out.println("玩啥都行~"); }}//2.创建子类class Dog2 extends Animal2{ //5.定义子类的成员变量 int sum = 20; //6.重写父类的方法 @Override public void eat(){ System.out.println("小狗爱吃肉包子"); } //9.2创建子类的静态方法play //@Override /*这不是一个重写的方法,只是恰巧在两个类中出现了一模一样的两个静态方法 * 静态方法属于类资源,只有一份,不存在重写的现象 * 在哪个类里定义,就作为哪个类的资源使用*/ public static void play(){ System.out.println("小狗喜欢玩皮球~"); }}7 拓展7.1 设计汽车综合案例创建包: cn.tedu.oopexec创建类: DesignCar.javapackage cn.tedu.oop2;/*本类用于完成汽车设计案例*/public class DesignCar { public static void main(String[] args) { //9.创建一个纯纯的父类对象进行测试 Car c = new Car(); System.out.println(c.getColor());//null c.start(); c.stop(); //c.swim();//报错,父类对象不可以调用子类的特有功能 //10.创建纯纯的子类对象做测试 BMW b = new BMW(); System.out.println(b.color);//五彩斑斓的黑 System.out.println(b.getColor());//null b.start();//都让开,我的车要起飞啦~ b.stop();//唉呀妈呀熄火了~ //11.创建多态对象进行测试 Car c2 = new TSL(); //System.out.println(c2.color); System.out.println(c2.getColor()); c2.stop(); c2.start(); //c2.swim(); }}//1.通过分析,抽象形成一个汽车类class Car{ //2.定义并封装汽车类的属性--成员变量 private String brand;//品牌 private String color;//颜色 private int id;//编号 private double price;//价格 //3.定义功能 public void start(){ System.out.println("我的小车车启动啦~"); } public void stop(){ System.out.println("唉呀妈呀熄火了~"); } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getId() { return id; } public void setId(int id) { this.id = id; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; }}//4.创建子类class BMW extends Car{ String color = "五彩斑斓的黑"; //5.重写父类的方法 @Override public void start(){ System.out.println("都让开,我的车要起飞啦~"); }}//6.创建子类2class TSL extends Car{ //7.重写父类的方法 @Override public void stop(){ System.out.println("唉呀妈,怎么停不下来呢"); } //8.添加子类的特有功能 public void swim(){ System.out.println("没想到吧,我还是个潜水艇"); }}7.2 多态为了统一调用标准package cn.tedu.oop2;public class TestFruit { public static void main(String[] args) { Fruit f = new Fruit(); Apple a = new Apple(); Orange o = new Orange(); get(f); get(a); get(o); } //只需要创建一个方法,就可以执行截然不同的效果 //忽略子类对象的差异统一看作父类类型 public static void get(Fruit f){ f.clean(); }}class Fruit{ public void clean(){ System.out.println("水果要洗洗再吃"); }}class Apple extends Fruit{ @Override public void clean(){ System.out.println("苹果需要削皮"); }}class Orange extends Fruit{ @Override public void clean(){ System.out.println("橙子需要剥皮"); }}7.3 静态变量和实例变量的区别在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。7.4 向上转型和向下转型在JAVA中,继承是一个重要的特征,通过extends关键字,子类可以复用父类的功能,如果父类不能满足当前子类的需求,则子类可以重写父类中的方法来加以扩展。那么在这个过程中就存在着多态的应用。存在着两种转型方式,分别是:向上转型和向下转型。向上转型:可以把不同的子类对象都当作父类来看,进而屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准。比如:父类Parent,子类Child父类的引用指向子类对象:Parent p=new Child();说明:向上转型时,子类对象当成父类对象,只能调用父类的功能,如果子类重写了父类中声明过的方法,方法体执行的就是子类重过后的功能。但是此时对象是把自己看做是父类类型的,所以其他资源使用的还是父类型的。比如:花木兰替父从军,大家都把花木兰看做她爸,但是实际从军的是花木兰,而且,花木兰只能做她爸能做的事,在军营里是不可以化妆的。向下转型(较少):子类的引用的指向子类对象,过程中必须要采取到强制转型。这个是之前向上造型过的子类对象仍然想执行子类的特有功能,所以需要重新恢复成子类对象Parent p = new Child();//向上转型,此时,p是Parent类型Child c = (Child)p;//此时,把Parent类型的p转成小类型Child其实,相当于创建了一个子类对象一样,可以用父类的,也可以用自己的说明:向下转型时,是为了方便使用子类的特殊方法,也就是说当子类方法做了功能拓展,就可以直接使用子类功能。比如:花木兰打仗结束,就不需要再看做是她爸了,就可以”对镜贴花黄”了————————————————版权声明:本文为CSDN博主「程序媛 泡泡」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/weixin_43884234/article/details/116593803
-
10. 操作符算数操作符+ - * / %算数操作符中的+ - *和平常运算方法相似,我们在这边重点介绍 / 和 %运算符/ 操作符为了让我们的讲解更加具有针对性,我们分正数和负数两部分进行讲解:/ 操作符对正数#include<stdio.h>int main(){ int a = 7 / 2; printf("%d\n", a);//3}分析:对于上方代码当我们用平时的逻辑,那么这个答案应该是3.5,可在程序中编译运行,结果是 3,我们不禁产生疑惑是不是因为你打印的结果是整形的缘故,其实本身结果还是3.5呢?让我们用代码验证:#include<stdio.h>int main(){ float f = 7 / 2; printf("%f\n",f);//3.000000}可当我们再次进行编译运行时,结果是3.000000,因此我们可以得出结论:除号两端的操作数如果都是整数,执行的是整数除法,至少有一个操作数是浮点数,执行的才是浮点数的除法!!!对于正数是这样进行运算的,那么负数呢?/ 操作符对负数#include<stdio.h>int main(){ int i = -2.9; int j = 2.9; printf("%d\n",j);//-2 printf("%d\n",j);//2 return 0;}对于负数运算,我们打印 j 的值,结果为 -2 ,和正数运算规律相似,我们可以看出它们运算都是向0取整的,那么如何理解呢?对于取整,当正负数进行运算时,并不会出现四舍五入的情况,无论正数负数都是向0方向取整!(-2.9向零取整得到2)如下图所示:小科普在C语言中,是不是只有一种取整方式?如果有它们分别是怎么实现的?接下来我们来一一了解:trunc - 取整函数#include<math.h>int main(){ printf("%d\n",(int)trunc(-2.9));//-2 printf("%d\n",(int)trunc(2.9));//2 }Tips:由于trunc函数默认接收的返回值为%f,但是我们这边想输出的是整数所以强制类型转化成int类型。floor - 地板取整#include<stdio.h>#include<math.h>int main(){ printf("%.lf\n",floor(-2.9));//-3 printf("%.lf\n",floor(-2.1));//-3 printf("%.lf\n",floor(2.9));//2 printf("%.lf\n",floor(2.1));//2}因为其取整方式和函数名,我们称它为地板取整,什么意思呢,我们编译结果发现负数-2.9的值变成了-3,对于正数2.9的值变成了2。我们可以观察到无论是正数还是负数,在用floor函数进行取整的时候都是变小,我们观察其本质可以总结为-∞取整,如下图所示:ceil - +∞取整#include<stdio.h>int main(){ printf("%.lf\n",ceil(-2.9));//-2 printf("%.lf\n",ceil(-2.1));//-2 printf("%.lf\n",ceil(2.9));//3 printf("%.lf\n",ceil(2.1));//3}当我们编译运行程序,可以观察到负数-2.9变为-2,-2.1变为-2,正数2.9变为3,2.1变为3。我们可以观察到ceil函数的取整,结果都会在原来的基础上变大一个整数位,我们总结出该取整方式为+∞取整,如下图所示:round - 四舍五入取整是的你没有看错,与我们平常思维方式相同的四舍五入取整来了,上代码:#include<math.h>int main(){ printf("%.lf\n",round(-2.9));//-3 printf("%.lf\n",round(-2.1));//-2 printf("%.lf\n",round(2.9));//3 printf("%.lf\n",round(2.1));//2}对于这种取整方式,没什么好说的,就是按照我们平时的思路来,例如当值2.9时,值为3,当值为2.1时,值为2。在当前情况下,凡取整的值大于等于2.5,得出的结果都会变为3。% 操作符概念:如果a和d是两个自然数,d非零,可以证明存在两个唯一的整数 q 和 r,满足 a = q*d + r 且0 ≤ r < d。其中,q 被称为商,r 被称为余数。对于此部分我们依旧是从正数和负数两方面进行剖析:% 操作符对正数#include<stdio.h>int main(){ int a = 10; int d = 3; printf("%d\n",a%d);//1 //因为:a=10,d=3,q=3,r=1 0<=r<d(3) //所以:a=q*d+3 -> 10=3*3+1 return 0;}-代码:基于概念,我们可以理解当前代码的意思(详情见注释)。但我们还有另一种理解方式:% 操作符,关注的是除法后的余数,例如代码中的10%3,我们也可以理解为商3余1,相对于概念,这种方式更加容易接受一些。Warning:操作符两端的操作数必须是整数!!!% 操作符对负数int main(){ int a = - 10; int d= 3; printf("%d\n",a%d);//-1} 很显然,结果不满足定义中的0<=r<d,故后来就有了一个修订版的定义:如果a和d是两个自然数,d非零,可以证明存在两个唯一的整数 q 和 r,满足 a = q*d + r , q 为整数,且0 ≤ |r| < |d|。其中,q 被称为商,r 被称为余数。根据定义,这里的结果也能解释了,即-10 = (-3)*3+(-1)。在C语言中,%本质为取余,余数的大小,本质取决于商q的,而商都取决于除法运算的取整规则。在对于正数的取余和取模在C语言中是相同的,我们发现对于向0取整和向-∞的取整在正数上是同向的,但是对于负数上就完全不同了,因此我们平时遇到的大多都是整数取模,并没有做太多解释。移位操作符>> <<(以后讲解)位操作符& ^(以后讲解)赋值操作符= += -= *= /= &= ^= |= >>=由于赋值操作符便于理解,我们挑两个讲一下(详情见注释):int main(){ int a = 10;//创建变量,并初始化 a = 20;//赋值 a = a+5//等价于 a+=5 a = a-5//等价于 a-=5}单目操作符! 逻辑反操作- 负值+ 正值& 取地址sizeof 操作数的类型长度(以字节为单位)~ 对一个数的二进制按位取反-- 前置、后置--++ 前置、后置++* 间接访问操作符(解引用操作符)(类型) 强制类型转换我们常见的操作符比如+都有两个操作数,表示为左操作数+右操作数,这种操作符叫做双目操作符。单目操作符其实就是只有一个操作数的。在这里,对于!,-,+等操作符都便于理解,而对于&和*我打算之后在指针部分讲解,这里我们着重讲一下--,和++操作符(详情见注释):#include<stdio.h>int main(){ int a = 10; int b = ++a;//前置++,先++后使用 //a=a+1,b=a printf("a=%d b=%d\n",a,b);//11 11 --------------------------------- int a = 10; int b = a++;//后置++,先使用,后++ //b=a,a=a+1 printf("a=%d b=%d\n",a,b);//11 10 --------------------------------- int a = 10; int b = --a;//前置--,先--后使用 //a=a-1,b=a printf("a=%d b=%d\n",a,b);//9 9 --------------------------------- int a = 10; int b = a--;//后置--,先使用,后-- //b=a,a=a-1 printf("a=%d b=%d\n",a,b);//10 9}关系操作符> >= < <= !=(不相等) ==(相等)前几个操作符,也就是对应的大于,大于等于,小于,小于等于等比较关系的操作符,这里我们讲一下后两个操作符。例1int main(){ int a = 3; int b = 3; if(a!=b) { printf("hehe\n"); } if(a==b) { printf("haha\n"); } //结果为hehe}运行结果如下: 观察代码,很简单,判断a和b是否相等,如果相等则输出haha,若不相等输出hehe,因为c此处a和b都等于3,所以打印结果为hehe。例2#include<stdio.h>int main(){ char arr1[] = "abcdef"; char arr2[] = "abcdef"; if(arr1==arr2) { printf("==\n"); } else { printf("!=\n"); }}我们知道用==和!=可以判断是否相等,那么对于字符串呢?他们是否相等,当我们编译后,发现它们是不相等的!因为arr1和arr2是字符串首元素地址,开辟的空间不同,所以地址当然不同,如果要比较两个字符串的大小可以用strcmp函数,接下来看修改后的代码:#include<stdio.h>#include<string.h>int main(){ char arr1[] = "abcdef"; char arr2[] = "abcdef"; if(strcmp(arr1,arr2)==0) { printf("==\n"); } else { printf("!=\n"); }}再次运行:对于strcmp这个函数使用时需要应用头文件#include<string.h>,如果返回的值为0,则两个字符串相等。 逻辑操作符&& - 逻辑与 - 并且 || - 逻辑或 - 或者int main(){ int a= 3; int b = 0; int c = a && b; printf("%d\n",c);//真为1,假为0 if(a&&b) { printf("hehe\n"); } if(a||b) { printf("haha\n); }}运行得:分析:&&的返回值是这样规定的,如果两个数都为真,则值为1,反之则为0。对于本代码由于a&&b为0,故不打印hehe,||的值是有一个为真则为真,值为1,反之为0。这里由于a||b为真,所以打印haha。条件操作符exp1?exp2:exp3#include<stdio.h>int main(){ int a = 10; int b = 0; b = (a>5?3:-3); printf("%d\n",b);//3 return 0;}分析:条件操作符使用时先判断表达式1,如果表达式1结果为真,则输出第一个值,否则为第二个值,改题中因为a>10,所以打印结果为3。当然,这段代码也可以用if else语句来表示:#include<stdio.h>int main(){ int a = 10; int b = 0; if(a>5) { b=3; } else { b=-3; } printf("%d\n", b);}逗号表达式exp1, exp2, exp3, …expN#include<stdio.h>int main(){ int a=3; int b=5; int c=0; int d= (a+=2,b=b-c+a,c=a+b); // a=5 b=10 c=5+10 printf("%d\n",d);}分析:对于逗号表达式其特点为从左往右依次计算,整个表达式的结果是最后一个表达式的结果,因此在代码中d的值也就是15。下标引用、函数调用和结构成员[] () . ->对于这类操作符我们讲解一下[ ]操作符:#include<stdio.h>int main(){ int arr[10] = {0}; arr[4]=5; return 0;}分析:对于上述代码就是引用下标4,将arr[4]的位置上赋值5。和一些操作符相同,[ ]也有两个操作数,例如arr 和 4是两个操作数,对于这个代码写成4[arr]也可以,但是这种写法不仅让人难以理解,而且比较挫,我们可千万不要写出这样的代码!!!11. 常见关键字C 语言标准中规定了32个关键字,而在之后C99的标准下又增加了五个关键字,anduin这次对大家进行归纳的是C标准中的32个关键字,我们根据其特性,可以把它分为几类: 数据类型关键字(12个)char:声明字符型变量或函数short:声明短整型或函数Int :声明整型变量或函数long :声明长整型变量或函数signed:声明有符号类型变量或函数unsigned:声明无符号整形变量或函数foat:声明浮点型变量或函数double:声明双精度变量或函数struct:声明结构体变量或函数union:声明共用体(联合)数据类型enum:声明枚举类型void:声明函数无返回值或无参数,声明无类型指针控制语句关键字(12个)1.循环控制(5个)for:一种循环语句do:循环语句的循环体while :循环语句的循环条件break:跳出当前循环continue:结束当前循环,开始下一轮循环2.条件语句(3个)if:条件语句else:条件语句否定分支goto:无条件跳转语句3.开关语句(3个)switch:用于开关语句case:开关语句分支default:开关语句中的"其他"分支4.返回语句(1个)return:函数返回语句(可以带参数,也可以不带参数)5.存储类型关键字(5个)auto:声明自动变量,一般不使用extern:声明变量实在其他文件中声明register:声明寄存器变量static:声明静态变量typedef:用以给数据类型取别名(但是该关键字被分到存储关键字分类中,虽然看起来没什么相关性)注意:存储关键字,不可以同时出现,也就是说,在一个变量定义的时候,只能有一个。6.其它关键字(3个)const:声明只读变量sizeof:计算数据类型长度volatile:说明变量在程序执行中可被隐含地改变这里anduin带大家有选择性的,讲解几个关键字,若没有讲到日后我们一一讲解:autoauto 从字面意思来看就是自动的意思 它也被成为自动变量局部变量都是自动创建,自动销毁的,所以局部变量都是auto修饰的。int main(){ auto int a = 10;//局部变量都是auto类型的,因此auto基本会被省略 return 0;}typedef本质本质:类型重命名使用方法#include<stdio.h>typedef unsignde int u_int;int main(){ u_int x = 0; return 0;}分析:当我们在写代码时,一些代码类型很长,例如无符号整型unsigned int或者结构体,指针等,这时我们就可以用typedef对它进行类型重命名,本段代码中就是用了typedef来重命名unsigned int为u_int。作用对类型重命名的一种解决方案,让我们在面临冗长的类型命名方面上更加简便,可以对一些不太好理解的数据类型进行简化。register我们先想想,数据在计算机上可以存放在哪里呢?1.内存2.硬盘3.高速缓存4.寄存器存储金字塔寄存器存在的本质从硬件层面上,提高计算机的运算效率。当读取数据时,计算器先去寄存器中读取,如果没有读取到,再去高速缓存区中读取,最后才是内存,而且在cpu再读取寄存器中的数据时,内存->高数缓存区(cache),cache->寄存器,这个数据传递过程会持续进行,大大提高效率!register 修饰变量也就是相同的原理,尽量把所修饰变量,放入CPU寄存区中,从而达到提高效率的目的。#include<stdio.h>int main(){ register int a = 10; return 0;}register 修饰什么变量register可不是什么变量都适合修饰的,要知道寄存器的价格是很昂贵的,register所修饰的变量也得"精挑细选"一番。局部变量(全局变量由于其特性会导致CPU寄存器被长时间占用)不会被写入的(写入就需要写回内存,register本身就是快速读取,后续还要读取检测的话,就与原目的背道而驰了)高频被读取的变量(俗话说把钱用在刀刃上,存入了寄存器,当然要经常使用的)如果要使用,不要大量使用,寄存器的数量是有限的!小科普register修饰的变量,不能取地址!!!#include<stdio.h>int main(){ register int a = 0; printf("&a = %p\n", &a); return 0;}编译运行: 分析:因为register的作用,变量a已经被放入寄存器中了,你怎么取地址呢?结语以上就是初识C语言中篇的内容,虽然只有两个专题,但是内容其实也是很多的,希望我的文章对你有帮助,如果大家觉得anduin写的还可以的话,请点赞+收藏哦!你们的肯定就是对我最大的鼓励!今天也是高考第一天,祝广大学子辛勤奋战在学海,汗水扬起成功帆!愿大家都可以金榜题名!————————————————版权声明:本文为CSDN博主「ExplorerAnduin」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/m0_67867172/article/details/125163589
-
1、函数的优点:(1)复用代码(2)隐藏实现细节(3)提高可维护性(4)提高可读性便于调试2、函数的创建:def 函数名([输入参数])函数体[return xxx]3、函数的参数传递:(1)函数调用时的参数传递:位置实参:根据形参对应的位置进行实参传递,位置对应例如def fuc1(a,b),调用时fuc1(10,20)关键字实参:根据形参名称进行实参传递,例如def fuc1(a,b),调用时fuc1(b=10,a=20)(2)如果是不可变对象,在函数体内的修改不会影响实参的值如果是可变对象,在函数体内的修改会影响实参的值4、函数的返回值:(1)函数返回多个值时,结果为元组(2)函数返回一个值时,结果为原值(3)函数没有返回值时,省略return5、函数的参数定义:(1)函数定义默认值参数:函数定义时,给形参设置默认值,只有与默认值不符的时候才需要传递实参。只传一个参数,未被定义的参数未默认值。默认值参数注意一定要放在其他需要传递实参的形参最后。(2)个数可变的位置参数:使用*定义,结果为一个元组,例如def fun1(*args)个数可变的关键字形参:使用**定义,结果为一个字典,例如def fun1(**args)如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后。 Python先匹配位置实参和关键字实参,再将余下的实参都收集到最后一个形参中。
-
Lua分为主要三类运算符,分别是算术运算符,关系运算符,逻辑运算符,还有特殊运算符。1、算术运算符有: + (加) -(减) *(乘) /(除) %(取模) ^(求幂) -(符号)来看一个例子:test6.luanum1 = 4 ;num2 = 2 ;print(num1+num2);print(num1-num2);print(num1*num2);print(num1/num2);print(num1%num2);print(num1^num2);print(-num1);解释运行:lua test6.lua结果:6282.0016.0-42、关系运算符有: ==(等于) ~=(不等于) >(大于) <(小于) >=(大于等于) <=(小于等于)当比较结果成立返回true,否则返回false来看一个例子: test6.luanum = 1 ;num1 = 1;num2 = 2;num3 = 3; num4 = 4;num5 = 5;num6 = 6;ret = num1 == num2 ;print(ret);ret = num1 ~= num2 ; print(ret);ret = num3 > num2 ;print(ret);ret = num4 < num3 ; print(ret);ret = num5 >= num6 ;print(ret);ret = num1 <= num ;print(ret);解释运行:lua test6.lua结果:falsetruetruefalsefalsetrue3、逻辑运算符有: and(逻辑与) or(逻辑或) not(逻辑非)假设有A和B,如果A and B, 为真返回A,为假返回B 假设有A和B ,如果A or B , 为真返回A ,为假返回B假设有A和B ,如果 not A , 为真返回true ,为假返回false来看一个例子:test6.luanum1 = 100 ;num2 = 200 ;num3 = 0 ;ret = num1 and num3 ; print(ret);ret = num1 or num3 ; print(ret);ret = not num1 ;print(ret);ret = not(num1 and num2);print(ret);解释运行:lua test6.lua结果:0100falsefalse4、特殊运算符 .. 表示连接两个字符串 #表示返回字符串或者表的长度(注意,这里的长度不包括'\0')案例: test6.lua解释运行: lua test6.lua--定义两个字符串str1 = "Hello";str2 = "World";--连接两个字符串ret = str1..str2;print(ret);--获取连接后的字符串的长度str_length = #ret ;print(str_length);结果:HelloWorld10当然,lua的运算符也是有优先级的,优先级从高到底的顺序为:^ not -(负号) * / + - .. < > <= >= ~= == and or
-
上一章: 一.准备出发 二.编程基础 三. 数字类型的数据1.Python中的数据类型 python中有6种主要的内置数据类型:数字、字符串、列表、元组、集合和字典。 *列表、元组、集合和字典都是容器类型,只不过容器之间的内部结构不同。 不同的数据类型在计算机内部存储时会有所不同。不同的数据类型有时候不兼容,需要进行类型转换才可以计算,相同的数据类型是可以进行计算的2. 数字类型 有4种数字类型:整数类型、浮点类型、复数类型和布尔类型。 (1)整数类型为int类,表示的是不带小数的数字。有四种进制表示方式,分别是十进制、二进制、八进制和十六进制。 (2)浮点类型为float类,有两种表示方式,一是小数,二是科学技术法。 (3)复数类型为complex类。 在计算机中被表示为a+bj,其中a称为实部,b称为虚部,j称为虚数单位。 两个复数可以进行相加,实部和实部相加,虚部和虚部相加,形成新的复数。 (4)布尔类型为bool类,只有两个值:True和False 布尔类型属于整数类型,或说布尔类型是整数类型的一个子类。 Python任何类型的数据都可以通过bool()函数转换为布尔值,那些“没有的”、“空的”值会被转换成False,反之转换为True。3. 数字类型的相互转换 两种:隐式类型转换(自动转换)、显式类型转换(非自动) 比如,使用布尔类型的函数转换就是显式类型转换 <1>隐式类型的装换 看一个例子 <2>显式类型的装换 除复数外,三种数字类型如整数、浮点和布尔都有自己的转换函数,分别是int()、float()、和bool()函数 四.运算符1.算术运算符 主要是针对数字类型的运算,但是有些运算符也可以用于字符串以及列表类型的运算。 *注意除和地板除法区别,除结果为float类型,地板除法结果为整数类型。注意下述例子中负数的地板除,注意True的大小写,注意True被当作整数1参与运算。2.比较运算符 也称为关系运算符,结果为布尔值,即True或False 注意下方例子中浮点数与整数都可以进行比较3.逻辑运算符 “逻辑与”与“逻辑或”具有短路特征 注意下方例子,在不进行短路计算,结果不确定时,f1()函数会被调用。而在进行短路计算,有确定结果时,f1()函数不会被调用。【def f1(): #定义一个函数,冒号后为函数内容】5.位运算符 在计算机中,数据按照字节进行存放,1个字节为8位二进制数,此8位二进制数可以按位进行计算。 (1) ~ 取反 ,二进制数,不是0就是1,0取反就是1,1取反就是0。但!错啦!具体运算比较复杂,涉及到原码、补码、反码的问题。 公式:~a = (a + 1) x -1 ,比如下面例子中a十进制数9,则~a为-10,如a十进制数为-9,则~a为10 ❶ 所以,你知道正负数的原码、补码、反码分别如何计算吗?❷你知道在上述9和-10的例子中,按位取反具体是如何运算的吗? 【请耐心阅读,文末为大家解答哦~】 (2) & :如果两个位都为1的情况下,结果为1,只要一个为0,结果就位0 (3) | :只有一个为1的情况下,结果就为1 (4) ^ :如果一个是0,一个是1,结果就是1;如果都是为1,或者都是为0,结果为0 (5)>>右移:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1 如 00001010>>2=00000010; 10001010>>3=11110001 右移一位相当于除2,右移n位相当于除以2的n次方。这里是取商哈,余数就不要了。 (6)<< 左移:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。 要求右操作数必须是非负值,在数字没有溢出的前提下,对于正数和负数,左移一位都相当于乘以2的1次方,左移n位就相当于乘以2的n次方。 若a=15,即二进制数00001111,左移2位得00111100,没有1溢出,则左移两位相当于15乘2^2,15<< 2=60,即乘了4,即十进制数60。以下是左移两位溢出的高位中包含1的情况,64<<2为256。127<<2为5086.赋值运算符7.运算符的优先级———————————————————————————————————今天的学习就到这里,一起来看下帖中的2个问题。❶ 问:你知道正负数的原码、补码、反码分别如何计算吗?首选请注意分清下概念:取反:逻辑非“!”,逻辑取反, false变true,true变false,在C中,只要不是0就是真,所以!5值是0反码:正数的反码是其本身,对于负数其符号位不变其它各位取反(0变1,1变0)按位取反(~): 按位取反1变0,0变1。好了,现在解决问题疑问,请看机器数、真值、原码、反码、补码的相关定义1、机器数一个数在计算机中的二进制表示形式,叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号,正数为0,负数为1.比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是00000011。如果是 -3 ,就是 10000011 。那么,这里的 00000011 和 10000011 就是机器数。2、真值机器数的第一位是符号位,后边才是真正的数值,所以机器数的形式值就不等于真正的数值。例如上面的有符号数10000011,其最高位1代表负,其真正数值是 -3 而不是形式值131(10000011转换成十进制等于131)。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。例:0000 0001的真值 = +000 0001 = +11000 0001的真值 = –000 0001 = –13. 原码原码就是符号位加上真值的绝对值,即用第一位表示符号,其余位表示值。比如如果是8位二进制:[+1](原码) = 0000 0001[-1](原码) = 1000 0001第一位是符号位。因为第一位是符号位,所以8位二进制数的取值范围就是:[1111 1111 , 0111 1111]。即[-127 , 127]原码是人脑最容易理解和计算的表示方式。4. 反码反码的表示方法是: 正数的反码是其本身,负数的反码是在其原码的基础上,符号位不变,其余各个位取反。[+1] = [00000001](原码)= [00000001](反码)[-1] = [10000001](原码)= [11111110](反码)可见如果一个反码表示的是负数,人脑无法直观的看出来它的数值。通常要将其转换成原码再计算。5. 补码补码的表示方法是:正数的补码就是其本身,负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1 (即在反码的基础上+1)。[+1] = [00000001](原码) = [00000001](反码) = [00000001](补码)[-1] = [10000001](原码) = [11111110](反码) = [11111111](补码)对于负数,补码表示方式也是人脑无法直观看出其数值的。通常也需要转换成原码在计算其数值。❷你知道在上述例子中,按位取反具体是如何运算的吗?如何得到9按位取反为-10,10按位取反为-9的?(1)正数9按位取反——>(~9),计算步骤如下:正数原码=反码=补码所以9的原码/反码/补码: 0000 1001对补码取反 1111 0110(符号位一起取反)对其取反码: 1000 1001(符号位不变)取补码: 1000 1010(反码+1)最终结果 1000 1010,即-10(2)负数-10按位取反——>(~10)正数原码=反码=补码-10 原码:1000 1010-10反码: 1111 0101(符号位不变)-10补码: 1111 0110(反码+1)补码取反:0000 1001(符号位一起取反)正好得到一个整数,正数原码、反码、补码都一样所以最后结果 0000 1001,二进制为-9特殊:0按位取反,即(~0)为-1总结:按位取反公式:~a = (a + 1) x -1下一章:...
-
如果构造函数只接受一个实参,则它实际上定义了转换为此类类型的隐式转换机制。这种构造函数又叫转换构造函数(converting constructor)。能通过一个实参调用的构造函数定义了一条从构造函数的参数类型向类类型隐式转换的规则。只允许 一步类类型转换抑制构造函数定义的隐式转换将构造函数声明为 explicit加以阻止explicit关键字只允许出现在类内的构造函数声明处(只对一个实参的构造函数有效)explicit构造函数只能用于直接初始化,不能将explicit构造函数用于拷贝形式的初始化过程。Sales_data item1(null_book); //正确,直接初始化Sales_data item2 = null_book; //错误:不能将 explicit 构造函数用于拷贝形式的初始化过程尽管编译器不会将explicit的构造函数用于隐式转换过程,但是我们可以使用这样的构造函数 显式地强制进行转换。
推荐直播
-
华为云码道 × 仓颉编程:工程化AI编码探索2026/05/27 周三 19:00-21:00
刘俊杰-华为云仓颉语言专家/李炎-华为云码道技术专家/王智鹏-OpenCangjie开源社区发起人
本场直播围绕华为云仓颉语言与华为云码道的深度结合,展示华为云智能编程从零基础到高效落地的完整生态能力。以华为云码道为引擎,仓颉语言为载体,带给大家日常提效、趣味创新到极速量产的开发体验。
即将直播
热门标签