首页 文章 精选 留言 我的

精选列表

搜索[基础搭建],共10000篇文章
优秀的个人博客,低调大师

python学习之路——基础语法篇(2)之list

1. 定义 定义一个列表的方法有三种: a = ['zhangsan', 18, 'male'] # 第一种,直接用[] b = list(['zhangsan', 18, 'male']) # 第二种,用list函数,也可以写成b = list([1, 2, 3]) b = a # 第三种,用一个列表初始化另一个列表 c = a + b # 与第三种类似,可以用两个列表相加来初始化另一个列表 print(c)# ['zhangsan', 18, 'male', 'zhangsan', 18, 'male'] 需要注意的是第三种方法的赋值是浅拷贝,所以在修改数据时可能会出现问题:: a = ['zhangsan', 18, 'male', 'handsome', 100] b = a #浅拷贝 print(a,b)# a=['zhangsan', 18, 'male', 'handsome', 100] b=['zhangsan', 18, 'male', 'handsome', 100] b[0]='lisi' print(a,b)# a=['lisi', 18, 'male', 'handsome', 100] b=['lisi', 18, 'male', 'handsome', 100] 可以看到,当修改了b里面的第一个元素的值以后,a的值也被修改了,因为a与b共用同一块内存空间,解决办法就是使用深拷贝,使用深拷贝时要引入copy模块: import copy a = ['zhangsan', 18, 'male', 'handsome', 100] b = copy.deepcopy(a) #深拷贝 print(a,b)# a=['zhangsan', 18, 'male', 'handsome', 100] b=['zhangsan', 18, 'male', 'handsome', 100] b[0]='lisi' print(a,b)# a=['zhangsan', 18, 'male', 'handsome', 100] b=['lisi', 18, 'male', 'handsome', 100] list中的变量可以是不同的数据类型,类似与C++中的数组,下标是从1开始,但是这个数组更灵活一些,可以存储各种数据类型的数据。 2.查 list的查找可以通过各种切片操作来实现,切片一个有三个参数,第一个参数是起始下标(包括该值),第二个是终止下标(不包括该值),第三个是步长(默认为1): a = ['zhangsan', 18, 'male', 'handsome', 100] # 切片方法 print(a[0]) # 取出下标为0的元素,zhangsan # print(a[10]) # 下标越界,会报错 print(a[1:3]) # 左边包括,右边不包括,[18, 'male'] print(a[1:-1]) # -1表示最后一个元素,由于右边不包括故不取最后一个值,即取到倒数第二个值,[18, 'male', 'handsome'] # 省略值表示全取 print(a[:]) # 从第一个开始取到最后一个,['zhangsan', 18, 'male', 'handsome', 100] print(a[1:]) # 取到最后一个值,[18, 'male', 'handsome', 100] print(a[:-1]) # 从第一个开始取到倒数第二个,['zhangsan', 18, 'male', 'handsome'] # 步长为负表示从右往左开始取值,第一个元素是起始下标(从左往右看时的下标) print(a[1:-1:1])# 从左到右数一下,从下标为1开始到最后一个元素(不包括)结束,[18, 'male', 'handsome'] print(a[1::2]) # 从左到右数两下,[18, 'handsome'] print(a[3::-2]) # 从右到左数两下,下标为3的元素是handsome,故['handsome', 18] print(a[2::-1]) # 从右到左数一下,下标为2的元素是male,故['male', 18, 'zhangsan'] 3.增 像列表添加元素主要有两个方法,append与insert: a = ['zhangsan', 18, 'male', 'handsome', 100] a.append('aaa') # append中的参数放的是要插入的值,默认插到列表的最后面,若append的是字典,会直接将整个字典插入到列表的表尾 print(a) # ['zhangsan', 18, 'male', 'handsome', 100, 'aaa'] a.insert(1,"bbb")# 第一个参数是插入的位置,第二个参数是插入的值 print(a) # ['zhangsan', 'bbb', 18, 'male', 'handsome', 100, 'aaa'] 还有一个是对列表的扩展,使用的是extend方法,extend方法的参数不能是单个的值: a = ['zhangsan', 18, 'male', 'handsome', 100] b = ['aaa','bbb'] a.extend(b) # 将b的内容加在a的后面,extend的参数不能是单个的值 print(a) # ['zhangsan', 18, 'male', 'handsome', 100, 'aaa', 'bbb'] b = {'zhang':11,'li':22} a.extend(b) # 将b的内容加在a的后面,如果参数是字典的话,只会将键加入列表中 print(a) # ['zhangsan', 18, 'male', 'handsome', 100, 'aaa', 'bbb', 'zhang', 'li'] 4.删 删除列表中的元素共有4种方法: a = ['zhangsan', 18, 'male', 'handsome', 100] a.remove('zhangsan') # remove中放的是要删除的内容 或者 a.remove(a[0]) print(a) # [18, 'male', 'handsome', 100] b = a.pop(1) # pop中放的是索引值,并返回删掉的值 若不指定就默认删除最后一个 print(a) # [18, 'handsome', 100] print(b) # male del a[0] #del既可以删除某个固定的内容,也可以删除整个列表 print(a) # ['handsome', 100] a.clear() # clear将整个列表置为空表 print(a) # [] del a # print(a) # 当a被删除以后再输出会报错 5.修改 修改与查是类似的,只需要将元素重新赋值即可: a = ['zhangsan', 18, 'male', 'handsome', 100] a[0]='lisi' 6.常见函数 count:统计某个元素出现次数 a = [1,2,3,4,3,5,2,3].count(3) print(a) # 3 index:获取某个元素第一次出现的下标 a = [1,2,3,4,3,5,2,3] print(a.index(3)) # 2 print(a.index(0)) # 元素不存在时会报错 reverse:逆序 a = [1,2,3,4,3,5,2,3] a.reverse() print(a) # [3, 2, 5, 3, 4, 3, 2, 1] sort与sorted:排序,默认为升序,sort是直接对原列表进行排序,sorted是返回排序后得到的新列表 a = [1,2,3,4,3,5,2,3] a.sort(reverse=True) #reverse默认为False即升序,reverse=True:降序 print(a) # [5, 4, 3, 3, 3, 2, 2, 1] b = sorted(a) # 默认为升序 print(b) # [1, 2, 2, 3, 3, 3, 4, 5] b = sorted(a, reverse=True) print(b) # [5, 4, 3, 3, 3, 2, 2, 1] 记录自己的python学习之路,错误的地方欢迎指正~~

