定义set
emptySet = set() mySet = {'a','b','c'} tuple, 与list类似,但是是immutable的
如果你将一个list添加到set,就会报错;但是如果你将tuple添加到set是ok的,因为tuple 不可改变因此它的hash值是固定的
alist = [1,2,3] myset = () myset.add(alist) ## 这个会报错 myset.add(tuple(alist)) ##这个不会报错 如何在python中使用queue呢?实际还是个list,只要你的操作是先进先出的即可,但是pop(0) 的时间复杂度为O(N)
queue = [1,2,3] queue.append(4) ##入队列 O(1) queue.pop(0) ##出队列 O(N)
一.pta题目集
7-1 sdut-String-2 识蛟龙号载人深潜,立科技报国志(II)(正则表达式)
刚接触到正则表达式感觉还是很多陌生什么也不会,在完成多次测试后终于对使用有所了解了
正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为元字符)。
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。
正则表达式是繁琐的,但它是强大的,学会之后的应用会让你除了提高效率外,会给你带来绝对的成就感。只要认真阅读本教程,加上应用的时候进行一定的参考,掌握正则表达式不是问题。
许多程序设计语言都支持利用正则表达式进行字符串操作。
import java.util.ArrayList; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { ArrayList<String> str1 = new ArrayList<String>(); public static void main(String[] args) { Scanner input = new Scanner(System.in); boolean isEnd = false; int num = 0; int sum = 0; String str; String pattern = [0-9]+; Pattern r = Pattern.compile(pattern); while(isEnd == false) { str = input.nextLine(); if(str.
以java为例,其illegalstateexception该异常表示,当前对客户端的响应已经结束,不能在响应已经结束(或说消亡)后再向客户端(实际上是缓冲区)输出任何内容。
在一次响应commit之前,所有的内容输出都将写入servlet引擎的缓冲区(tomcat或weblogic的内容空间),而在commit之后,上一次response向缓冲区写入的内容,将清空。由于servlet在没有设置单线程的情况下(使用Single-Threaded Model,servlet实现SingleThreadModel接口,jsp使用<%@ page isThreadSafe=“false”%>),是多线程的,所以上面所说的缓冲区,都将是该response所属的线程私有的内存空间。有了这个概念,将可以分析碰到的关于servlet多线程的很多问题。如果不能确认response是否已经committed。可以调用response.isCommitted()来判断。导致这个错误最普遍的原因是,jsp有编译错误。web.xml中上次写错
<url-pattern>*do</url-pattern> 修改后 <url-pattern>*.do</url-pattern> 中间少了. 没有按正确规则书写后缀
元编程技术综述 来源 https://zhuanlan.zhihu.com/p/399035868
# 作者简介 # Yannis Lilis 博士是欧洲最大的汽车租赁公司的高级程序员,兼职在克里特大学的计算机科学系任客座讲师,在数学及应用数学系任兼职教师,同时兼任计算机科学研究所(ICS)FORTH 实验室的研究员。他的研究兴趣包括软件工程、机器学习、计算机视觉、人工智能、分布式系统等等。他总计发表了 20 篇会议 / 期刊等出版物,其中超过半数为元编程相关技术文章。
Anthony Savidis 教授是克里特大学计算机科学系的正教授和计算机科学研究所(ICS)FORTH 和 HCI 实验室的研究员。他的研究兴趣包括:编程语言、软件工程、用户界面开发工具、特定领域工具以及面向学习者的交互式编程环境。他参与了 35 项欧洲和国家研发项目,发表了 150 多篇会议 / 期刊 / 书籍出版物(2600 次引用,hIndex 30),曾任信息通信技术中心主任,现任克里特大学数据处理实验室主任。他在用户界面管理系统、脚本编程语言、自适应界面、下一代 IDE 和调试器、可访问的用户界面工具包方面做了开创性的工作,并在 2003 年开发了最早的物联网软件工具包之一。
个人主页:
https://www.ics.forth.gr/person/Savidis/Anthonywww.ics.forth.gr/person/Savidis/Anthony # 译者按 # 元编程是计算机编程中一个非常重要、有趣的概念,可以很大程度地简化和复用代码。元编程几乎是现代编程语言的必备能力之一,在数值计算、编译器设计和实现(类型推导、代码生成……)、领域专用语言(DSL/eDSL)设计、框架开发等领域有广泛的应用。
本文《A Survey of Metaprogramming Languages》是一篇系统介绍元编程技术的综述类文献,比较全面地对已有的元编程模型做了分类,并且对各类元编程的特点做了介绍。让读者可以清晰地了解元编程的历史、编程范式、代表语言…… 这也是译者选择这篇文献的初衷。近几年,在系统编程领域大热的 Rust、发力科学计算领域 Julia、擅长 Web 应用的 Ruby,都非常依赖和推崇元编程技术。遗憾的是,本文没有对这几门语言中的元编程做分析归类。另,原文献第二章中除对概念的介绍外,列举了众多语言的元编程系统作为示例解读,由于篇幅原因,译者只摘选了针对主流语言的介绍,省略部分语言,感兴趣的读者可阅读原文了解更多。
由于文献的性质,本文只能算是对元编程的意况大旨,欢迎读者朋友加入我们的编程语言技术社区 SIG-元编程小组,和我们一起对元编程技术做更深入的探讨。(加入方式:添加小助手微信pl_lab_001,添加并备注加入SIG-元编程)
原论文地址:
https://dl.acm.org/doi/epdf/10.1145/3354584dl.acm.org/doi/epdf/10.1145/3354584 #1 介绍 元编程是一种将计算机程序当作数据进行处理,从而生成新程序或修改现有程序的技术。元程序所用的语言,我们称之为元语言,生成或转换成的程序所使用的语言,我们称为对象语言 [1]。如果对象语言和元语言相同我们称为同构元编程,若不同,则称为异构元编程。元编程技术在生成或修改代码时,需要将代码在抽象层面进行表示,一般采用抽象语法树(AST,Abstract Syntax Tree,起源于 Lisp S 表达式 [2])的形式。为了让开发者更便捷的操作 AST,不同的语言有不同的形式,本质来说均是通过元语言编写元程序,修改目标代码的 AST。
运用元编程技术带来的收益 [3] 主要体现在以下三个方面:
Docker应用之创建镜像 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)中简单介绍了Dockerfile创建镜像,本文将详细介绍Dockerfile的基本结构、指令。
一、基本结构
如果具备一定Linux命令行基础,编写Dockerfile会更轻松——因为整体而言,Dockerfile就是一份自动化的Linux命令集。同时基于此,在写Dockerfile的过程中,需要模拟一遍命令的执行过程,避免因命令行写错而重新构建的情况(构建比较费时)。
命令规则:Dockerfile虽然可以命名为其他名字,但是一般情况不推荐修改除非同一个文件夹下存在多个Dockerfile文件。因为Dockerfile本身只是一份文本,不带特殊权限改为其他名字后会导致其他人可能仅看文件名不看内容不容易分;而且部分自动化构建工具甚至默认使用Dockerfile这个名字。
书写规则:一份标志的Dockerfile文件中应包含指令、注释等内容,构建指令应使镜像尽量干净没有垃圾文件——基于其是Linux命令集,可以想象Dockerfile就是一份指定文件名指定文件格式内容的脚本:
1、自动化:Dockerfile全程无交互(不同于其他脚本可能还给选择让在终端做出选择),所以整个构建过程需要保证命令集能够一直持续不断执行下去。
2、顺序:Dockerfile构建过程默认就是之上而下,所以对其中的命令编写要考虑顺序问题。
3、清理:构建镜像的过程中会产生很多临时文件,对于这些临时文件需要通过在Dockerfile文件最后写上清理系统的命令处理。
4、易读:对于这个作为IT从业人员是基本的职业素养。
二、指令
通过查看官网上已有镜像的Dockerfile文件可以发现一个规律就是所有命令默认均是大写。
1、FROM
FROM指令表示将来构建的镜像来自哪个镜像,也就是使用哪个镜像作为基础进行构建。其必须是这个Dockerfile第一句有效指令。如下示例:
2、MAINTAINER
这条指令主要指定维护者信息,方便他人寻找作者。
3、RUN
RUN指令用来在Docker的编译环境中运行指定命令。其会在shell或者exec的环境下执行命令,具体格式如下:
shell:RUN sh命令 ……
exec:RUN [程序名, 参数1, 参数2,……]
需要注意的是exec格式不会触发shell,所以其可以免除运行/bin/sh的开销在没有bash的镜像中执行同时可以避免错误的解析命令字符串。其也具有一定缺点就是如$HOME这样的环境变量无法使用。
4、ENV
ENV指令用来指定在执行docker run命令运行镜像时,自动设置的环境变量。这个环境变量可以在后续任何RUN指令中使用,并在容器运行时保持。而且可以通过docker run命令的-e参数来修改。
5、COPY
这条指令用来将本地的文件或文件夹复制到镜像的指定路径下,类似单向的docker cp(个人理解)。
6、ADD
该指令与COPY作用类似,但实现不同。ADD指令可以从一个URL地址上下载内容复制到容器的文件系统中,还可以两压缩打包格式的文件解压后复制到指定路径。
在相同的复制命令下,使用ADD构建镜像的大小比COPY构建的镜像要大,所以如果只是单纯的复制文件尽可能用COPY。
7、EXPOSE
nginx -s reload (热重载): Nginx 服务不会终止,使用主进程检查配置,如果配置文件语法正确,则主进程会启动一个新的工作进程处理新来的请求。主进程发送消息给原来的工作进程,通知旧的进程不在接受请求,处理完现有的请求后退出(优雅退出);如果语法不正确,则继续使用旧的进程继续处理请求。
service nginx restart(重启): 该条命令的执行过程如下,nginx -s stop -> nginx 先将 Nginx 快速的停止(等同于 service nginx stop),然后在执行启动命令(等同于 service nginx start),启动的时候会造成短暂的服务中断;如果配置文件语法错误,那问题就大了,有可能会造成更长时间的中断,有可能会造成很大的宕机。
搜索
复制
原文链接:https://blog.csdn.net/luoshengyang/article/details/29688041
说起刷ROM的动机,除了上面说的用来看Android系统源码在真实设备上的运行效果,还有很多值得说的。回想起PC时代,我们对我们自己拥有的设备(电脑),基本上能做的就是在上面重装系统。这个系统是厂商做好给我们的,里面有什么我们就用什么,不能随心所欲地定制。当然,如果你用的是Linux系统,你是可以随心所欲地对它进行定制的。不过可惜的是,我们的女神用的都是Windows系统。你和女神说你想要什么样的Linux系统,我给你定制一个,她会不知道你说的是什么——她需要的是一个不会中毒的又跑得快的Windows系统而已。现如今虽然很多女神用的是仍然是我们不能随心所欲定制的iOS系统,但是在移动设备上,iOS系统毕竟不能做到Windows在PC那样的一家独大——我们还有不少女神是用Android系统的。所以,如果你现在和女神说,我可以帮你刷一个专属的精简Android系统,里面没有一堆你不需要的预装软件,会让你的手机跑得很快,那女神得有多崇拜你啊。
当然,刷ROM的动机不能只是为了让女神崇拜,作为一个程序猿,我们的首要任务是维护宇宙和平。怎么维护呢?至少程序有BUG不能不改吧。你不改的话,老板是不会放过你的。但是,碰到那些很棘手的BUG,怎么办呢?例如,你是一个Android应用开发者,调用一个API接口的时候,总是抛出一个异常,而这个异常不跟到API内部实现去看看实在是不知道什么原因造成的。这时候,如果你手头上有这个手机的系统源代码,找这个API内部实现的地方,加一两行调试代码,再编译回手机上去跑,是不是就很容易定位问题了呢?
所以说,会刷ROM,不只是可以获得女神崇拜,还可以维护世界和平,作为一个Android开发者,你还有什么理由不去学习刷ROM呢?既然你决定学习刷ROM了,那你就得先搞清楚两个问题:1. 什么是刷ROM;2. 怎么学习刷ROM。
在回答第一个问题之前,我们先来看看Android设备从硬件到系统的结构,如图1所示:
图1 Android系统架构
最底层的是各种硬件设备,往上一层是Bootloader。Bootloader是什么概念呢?我们都知道,PC主板上有一小段程序叫做BIOS,主板加电时它是第一个跑起来的程序,负责初始化硬件,以及将OS启动起来。在嵌入式世界里(手机也是属于嵌入式设备),也有一小段类似BIOS的程序,不过它不叫BIOS,而是叫Bootloader。使用最广泛的Bootloader是一个叫uboot的程序,它支持非常多的体系结构。经过编译后,uboot会生成一个uboot.bin镜像,将这个镜像烧到设备上的一个特定分区去,就可以作为Bootloader使用了。
Bootloader支持交互式启动,也就是我们可以让Bootloader初始化完成硬件之后,不是马上去启动OS,而是停留在当前状态,等待用户输入命令告诉它接下来该干什么。这种启动模块就称为Fastboot模式。对于Android设备来说,我们可以通过adb reboot bootloader命令来让它重新启动并且进入到Fastboot模式中去。
在讨论Fastboot模式之前,我们先了解一下嵌入式设备的ROM结构(NAND flash之类的芯片)。通常,一个能够正常启动的嵌入式设备的ROM包含有以下四个分区:
1. Bootloader分区,也就是存放uboot.bin的分区
2. Bootloader用来保存环境变量的分区
3. Kernel分区,也就是存放OS内核的分区
4. Rootfs分区,也就是存入系统第一个进程init对应的程序的分区
当设备处于Fastboot模式时,我们可以通过另外一个工具fastboot来让设备执行指定的命令。对搞机者来说,最常用的命令就是刷入各种镜像文件了,例如,往Kernel分区和Rootfs分区刷入指定的镜像。
对于Android设备来说,当它处于Fastboot模式时,我们可以将一个包含有Kernel和Rootfs的Recovery.img镜像通过fastboot工具刷入到一个称为设备上一个称为Recovery的分区去。这个过程就是刷Recovery了,它也是属于刷ROM的一种。由于Recovery分区包含有Kernel和Rootfs,因此将Recovery.img刷入到设备后,我们就可以让设备正常地启动起来了。这种启动方式就称为Recovery模式。 对于Android设备来说,我们可以通过adb reboot recovery命令来让它进入到Recovery模式中去。
当设备处于Recovery模式时,我们可以做些什么呢?答案是取决于刷入的Recovery.img所包含的Rootfs所包含的程序。更确切地说,是取决于Rootfs镜像里面的init程序都做了些什么事情。不过顾名思义,Recovery就是用来恢复系统的意思,也包含有更新系统的意思。这里所说的系统,是用户正常使用的系统,里面包含有Android运行时框架,使得我们可以在上面安装和使用各种APP。
用户正常使用Android设备时的系统,主要是包含有两个分区:System分区和Boot分区。System分区包含有Android运行时框架、系统APP以及预装的第三方APP等,而Boot分区包含有Kernel和Rootfs。刷入到System分区和Boot分区的两个镜像称为system.img和boot.img,我们通常将它们打包和压缩为一个zip文件,例如update.zip,并且将它上传到Android设备上的sdcard上去。这样当我们进入到Recovery模式时,就可以在Recovery界面上用我们之前上传到sdcard的zip包来更新用户正常使用Android设备时所用的系统了。这个过程就是通常所说的刷ROM了。
不知道大家看明白了没有?广义上的刷ROM,实际上包含更新Recovery和更新用户正常使用的系统两个意思;而狭义上的刷ROM,只是更新用户正常使用的那个系统。更新Recovery需要进入到Fastboot模式中,而更新用户正常使用的那个系统需要进入到Recovery模式中。Android设备在启动的过程中,在默认情况下,一旦Bootloader启动完成,就会直接启动用户正常使用的那个系统,而不会进入到Recovery模式,或者停留在Bootloader中,也就是停留在Fastboot模式中。只有通过特定的命令,例如adb reboot recovery和adb reboot bootloader,或者特定的按键,例如在设备启动过程中同时按住音量减小键和电源开关键,才能让设备进入到Recovery模式或者Fastboot模式中。
因此,一个完整的刷ROM过程,包含以下两个步骤:
1. 让设备进入到Fastboot模式,刷入一个recovery.img镜像
2. 让设备进入到Recovery模式,刷入一个包含system.img镜像和boot.img镜像的zip包
不过需要注意的是,system.img镜像和boot.img镜像不一定是只有在Recovery模式才能刷入,在Fastboot模式下也是可以刷入的,就像在Fastboot模式中刷入recovery.img镜像一样,只不过在Recovery模式下刷入它们更友好一些。说到这里,就不得不说另外一个概念,就是所谓的Bootloader锁。在锁定Bootloader的情况下,我们是无法刷入非官方的recovery.img、system.img和boot.img镜像的。这是跟厂商实现的Bootloader相关的,它们可以通过一定的算法(例如签名)来验证要刷入的镜像是否是官方发布的。在这种情况下,必须要对Bootloader进行解锁,我们才可以刷入非官方的镜像。
好了,以上就回答了什么是刷ROM这个问题,接下来我们要回答的是如常学习刷ROM这个问题。
前面我们提到了刷ROM的两个步骤,实际上我们还少了一个重要的步骤,那就是先要制作recovery.img、system.img和boot.img。有人可能会说,网上不是很多现成的刷机包吗?直接拿过来用不就是行了吗?但是别忘了前面我们所说的刷ROM动机:随心所欲地定制自己的系统。去拿别人制好的刷机包就失去了随心所欲定制的能力。那就只能自己去编译AOSP源码生成刷机包了。
然而,从零开始从AOSP源码中编译出能在自己使用的手机上运行的系统,可不是一件容易的事情。不过,好在有很多现成的基于AOSP的第三方开源项目,可以编译出来在目前市场上大部分的手机上运行。其中,最著名的就是CyanogenMod了,简称CM。国内大部分的第三方Android系统,都是基于CM来开发的,包括MIUI和锤子。
选择CM来讲解刷ROM的过程是本文的主题。不过单就刷ROM这个过程来说,CM官网上已经有很详细的过程,包括从CM源码编译出适用特定机型的刷机包,以及将编译出来的刷机包刷到手机里面去的过程。因此,本文不是单纯地讲解刷ROM过程,而是要结合原理来讲解刷ROM过程的关键步骤,来达到帮助大家更进一步地理解Android的目的。
如果你写过一些 Java 代码的话,你应该知道 Java 中最常见的就是空指针异常错误。
这个错误的原因就是你对一个为空的对象进行操作了。
比如说,你有一个 List,但是这个 List 是空对象,如果你要向这个 List 中添加元素或者删除元素的话,你铁定会遇到空对象的异常。
Optional 类是一个可以为 NULL 的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional 是个容器:它可以保存类型T的值,或者仅仅保存 NULL。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional 类的引入很好的解决空指针异常。
概述 在本指南中,我们针对 Optional 来进行一些探讨。
Optional 这个类最新是从 Java 8 中引入的,其主要目的如上面我们介绍的,就是为了解决 Java 中广受诟病的空异常。
Java 从 类型级别(type-level) 给出了一个解决方案,用来替代 null。In this tutorial, we’re going to show the Optional class that was introduced in Java 8.
如果你还想对 Java 的 Optional 了解更多的话,你可以直接访问 Oracle 提供的官方 API,访问地址为: Tired of Null Pointer Exceptions? Consider Using Java SE 8's Optional!
metamask 所有官方版最新版下载,chrome浏览器插件, 区块链以太坊eth钱包安装使用教程 MetaMask是一个开源的以太坊钱包,能帮助用户方便地管理自己的以太坊数字资产, 但在国内由于网络原因,你可能下载不了。本文将介绍如何解决metamask钱包无法下载的问题。
如果需要开源多链钱包(btc,bch,eth,xrp等多币共用一个私钥),推荐imtoken
安全性问题 一些不开源的钱包有后门也不一定,metamask开源就不会存在这种问题,所以可以放心存储自己的币和token。
方法1:本地包下载和安装 你可以按照以下操作步骤完成MetaMask钱包的安装:
STEP 1 下载链接: https://pan.baidu.com/s/1Qs_PkWM1z93q8uOIUQrTiw 提取码: xdxs(有三个文件,选择metamask-chrome-7.7.9.zip)
STEP 2 点击 “metakmask官方版最新版” 列表下的 “metamask-chrome-7.7.9.zip” (或你看到的最新版), 下载并解压此压缩包STEP 3 用谷歌浏览器 (Chrome) 打开链接:chrome://extensions
勾选开发者模式,选择 加载已解压的扩展程序 (Load unpacked extension),在跳出菜单中选择刚才解压的文件包STEP 4 网页将跳出Metamask欢迎页面(等一会儿如果没跳出来点击浏览器右上角狐狸图标)。执行上述步骤后,浏览器右上角将出现一个新图标(MetaMask 狐狸插件图标), 成功安装 MetaMask 钱包。
中文版 metamask自带多国语言,Settings->General->Current Language->拉到最下面中文(简体),就可切换成中文版(不过翻译做的不够地道)。
之后便可以在浏览器中打开以太坊
在函数内,yield语句可以作为表达式使用,出现在赋值运算符的右边,例如:
def receiver(): print(Ready to receive) while True: n = (yield) print(go %s, n) 以这种方式使用yield语句的函数称为协程,向函数发送值时函数将执行,它的行为类似于生成器
r = reveiver() r.__next__() 或者 next(r) # 向前执行到第一条yield语句 for i in range(5): r.send(i) go %s 0 go %s 1 go %s 2 go %s 3 go %s 4 在这个例子中,一开始调用next()是必不可少的,这样协程才能执行第一个yield表示式之前的语句。这时,协程会挂起, 等待相关生成器对象r的send()方法给它发送一个值。传递给send()的值由协程中的(yield)表达式返回。接收到值后,协程 就会执行语句,直至遇到下一条yield语句。 在协程中需要首先调用next()这件事很容易被忽略,这经常成为错误出现的原因。因此,建议使用一个能自动完成该步骤的 装饰器来包装协程。
def coroutine(func): def start(*args, **kwargs): g = func(*args, **kwargs) g.next() return g return start 使用这个装饰器就可以像下面这样编写和使用协程:
@coroutine def receiver(): print(Ready to receive) while True: n = (yield) print(go %s, n) # 示例用法 r = receiver() r.