编程语言
未读废话不多说,直接上代码 (adsbygoogle = window.adsbygoogle || []).push({}); 12345678910111213141516171819from PIL import Image, ImageFilter, ImageOpsimg = Image.open('/Users/demo/Desktop/b.png') # 原图路径def dodge(a,b,alpha): return min(int(a*255/(256-b*alpha)),255)def draw(img,blur=25,alpha=1.0): img1 = img.convert('L') img2 = img1.copy() img2 = ImageOps.invert(img2) for i in range(blur): img2 = img2.filter(ImageFilter.BLUR) width,height = img1.size for x in range(width): for y ...
迭代器是一种可以让我们遍历一个集合中所有元素的代码结构。在Lua语言中,通常使用函数表示迭代器:每一次调用函数时,函数会返回集合中的”下一个“元素。一个典型的例子是io.read,每次调用该函数时它都会返回标准输入中的下一行,在没有读取的行时返回nil。 (adsbygoogle = window.adsbygoogle || []).push({}); 所有的迭代器都需要在连续的调用之间保存一些状态,这样才能知道当前迭代所处的位置及如何从当前位置步进到下一位置。对于函数io.read而言,C语言会将状态保存在流的结构体中。对于我们自己的迭代器而言,闭包则为保存状态提供了一种良好的机制。庆祝,一个闭包就是一个可以访问其自身的环境中一个或多个局部变量的函数。这些变量将连续调用过程中的值并将其保存在闭包中,从而使得闭包能够记住迭代所处的位置。当然,要创建一个新的闭包,我们还必须创建非局部变量。因此,一个闭包结构通常涉及两个函数;闭包本身和一个用于创建该闭包及其封装变量的工程。作为示例,让我们来为列表编写一个简单的迭代器。与ipairs不同的是,该迭代器并不是返回每个元素 ...
通常,Lua语言不会设置规则。相反,Lua语言提供的是足够强大的机制供不同的开发者实现最适合自己的规则。然而,这种方法对于模块而言并不是特别适用。模块系统的主要目标之一就是允许不同的人共享代码,缺乏公共规则就无法实现这样的分享。 (adsbygoogle = window.adsbygoogle || []).push({}); Lua语言从5.1版本开始为模块和包定义了一系列的规则。这些规则不需要从语言中引入额外的功能,程序猿可以使用目前为止我们学习到的机制实现这些规则。程序员也可以自由地使用不同的策略。当然,不同的实现可能会导致程序不能使用外部模块,或者模块不能被外部程序使用。从用户观点来看,一个模块就是一些代码,这些代码可以通过函数require加载,然后创建和返回一个表。这个表就像是某种命名空间,其中定义的内容是模块中导出的东西,比如函数和常量。例如,所有的标准库都是模块。我们可以按照如下的方式使用数学库:12local m = require "math"print(m.sin(3.14)) -- 0.00159265291648 ...
编程语言
未读虽然我们把Lua语言成为解释型语言,但Lua语言总是在运行代码前先预编译源码为中间代码(这没什么大不了的,很多解释型语言也这样做)。编译阶段的存在听上去超出了解释型语言的范畴,但解释型语言的区分并不在与源码是否被编译,而在于是否有能力(且轻易地)执行动态生成的代码。可以认为,正是由于诸如dofile这样函数的的存在,才使得Lua语言能够被称为解释型语言。 (adsbygoogle = window.adsbygoogle || []).push({}); 编译此前,我们已经介绍过函数dofile,它是运行Lua代码段的主要方式之一。实际上,函数dofile是一个辅助函数,函数loadfile才完成了真正的核心工作。与函数dofile类似,函数loadfile也是从文件中加载Lua代码段,但它不会运行代码,而是只是编译代码,然后将编译后的代码段作为一个函数返回。此外,与函数dofile不同,函数loadfile只返回错误码而不抛出异常。可以认为,函数dofile就是:1234function dofile (filename) local f = assert(loa ...
笔者这里是使用树莓派搭建虚拟专用网络服务器,树莓派是用的ubuntu系统,所以该方法使用于所有的ubuntu系统的服务器. (adsbygoogle = window.adsbygoogle || []).push({}); 想要用服务器搭建虚拟专用网络服务器,你首先得上手一个树莓派,可以参考这里.或者你对虚拟专用网络不够了解,可以参考这里. 安装pptp在终端输入下面命令并回车.1sudo apt-get install pptpd 配置内网ip策略在终端输入下面命令并回车,进入vim编辑器.1sudo vim /etc/pptpd.conf 注释logwtmp,即在前面加一个#. 在# TAG:localip后面增加2行12localip 192.168.0.1remoteip 192.168.0.234-238,192.168.0.245 上面配置的localip为服务器的ip地址,在搭建虚拟专用网络的时候要根据自己服务器的地址来设置.remoteip为连接虚拟专用网络的客户端ip地址,一般情况下不需要更改. 配置dns在终端输入下面命令并回车,进入 ...
编程语言
未读在处理数据文件时,写数据通常比读数据简单很多。当向一个文件中写时,我们拥有绝对的控制权;但是,当从一个文件中读时,我们并不知道会读什么东西。一个健壮的程序除了能够处理一个合法文件中所包含的所有类型的数据外,还应该能够优雅地处理错误的文件。因此,编写一个健壮的处理输入的程序总是比较困难的。 (adsbygoogle = window.adsbygoogle || []).push({}); Lua语言自1993年发布以来,其主要用途之一就是描述数据。在那个年代,主要的文本数据描述语言之一是SGML。对于很多人来说,SGML既臃肿又复杂。在1998年,有些人将其简化成XML,但以我们的眼光看仍然臃肿又复杂。有些人跟我们的观点一直,进而在2001年开发了JSON。JSON基于JavaScript,类似于一种精简过的Lua语言数据文件。一方面,JSON的一大优势在于它是国际标准,包括Lua语言在内的多种语言都具有操作JSON文件的标准库。另一方面,Lua语言数据文件的读取更加容易和灵活。使用一门全功能的编程语言来描述数据确实非常灵活,但也会带来两个问题。问题之一在于安全性, ...
Lua语言中的表并不是一种数据结构,它们是其他数据结构的基础。我们可以用Lua语言中的表来实现其他语言提供的数据结构,如数组、记录、列表、队列、集合等。而且,用Lua语言中的表实现这些数据结构还很高效。 (adsbygoogle = window.adsbygoogle || []).push({}); 在像C和Pascal这样更加传统的语言中,通常使用数组和列表来实现大多数数据结构。虽然在Lua语言中也可以使用表来实现数组和列表,但表实际上比数组和列表强大很多。使用表时,很多算法可以被简化。例如,由于表本身就支持任意数据类型的直接访问,因此我们很少在Lua语言中编写搜索算法。 数组在Lua语言中,简单地使用整数来索引表即可实现数组。因此,数组的大小不用非得是固定的,而是可以按需增长的。通常,在初始化数组时就间接地定义了数组的大小。例如,在执行了以下的代码后,任何访问范围1~1000之外的元素都会返回nil而不是0:1234local a = {}for i = 1, 1000 do a[i] = 0end长度运算符(#)正是基于此来计算数组大 ...
Lua语言处理二进制数据的方式与处理文本的方式类似。Lua语言中的字符串可以包含热议字节,并且几乎所有能够处理字符串的库函数也能处理任意字节。我们甚至可以对二进制数据进行模式匹配。以此为基础,Lua5.3中引入了用于操作二进制数据的额外机制:除了整型数外,该版本还引入了位操作及用于打包/解包二进制数据的函数。 (adsbygoogle = window.adsbygoogle || []).push({}); 位运算Lua语言从5.3版本开始提供了针对数值类型的一组标准位运算符与算术运算符不同的是,位运算符只能用于整型数。位运算符包括&(按位与)、|(按位或)、~(按位异或)、>>(逻辑右移)、<<(逻辑左移)和一元运算符~(按位取反)。所有的位运算都针对构成一个整型数的所有位。在标准Lua中,也就是64位。这对于用32位整型数的算法可能会成问题。不过,要操作32位整型数也不难。除了右移操作外,只要忽略高32位,那么所有针对64位整型数的操作与针对32位整型数的操作都一样。这对于加法、减法和乘法都有效。因此,在操作32位整型数时,只需 ...
Lua语言的标准库提供了两个用于操作日期和时间的函数,这两个函数在C语言标准库中也存在,提供的是同样的功能。虽然这两个函数看上去很简单,但依旧可以基于这些简单的功能完成很多复杂的工作。 (adsbygoogle = window.adsbygoogle || []).push({}); Lua语言针对日期和时间使用两种表示方式。第1中表示方式是一个数字,这个数字通常是一个整型数。尽管并非IOS C所必需的,但在大多数系统中这个数字时自一个被称为纪元的固定日期后至今的秒数。特别地,在POSIX和Windows系统中国这个固定日期均是Jan 01,1970,0:00 UTC。Lua语言针对日期和时间提供的第2中表示方式是一个表。日期表具有以下几个重要的字段:year、month、day、hour、min、sec、wday、yady和isdst,除isdst以外的所有字段均为整型值。前6个字段的含义非常明显,而wday字段表示本周中的第几天(第1天为星期天);yday表示当年中的第几天(第1天是1月1日);isdst字段表示布尔类型,如果使用夏时令则为真。例如,Sep 1 ...
与其他几种脚本语言不通,Lua语言既没有使用POSIX正则表达式,也没有使用Perl正则表达式来进行模式匹配。之所以这样做的主要原因在于大小问题:一个典型的POSIX正则表达式实现需要超过4000行代码,这比所有Lua语言标准库总大小的一半还大。相比之下,Lua语言模式匹配的实现代码只有不到600行。尽管Lua语言的欧式匹配做不到完整POSIX实现的所有功能,但是Lua语言的模式匹配仍然非常强大,同时还具有一些与标准POSIX不同但又可与之媲美的功能。 (adsbygoogle = window.adsbygoogle || []).push({}); 模式匹配的相关函数字符串标准库提供了基于模式的4个函数。我们已经初步了解过函数find和gsub,其余两个函数分别是match和gmatch。 函数string.find函数string.find用于在指定的目标字符串中搜索指定的模式。最简单的模式就是一个单词,它智慧匹配到这个单词本身。例如,模式’hello’会在目标自服装中所搜子串”hello”。函数string.find找到一个模式后,会返回两个值:匹配到模 ...
在Lua语言中,函数是严格遵循词法定界的第一类值。“第一类值”以为这Lua语言中的函数与其他常见类型的值具有同等权限:一个程序可以将某个函数保存到变量中或表中,也可以将某个函数作为参数传递给其他函数,还可以将某个函数作为其他函数的返回值返回。 (adsbygoogle = window.adsbygoogle || []).push({}); “词法定界”意味着Lua语言中的函数可以访问包含其自身的外部函数中的变量。上述两个特行联合起来为Lua语言带来了极大的灵活性。例如,一个程序可以通过重新定义函数来增加新功能,也可以通过擦除函数来为不受信任的代码创建一个安全的运行时环境。更重要的是,上述两个特行允许我们在Lua语言中使用很多函数式语言的强大编程技巧。即使对函数式编程毫无兴趣,也不妨学习下如何使用这些技巧。因为这些技巧可以使程序变得更加小巧和简单。 函数是第一类值如前所述,Lua语言中的函数是第一类值。以下的示例演示了第一类值的含义:123456a = {p = print} -- 'a.p'指向'print ...
Lua语言提供了一组精简且常用的控制结构,包括用于条件执行的if以及用户循环的while、repeat和for。所有的控制结构语法上都有一个显示的终结符:end用于终结if、for及while结构,until用于终结repeat结构。 (adsbygoogle = window.adsbygoogle || []).push({}); 控制结构的条件表达式的结果可以是任何值。Lua语言将所有不是false和nil的值当做真。 if then elseif 语句先测试其条件,并根据条件是否满足执行相应的then部分或else部分。else部分是可选的。12345678if a<0 then a == endif a <b then return a else return b endif line > MAXLINES then showpage() line = 0end 如果要编写嵌套的if语句,可以使用elseif。它类似于在else后面紧跟一个if,但可以避免重复使用end:1234567891011if op == "+" ...