优秀的个人博客,低调大师

Linux基础命令---uname显示计算机信息

uname uname指令用来显示计算机硬件以及操作系统的相关信息,例如计算机名、内核版本、硬件架构。 此命令的适用范围:RedHat、RHEL、Ubuntu、CentOS、Fedora、SUSE、openSUSE。 1、语法 uname[选项] 2、选项列表 -a|--all 显示所有的信息 -s|--kernel-name 显示内核名字 -n|--nodename 显示主机名 -r|--kernel-release 显示内核发型版本号 -v|--kernel-version 显示内核版本 -m|--machine 显示计算机硬件架构名字 -p|--processor 显示cpu类型 -i|--hardware-platform 显示硬件平台 -o|--operating-system 显示操作系统 --help 显示帮助信息,并且退出 --version 显示版本信息,并且退出 3、实例 显示系统所有信息 [root@localhostntop-4.0.1]# uname–a//显示所有信息 Linuxlocalhost.localdomain2.6.32-431.el6.i686#1SMPFriNov2200:26:36UTC2013i686i686i386GNU/Linux

优秀的个人博客,低调大师

python基础教程:包的创建及导入

包是一种通过用“带点号的模块名”来构造 Python 模块命名空间的方法。 例如,模块名 A.B 表示 A 包中名为 B 的子模块。正如模块的使用使得不同模块的作者不必担心彼此的全局变量名称一样,使用加点的模块名可以使得 NumPy 或 Pillow 等多模块软件包的作者不必担心彼此的模块名称一样。 假设你想为声音文件和声音数据的统一处理,设计一个模块集合(一个“包”)。由于存在很多不同的声音文件格式(通常由它们的扩展名来识别,例如:.wav, .aiff, .au),因此为了不同文件格式间的转换,你可能需要创建和维护一个不断增长的模块集合。 你可能还想对声音数据还做很多不同的处理(例如,混声,添加回声,使用均衡器功能,创造人工立体声效果), 因此为了实现这些处理,你将另外写一个无穷尽的模块流。这是你的包的可能结构(以分层文件系统的形式表示): __init__.py Initialize the sound package formats/ Subpackage for file format conversions __init__.py wavread.py wavwrite.py aiffread.py aiffwrite.py auread.py auwrite.py ... effects/ Subpackage for sound effects __init__.py echo.py surround.py reverse.py ... filters/ Subpackage for filters __init__.py equalizer.py vocoder.py karaoke.py ... 当导入这个包时,Python搜索 sys.path 里的目录,查找包的子目录。 The init__.py files are required to make Python treat directories containing the file as packages. This prevents directories with a common name, such as string, unintentionally hiding valid modules that occur later on the module search path. In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all variable, described later. 包的用户可以从包中导入单个模块,例如: 这会加载子模块 sound.effects.echo 。但引用它时必须使用它的全名。 导入子模块的另一种方法是 这也会加载子模块 echo ,并使其在没有包前缀的情况下可用,因此可以按如下方式使用: 另一种形式是直接导入所需的函数或变量: 同样,这也会加载子模块 echo,但这会使其函数 echofilter() 直接可用: 请注意,当使用 from package import item 时,item可以是包的子模块(或子包),也可以是包中定义的其他名称,如函数,类或变量。 import 语句首先测试是否在包中定义了item;如果没有,它假定它是一个模块并尝试加载它。如果找不到它,则引发 ImportError 异常。 相反,当使用 import item.subitem.subsubitem 这样的语法时,除了最后一项之外的每一项都必须是一个包;最后一项可以是模块或python包,但不能是前一项中定义的类或函数或变量。 从包中导入 * 当用户写 from sound.effects import * 会发生什么?理想情况下,人们希望这会以某种方式传递给文件系统,找到包中存在哪些子模块,并将它们全部导入。这可能需要很长时间,导入子模块可能会产生不必要的副作用,这种副作用只有在显式导入子模块时才会发生。 唯一的解决方案是让包作者提供一个包的显式索引。import 语句使用下面的规范:如果一个包的 init__.py 代码定义了一个名为 __all 的列表,它会被视为在遇到 from package import 时应该导入的模块名列表。在发布该包的新版本时,包作者可以决定是否让此列表保持更新。包作者如果认为从他们的包中导入 的操作没有必要被使用,也可以决定不支持此列表。例如,文件 sound/effects/__init__.py 可以包含以下代码: 这意味着 from sound.effects import * 将导入 sound 包的三个命名子模块。 如果没有定义 __all__,from sound.effects import * 语句 不 会从包 sound.effects 中导入所有子模块到当前命名空间;它只确保导入了包 sound.effects (可能运行任何在 __init__.py 中的初始化代码),然后导入包中定义的任何名称。这包括 __init__.py` 定义的任何名称(以及显式加载的子模块)。它还包括由之前的 import 语句显式加载的包的任何子模块。思考下面的代码: import sound.effects.surround from sound.effects import * 在这个例子中, echo 和 surround 模块是在执行 from...import 语句时导入到当前命名空间中的,因为它们定义在 sound.effects 包中。(这在定义了 all 时也有效。) 虽然某些模块被设计为在使用 import * 时只导出遵循某些模式的名称,但在生产代码中它仍然被认为是不好的做法。 请记住,使用 from Package import specific_submodule 没有任何问题!实际上,除非导入模块需要使用来自不同包的同名子模块,否则这是推荐的表示法。 子包参考 当包被构造成子包时(与示例中的 sound 包一样),你可以使用绝对导入来引用兄弟包的子模块。例如,如果模块 sound.filters.vocoder 需要在 sound.effects 包中使用 echo 模块,它可以使用 from sound.effects import echo 。 你还可以使用import语句的 from module import name 形式编写相对导入。这些导入使用前导点来指示相对导入中涉及的当前包和父包。例如,从 surround 模块,你可以使用: from .. import formats from ..filters import equalizer 请注意,相对导入是基于当前模块的名称进行导入的。由于主模块的名称总是 "__main__" ,因此用作Python应用程序主模块的模块必须始终使用绝对导入。 多个目录中的包包支持另一个特殊属性, path 。它被初始化为一个列表,其中包含在执行该文件中的代码之前保存包的文件 __init__.py 的目录的名称。这个变量可以修改;这样做会影响将来对包中包含的模块和子包的搜索。 虽然通常不需要此功能,但它可用于扩展程序包中的模块集。 脚注 [1] 实际上,函数定义也是“被执行”的“语句”;模块级函数定义的执行在模块的全局符号表中输入该函数名。

优秀的个人博客,低调大师

Hbase基础使用与云Hbase2.0体验

又到金三银四的季节,相信各位都已经找到适合自己的工作了~当然我也悄悄告诉你我也找到了,去到更广阔的平台 今年开始决定正式进入大数据领域工作,从事大数据方向方面的开发。因为之前我一直在游戏公司,所以我选择领域是游戏行业的大数据解决方案。目前我的工作主要是负责建立一套游戏大数据运营系统,包括一套完善的游戏数据采集,计算,落地的系统。通过开发一套游戏大数据运营系统提供给我们的游戏运营大佬们。 通过整合海量数据处理、敏捷BI、智能算法等平台能力,提高游戏日志等数据向业务价值转化的效率及智能化水平。 以前游戏大部分处理游戏日志都是把原始数据通过游戏服保存至Mysql,然后GM后台通过一定的定时逻辑运行定时统计,统计后的数据存入Mysql结果库。随着数据量的不断增长,MySQL传统关系型数据库并不能满足日益增长的数据需求。作为数据仓库需要解决高可用,分布式,存储大量数据的数据库。Hbase就是不错的选择。同时传统的数据统计计算交由Mysql的统计语句对数据进行汇总统计,加剧数据库负担,并且对实际生产环境产生一定的影响。Mysql是一款数据存储引擎,并不适合做大量的数据汇总与计算。计算应该交由专业的计算引擎去做计算【参考计算框架:MR,Spark,Flink】 HBase是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“Bigtable。 Hbase作为大数据产品家族的一员,存储底层借助Hadoop的HDFS,能够存储海量数据,同时它和mongoDB一样,也是一款NoSQL产品,但是却有一定的区别,例如列族,RowKey这些概念。下面我们来看看Hbase的架构图 HBase 一种是作为存储的分布式文件系统,另一种是作为数据处理模型的 MR 框架。因为日常开发人员比较熟练的是结构化的数据进行处理,但是在 HDFS 直接存储的文件往往不具有结构化,所以催生出了 HBase 在 HDFS 上的操作。如果需要查询数据,只需要通过键值便可以成功访问。 HBase 内置有 Zookeeper,但一般我们会有其他的 Zookeeper 集群来监管 master 和 regionserver,Zookeeper 通过选举,保证任何时候,集群中只有一个活跃的 HMaster,HMaster 与 HRegionServer 启动时会向 ZooKeeper 注册,存储所有 HRegion 的寻址入口,实时监控 HRegionserver 的上线和下线信息。并实时通知给 HMaster,存储 HBase 的 schema 和 table 元数据,默认情况下,HBase 管理 ZooKeeper 实例,Zookeeper 的引入使得 HMaster 不再是 单点故障。一般情况下会启动两个 HMaster,非 Active 的 HMaster 会定期的和 Active HMaster 通信以获取其最新状态,从而保证它是实时更新的,因而如果启动了多个 HMaster 反而增加 了 Active HMaster 的负担。 一个 RegionServer 可以包含多个 HRegion,每个 RegionServer 维护一个 HLog,和多个 HFiles 以及其对应的 MemStore。RegionServer 运行于 DataNode 上,数量可以与 DatNode 数量一致 随着 Spark 以及其社区的不断发展,Spark 及 Spark SQL 本身技术的不断成熟,Spark 在技术架构和性能上都展示出 Hive 无法比拟的优势。以前我们常用Hive进行数据分析,目前Spark结合SparkStreaming,MLib等组件能完美配合完成大数据生态圈的工作 我们通常会通过Kafka消息队列对接SparkStreaming作为消费者,根据Group去消费一组业务的Topic,主要有以下场景: Streaming实时读取Kafka数据做ETL 复杂的ETL可以实时读取HBase/Phoenix的维表数据做关联 结果数据写入HBase/Phoenix对外提供在线查询服务 现在阿里云最近在搞活动,免费1个月Hbase单节点版体验学习。借此机会赶紧学习一下~~ 白用白不用~ 赶紧撸了一台 阿里云Hbase访问控制台 通过管理开通公网访问权限,公网访问必须下载阿里云Hbase客户端,借助ECS 访问ZK地址去访问的。这个大家可以参考官方文档,我这里不做过多的描述。我们连接上去首先先来些简单操作,例如创建一张表Student: Hbase-UI 我们首先创建表,然后往里面放入数据,人名为czy年龄23的和一条人名为yejoe的,sex为0的数据。Hbase这里存数据是使用put,不是insert,mongdob使用时update,mysql使用insert,大家意思都有点大同小异,最好扫描了一下表结构。 操作记录 取出用户数据和查看表结构 统计student条数(基于RowKey),然后我们修改表结构,最多有3版本,然后再次放入数据,可以看到每次get会取出最新的数据 我们可以看到Hbase控制台查看Table Schema 通过简单学习,是不是发现Hbase原来这么强大,后续我们还会介绍Hbase读写机制,Hbase实际生产应用 ***部分图片来自阿里云Hbase

优秀的个人博客,低调大师

JAVA基础学习之-AQS的实现原理分析

AbstractQueuedSynchronizer是JUC的核心框架,其设计非常精妙。 使用了Java的模板方法模式。 首先试图还原一下其使用场景:对于排他锁,在同一时刻,N个线程只有1个线程能获取到锁;其他没有获取到锁的线程被挂起放置在队列中,待获取锁的线程释放锁后,再唤醒队列中的线程。 线程的挂起是获取锁失败时调用Unsafe.park()方法;线程的唤醒是由其他线程释放锁时调用Unsafe.unpark()实现。由于获取锁,执行锁内代码逻辑,释放锁整个流程可能只需要耗费几毫秒,所以很难对锁的争用有一个直观的感受。下面以3个线程来简单模拟一下排他锁的机制。 import sun.misc.Unsafe; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.LockSupport; public class AQSDemo { private static final Unsafe unsafe = getUnsafe(); private static final long stateOffset; private static Unsafe getUnsafe() { try { Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); return (Unsafe)field.get(null); } catch (Exception e) { } return null; } static{ try{ stateOffset = unsafe.objectFieldOffset (AQSDemo.class.getDeclaredField("state")); } catch (Exception ex) { throw new Error(ex); } } private volatile int state; private List<Thread> threads = new ArrayList<>(); public void lock(){ if(!unsafe.compareAndSwapInt(state,stateOffset,0,1)){ // 有问题,非线程安全;只作演示使用 threads.add(Thread.currentThread()); LockSupport.park(); Thread.interrupted(); } } public void unlock(){ state = 0; if(!threads.isEmpty()){ Thread first = threads.remove(0); LockSupport.unpark(first); } } static class MyThread extends Thread{ private AQSDemo lock; public MyThread(AQSDemo lock){ this.lock = lock; } public void run(){ try{ lock.lock(); System.out.println("run "); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } public static void main(String[] args) { AQSDemo lock = new AQSDemo(); MyThread a1 = new MyThread(lock); MyThread a2 = new MyThread(lock); MyThread a3 = new MyThread(lock); a1.start(); a2.start(); a3.start(); } } 上面的代码,使用park和unpark简单模拟了排他锁的工作原理。使用ArrayList屏蔽了链表多线程环境下链表的构造细节, 该代码实际上在多线程环境中使用是有问题的,发现了么? 通过上面的代码,能理解到多线程环境下,链表为什么能比ArrayList好使。 理解AQS, 其核心在于理解state和head, tail三个变量。换句话说,理解AQS, 只需理解状态和链表实现的队列 这两样东西。其使用方式就是,如果更新状态不成功,就把线程挂起,丢到队列中;其他线程使用完毕后,从队列中唤醒一个线程执行。 如果排队的线程数量过多,那么该谁首先获得锁就有讲究,不能暗箱操作,所以有公平和非公平两种策略。 越来越能理解 “编程功底,细节是魔鬼”,理解了上面的使用方式,只相当于理解了需求。那么实现上有那些细节呢? 我们通过问答的方式来阐明。 问题1: state变量为什么要用volatile关键词修饰? volatile是synchronized的轻量版本,在特定的场景下具备锁的特点变量更新的值不依赖于当前值, 比如setState()方法。 当volatile的场景不满足时,使用Unsafe.compareAndSwap即可。 问题2: 链表是如何保证多线程环境下的链式结构? 首先我们看链表是一个双向链表,我们看链表呈现的几个状态: 1. 空链表 (未初始化) head -- null tail -- null or (初始化后) head -- Empty Node tail -- Empty Node 2. 只有一个元素的链表 head -- Empty Node <-> Thread Node -- tail 也就是说,当链表的不为空时, 链表中填充者一个占位节点。 学习数据结构,把插入删除两个操作弄明白,基本就明白这个数据结构了。我们先看插入操作enq(): private Node enq(final Node node) { for (;;) { Node t = tail; if (t == null) { // Must initialize if (compareAndSetHead(new Node())) tail = head; } else { node.prev = t; if (compareAndSetTail(t, node)) { t.next = node; return t; } } } } 首先一个无限循环。 假如这个链表没有初始化,那么这个链表会通过循环的结构插入2个节点。 由于多线程环境下, compareAndSet会存在失败,所以通过循环保证了失败重试。 为了保证同步,要么依赖锁,要么通过CPU的cas。 这里是实现同步器,只能依赖cas。 这种编程结构,看AtomicInteger,会特别熟悉。 接下来看链表的删除操作。当线程释放锁调用release()方法时,AQS会按线程进入队列的顺序唤醒地一个符合条件的线程,这就是FIFO的体现。代码如下: public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } 这里unparkSuccessor()里面的waitStatus我们先忽略。这样的话,线程会从阻塞的后面继续执行,从parkAndCheckInterrupt()方法中出来。 final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC failed = false; return interrupted; } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } } 由于唤醒的顺序是FIFO, 所以通常p==head条件是满足的。如果获取到锁,就把当前节点作为链表的head节点:setHead(node), 原head节点从链表中断开,让GC回收p.next=null。 也就是说,链表的删除是从头开始删除,以实现FIFO的目标。 到这里,AQS的链表操作就弄清楚了。接下来的疑问就在节点的waitStatus里面。 问题: waitStatus的作用是什么? 在AQS, 实现了一个ConditionObject, 就像Object.wait/nofity必须在synchronized中调用一样, JUC实现了一个Object.wait/notify的替代品。这是另一个话题,这里不细说了,后面再研究一下。 最后,总结一下,本文简单分析了一下AQS的实现机制。主要参考ReentrantLock和论文《The java.util.concurrent Synchronizer Framework》。

优秀的个人博客,低调大师

python零基础应该怎样学习入门Python?

前言Python 语言应该如何入门,记得我几年前也碰到过这样的问题,当时网上随便搜了一下饥不择食的找了一些书开始啃起来,结果发现很疑惑,感觉吃力,走了很多弯路。若不得法还会降低初学者的兴趣,现在我就说说自己对python 入门的理解. 学Python和学其他的语言其实是相同的,我给新同事讲课的时候就说学编程和练武功其实是很相似,入门大致这样几步: 找本靠谱的书, 找个靠谱的师傅, 找一个地方开始练习。 学语言也是的:选一本通俗易懂的书,找一个好的视频资料,然后自己装一个IDE工具开始边学变写。下面我具体来讲讲: 1.找一本靠谱的书,难度一定要是入门级别,千万不能太复杂,不要一下子陷进去,会打乱节奏,学东西要循序渐进,不能一口吃个胖子.打个比方,学过java的同学都听过大名鼎鼎的thinking in java,这边书很厚很全,若一上来就学,肯定会吃力,时间长了就会失去兴趣,因此对初学者来说,一定要找一个通熟易懂的,简单的书。入门的书非常关键。 入门的书很多,但是我个人强烈推荐"A Byte of Python",这本书我读了2遍,作者写的思路非常清晰,对每一个知识点讲解的很到位,不多不少,刚刚好,对初学者来说,力道刚刚好。而且是全英文,对提高自己的英语水平,很有帮助. 2.找一个好的视频资源,当然若你周围有Python高手就更好了,可以多交流多请教。视频资源我推荐imooc,当然有人说还有jikexueyuan,网易公开课,这几家我都看过一些,各有千秋,我建议初学者还是选择imooc,他家的Python讲解的很仔细,而且音频的质量比较高,最关键是的可以在web上直接编程练习,都不用自己安装编译器,非常方便。居家旅行必备啊~~ 3.多编写程序,这似乎是废话,但是确实是一句实话。学编程一定要亲身去编写,没有什么捷径.一开始哪怕你把书里面的例子一字不落敲一遍,也好过你只是去看书,而不动手。 而且学Python最好是坚持编,每天抽小半个小时,学一些知识点,不断的坚持.大概快的话几个星期基本就能入门了。 以上就是我对Python入门的感悟,希望对初学者能有一点帮助,能帮到一些人少走一点弯路.也就不枉我大半夜在这里码字了~~

优秀的个人博客,低调大师

Python零基础学习笔记(三十六)—— 递归

''' 递归调用:一个函数,调用了自身,成为递归调用 递归函数:一个会调用自身的函数 凡是循环能干的事,递归都能干 ''' ''' 方式: 1、写出临界条件 2、找这一次和上一次的关系 3、假设当前函数已经能用,调用自身计算行一次的结果,再求出本次的结果 ''' #输入一个数,求 1+2+3+……+ n 的和 def sum1(n): sum = 0 for x in range(1, n + 1): sum += x return sum res = sum1(10) print("res =", res) #递归方法 def sum2(n): if n == 1: return 1 else: return n + sum2(n - 1) res1 = sum2(10) print(res1)

优秀的个人博客,低调大师

Python零基础学习笔记(三十)—— 读文件

''' 过程: 1、打开文件 2、读文件内容 3、关闭文件 ''' ''' 1、打开文件 open(path, flag[, encoding]) path:要打开文件的路径 flag:打开方式 r(read) 以只读方式打开文件,文件的描述符放在文件的开头 rb 以为进制格式打开文件用于只读,文件的描述符放在文件的开头 r+ 打开一个文件用于读写,文件的描述符放在文件的开头 w 打开一个文件只用于写入,如果该文件已经存在会覆盖,不存在则创建新文件 wb 打开一个文件只用于写入二进制,如果该文件已经存在会覆盖,不存在则创建新文件 w+ 打开一个文件用于读写,如果该文件已经存在会覆盖,不存在则创建新文件 a 打开一个文件用于追加,如果文集那存在,文件描述符将会放到文件末尾 a+ encoding:编码格式 errors:错误处理 ''' #打开文件 path = r"E:\File.txt" #f = open(path, "r", encoding = "utf-8",errors = "ignore") f = open(path, "r") ''' 2、读文件内容 ''' #读文件的所有内容 str1 = f.read() print("str1 =", str1) #读文件中指定字符数 f.seek(0) #修改描述符的位置 str2 = f.read(5) print("str2 =", str2) #读取整行,包括"\n"字符 f.seek(0) str3 = f.readline() print("str3 =", str3) #读取所有行并返回列表 f.seek(0) str4 = f.readlines() print("str4 =", str4) #读取指定字符数 f.seek(0) str5 = f.readline(20) print("str5 =", str5) #修改描述符的位置 f.seek(0) ''' 3、关闭文件 ''' f.close() ''' 完整过程 ''' #第一种 try: f1 = open(path,"r") print(f1.read()) finally: if f1: f1.close() #更为简单的方法 with open(path, "r", encoding= "gbk", errors="ignore") as f2: print(f2.read())

优秀的个人博客,低调大师

Python零基础学习笔记(二十)—— tuple元组

#创建空元组 tuple1 = () print(tuple1) #创建带有元素的元组 tuple2 = (1, 2, 3, "jjking", True) #元素类型可以不同 print(tuple2) #定义只有1 个元素的元组 tuple3 = (1 ) #后面必须加逗号 print(tuple3) print(type(tuple3)) ''' 元组元素的访问 格式: 元组名[下标] 注意:下标不能越界 ''' tuple4 = (1, 2, 3, 4, 5) print(tuple4[3]) #获取最后一个元素 print(tuple4[-1]) #获取倒数第二个元素 print(tuple4[-2]) #修改元组,实际上修改的是元素里面的数据 tuple5 = (1, 2, 3, 4, [1, 2, 3], 5) print(tuple5) tuple5[4][2] = 4 print(tuple5) #删除元组 del tuple5 #print(tuple5) 因为被删除了所以打印不出来,会报错 #元组的操作 t1 = (1 ,2, 3, 4) t2 = (5, 6) t3 = t1 + t2 print(t3) #元组重复 print(t3 *3) #判断元素是否在元组中 print( 3 in t3) #元组的截取 #格式:元组名[ 开始下标:结束下标 ] #从开始下标开始截取,到结束下标之前,默认从头到尾 print(t3[1:4]) #二维元组:元素为一维元组的元组 t4 = ((1, 2, 3), (4, 5, 6), (7, 8, 9)) print(t4) print(t4[2][1]) '''元组的方法''' #len() 返回元组中元素的个数 print(len(t4)) #max() 返回元组中的最大值 print(max(t1)) #min() 返回元祖中的最小值 print(min(t1)) #列表转元组 list2 = [1, 2, 3, 4, 5] t5 = tuple(list2) print(t5) #元组转列表 list1 = list(t3) print(list1) ''' 一旦初始化元组里面的元素就不能修改了 和列表的区别就是不可变 这就提高了数据的安全性 所以说能用元组尽量用元组 ''' #元组的遍历 for i in (1, 2, 3, 4,5): print(i)

优秀的个人博客,低调大师

Python零基础学习笔记(十五)—— list(列表)

''' 本质;一种有序的集合 格式: 列表名 = [列表选项1, 列表选项2, ...列表选项n] ''' list1 = [23, 22, 24, 22, 25] print(list1) #元素数据可以不同 list2 = [1, 233, "name", "jjking", True] ''' 列表元素的访问 取值: 格式:列表名[下标] 注意:列表下标不要越界 ''' print(list1[2]) #列表操作: #列表组合 list3 = list1 + list2 print(list3) #列表的重复 print(list2 * 5) #判断元素是否在列表中 print(1 in list2) #列表截取 [2:3) print(list2[2:3]) #二维列表 list4 = [[123],[2,2,3],[1,2,3],[4,5,6,8]] print(list4[2][2]) #列表方法 list5 = [1,2,3,4,5,6] #appeng() 在列表末尾添加新的元素 list5.append(7) print(list5) list5.append([8,9]) print(list5) #extend() 在末尾一次性追加另一个列表中的多个值 list5.extend([1,2,3]) print(list5) #insert() 在下标处添加一个元素,元数据向后顺延 list5.insert(2,10) print(list5) #pop() 删除下标处的元素,默认为最后一个下标,并返回删除的数据 list5.pop() print(list5) list5.pop(2) print(list5) print(list5.pop(2)) #remove() 移除列表中的某个元素 list5.remove(5) list5.remove([8, 9]) print(list5) #clear() 清除列表中所有的数据 list6 = [1,2,3] list6.clear() print(list6) #index() 从列表中找出某个值的第一个匹配的索引值,可以加开始和结束的下标范围 print(list5.index(2)) print(list5.index(2, 4,8)) #len() 列表中的元素 print(len(list5)) #max() 获取列表中的最大值,只能是在一维列表,不然会报错 print(max(list5)) #min() 获取列表中的最小值,只能是在一维列表,不然会报错 print(min(list5)) #count() 某元素出现的次数 print(list5.count(2)) #浅拷贝 内存地址是一样的 lis7 = list5 print(id(list5)) print(id(lis7)) #copy() 深拷贝 内存的拷贝 内存的地址是不一样的 print(id(list5.copy())) #reverse() 倒序 list5.reverse() print(list5) #sort() 从小到大排序 list5.sort() print(list5) #元组转换成列表 list8 = list((1,2,3,4)) print(list8)

优秀的个人博客,低调大师

Python零基础学习笔记(十四)—— while语句

''' while 语句: 格式: while 表达式: 语句 逻辑:当程序遇到while语句的时候,首先计算【表达式】的值 如果【表达式】的值为假,那么结束整个while语句 如果表达式的值为真,则执行【语句】,循环调用,直到为假停止 ''' #从1打印到小于5的数 num = 1 while num < 5: print("num = %d"% num) num += 1 #计算1+2+3+...+100 sum = 0 num = 1 while num <= 100: sum += num num += 1 #print("sum = %d" % sum) print("sum = %d"% sum) #打印字符串里的每一个字符 str = "My name is jjking." index = 0 while index <= len(str): print(str[index]) index += 1 运行结果: num = 1 num = 2 num = 3 num = 4 sum = 5050 M y n a m e i s j j k i n g .

优秀的个人博客,低调大师

Python零基础学习笔记(八)—— 数学功能

一定要导入math包,不然后面会报错 今日学习部分及执行结果如下图 import math # abs() 返回数的绝对值 a1 = -10 a2 = abs(a1) print(a2) #比较两个数的大小 a3 = 10 a4 = 9 print((a3>a4)-(a3<a4)) # max() 返回参数中的最大值 print(max(1,2,3,4,5)) # min() 返回参数中的最小值 print(min(1,2,3,4,5)) # pow() 求x的y次方 例如2^4 print(pow(2,4)) #round(x[, n]) x为数值,n为保留位数,n可有可无 # 四舍五入 print(round(3.576)) print(round(3.492)) #四舍五入保留位数 print(round(3.576, 1)) print(round(3.492, 2)) # math.ceil() 向上取整 print(math.ceil(8.1)) print(math.ceil(5.9)) # math.floor() 向下取整 print(math.floor(8.1)) print(math.floor(5.9)) # math.modf() 返回整数部分与小数部分 print(math.modf(12.3)) # math.sqrt() 开方 print(math.sqrt(25))

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册