当前位置: 首页 > news >正文

沈阳网站建app制作平台哪家好

沈阳网站建,app制作平台哪家好,网站系统设计方案,襄樊公司网站建设把以前一直只限于知道#xff0c;却不清晰理解的这几个概念完完整整地梳理了一番。内容参考自wiki页面#xff0c;然后加上自己一些理解。 词法作用域和动态作用域 不管什么语言#xff0c;我们总要学习作用域(或生命周期)的概念#xff0c;比如常见的称呼#xff1a;全局…把以前一直只限于知道却不清晰理解的这几个概念完完整整地梳理了一番。内容参考自wiki页面然后加上自己一些理解。 词法作用域和动态作用域 不管什么语言我们总要学习作用域(或生命周期)的概念比如常见的称呼全局变量、包变量、模块变量、本地变量、局部变量等等。不管如何称呼这些作用域的范围实现它们的目的都一样 (1)为了避免名称冲突;(2)为了限定变量的生命周期(本文以变量名说事其它的名称在规则上是一样的)。但是不同语言的作用域规则不一样虽然学个简单的基础就足够应用因为我们有编程规范(1)尽量避免名称冲突;(2)加上类似于local的修饰符尽量缩小生效范围;(3)放进代码块等等。但是真正去细心验证作用域的生效机制却并非易事(我学Python的时候花了很长时间细细验证学perl的时候又花了很长时间细细验证)但可以肯定的是理解本文的词法作用域规则(Lexical scoping)和动态作用域规则(dynamic scoping)对学习任何语言的作用域规则都有很大帮助这两个规则是各种语言都宏观通用的。 很简单的一段bash下的代码 x1 function g(){ echo g: $x ; x2; } function f(){ local x3 ; g; echo f: $x; } # 输出2还是3 f # 输出1还是3 echo $x # 输出1还是2 对于bash来说上面输出的分别是3(g函数中echo)、2(f函数中的echo)和1(最后一行echo)。但是同样语义的代码在其它语言下得到的结果可能就不一样(分别输出1、3和2例如perl中将local替换为my)。 这牵扯到两种贯穿所有程序语言的作用域概念词法作用域(类似于C语言中static)和动态作用域。词法作用域和词法这个词真的没什么关系反而更应该称之为文本段作用域。要区别它们只需要回答函数out_func中嵌套的内层函数in_func能否看见out_func中的环境。 对于上面的bash代码来说假如这段代码是适用于所有语言的伪代码 对于词法作用域的语言执行f时会调用gg将无法访问f文本段的变量词法作用域认为g并不是f的一部分而是跳出f的因为g的定义文本段是在全局范围内的所以它是全局文本段的一部分。如果函数g的定义文本段是在f内部则g属于f文本段的一部分。 所以g不知道f文本段中local x3的设置于是g的echo会输出全局变量x1然后设置x2因为它没有加上作用域修饰符而g又是全局内的函数所以x将修改全局作用域的x值使得最后的echo输出2而f中的echo则输出它自己文本段中的local x3。所以整个流程输出1 3 2对于动态作用域的语言执行f时会调用gg将可以访问f文本中的变量动态作用域认为g是f文本段的一部分是f中的嵌套函数。 所以g能看到local x3的设置所以g的echo会输出3。g中设置x2后仅仅只是在f的内层嵌套函数中设置所以x2对g文本段和f文本段(因为g是f的一部分)都可见但对f文本段外部不可见所以f中的echo输出2最后一行的echo输出1。所以整个流程输出3 2 1总结来说 词法作用域是关联在编译期间的对于函数来说就是函数的定义文本段的位置决定这个函数所属的范围。动态作用域是关联在程序执行期间的对于函数来说就是函数执行的位置决定这个函数所属的范围。由于bash实现的是动态作用域规则。所以输出的是3 2 1。对于perl来说my修饰符实现词法作用域规则local修饰符实现动态作用域规则。 例如使用my修饰符的perl程序 #!/usr/bin/perl$x1; sub g { print g: $x\n; $x2; } sub f { my $x3; g(); print f: $x\n; } # 词法作用域 f(); print $x\n; 执行结果 [fairyfairy:/perlapp]$ perl scope2.pl g: 1 f: 3 2 使用local修饰符的perl程序 #!/usr/bin/perl$x1; sub g { print g: $x\n; $x2; } sub f { local $x3; g(); print f: $x\n; } # 动态作用域 f(); print $x\n; 执行结果 [fairyfairy:/perlapp]$ perl scope2.pl g: 3 f: 2 1 有些语言只支持一种作用域规则特别是那些比较现代化的语言而有些语言支持两种作用域规则(正如perl语言my实现词法变量作用域规则local实现动态作用域规则)。相对来说词法作用域规则比较好控制整个流程还能借此实现更丰富的功能(如最典型的闭包以及高阶函数)而动态作用域由于让变量生命周期没有任何深度(回想一下shell脚本对函数和作用域的控制非常傻瓜化)比较少应用上甚至有些语言根本不支持动态作用域。 闭包和回调函数 理解闭包、回调函数不可不知的术语 1.引用(reference)数据对象和它们的名称 前文所说的可见、不可见、变量是否存在等概念都是针对变量名(或其它名称如函数名、列表名、hash名)而言的和变量的值无关。名称和值的关系是引用(或指向)关系赋值的行为就是将值所在的数据对象的引用(指针)交给名称让名称指向这个内存中的这个数据值对象。如下图 2.一级函数(first-class functions)和高阶函数(high-order functions) 有些语言认为函数就是一种类型称之为函数类型就像变量一样。这种类型的语言可以 将函数赋值给某个变量那么这个变量就是这个函数体的另一个引用就像是第二个函数名称一样。通过这个函数引用变量可以找到函数体然后调用执行。 例如perl中$ref_func\myfunc表示将函数myfunc的引用赋值给$ref_func那么$ref_func也指向这个函数。将函数作为另一个函数的参数。例如两个函数名为myfunc和func1那么myfunc(func1)就将func1作为myfunc的参数。 这种行为一般用于myfunc函数中对满足某些逻辑的东西执行func1函数。举个简单的例子unix下的find命令将find看作是一个函数它用于查找指定路径下符合条件的文件名将-print、-exec {}\;选项实现的功能看作是其它的函数(请无视它是否真的是函数)这些选项对应的函数是find函数的参数每当find函数找到符合条件的文件名时就执行-print函数输出这个文件名函数的返回值也可以是另一个函数。例如myfunc函数的定义语句为function myfunc(){ ...return func1 }。其实实现上面三种功能的函数称之为一级函数或高阶函数其中高阶函数至少要实现上面的2和3。一级函数和高阶函数并没有区分的必要但如果一定要区分那么 一级函数更像是一种术语概念它将函数当作一种值看待可以将其赋值出去、作为参数传递出去以及作为返回值对于计算机程序语言而言它更多的是用来描述某种语言是否支持一级函数高阶函数是一种函数类型就像回调函数一样当某个函数符合高阶函数的特性就可以将其称之为这是一个高阶函数。3.自由变量(free variable)和约束变量(bound variable) 这是一组数学界的术语。 在计算机程序语言中自由变量是指函数中的一种特殊变量这种变量既不在本函数中定义也不是本函数的参数。换句话说可能是外层函数中定义的但却在内层函数中使用的所以自由变量常常和非本地变量(non-local variable熟悉Python的人肯定知道)互用。例如 function func1(x){var z;function func2(y){return xyz # x和z既不是func2内部定义的也不是func2的参数所以x和z都是自由变量}return func1 } 自由变量和约束变量对应。所谓约束变量是指这个变量之前是自由变量但之后会对它进行赋值将自由变量绑定到一个值上之后这个变量就成为约束变量或者称为绑定变量。 例如 function func1(x){var m20 # 对func2来说这是自由变量对其赋值所以m变成了bound variablevar zfunction func2(y){z10 # 对自由变量z赋值z变成bound variablereturn mxyz # m、x和z都是自由变量}return func1 }ref_funcfunc1(3) # 对x赋值x变成bound variable 回调函数 回调函数一开始是C里面的概念它表示的是一个函数 可以访问另一个函数当这个函数执行完了会执行另一个函数也就是说将一个函数(B)作为参数传递给另一个函数(A)但A执行完后再自动调用B。所以这种回调函数的概念也称为call after。 但是现在回调函数已经足够通用化了。通用化的回调函数定义为将函数B作为另一个函数A的参数执行到函数A中某个地方的时候去调用B。和原来的概念相比不再是函数A结束后再调用而是我们自己定义在哪个地方调用。 例如Perl中的File::Find模块中的find函数通过这个函数加上回调函数可以实现和unix find命令相同的功能。例如搜索某个目录下的文件然后print输出这个文件名即find /path xxx -print。 #!/usr/bin/perl use File::Find;sub print_path { # 定义一个函数用于输出路径名称print $File::Find::name\n; }$callback \print_path; # 创建一个函数引用名为$callback所以perl是一种支持一级函数的语言find( $callback,/tmp ); # 查找/tmp下的文件每查找到一个文件就执行一次$callback函数 这里传递给find函数的$callback就是一个回调函数。几个关键点 $callback作为参数传递给另一个find()函数(所以find()函数是一个高阶函数)在find()函数中每查找到一个文件就调用一次这个$callback函数。当然如果find是我们自己写的程序就可以由我们自己定义在什么地方去调用$callback$callback不是我们主动调用的而是由find()函数在某些情况下(每查找到一个文件)去调用的回调就像对函数进行填空答题一样根据我们填入的内容去复用填入的函数从而实现某一方面的细节而普通函数则是定义了就只能机械式地复用函数本身。 之所以称为回调函数是因为这个函数并非由我们主观地、直接地去调用而是将函数作为一个参数通过被调用者间接去调用这个函数参数。本质上回调函数和一般的函数没有什么区别可能只是因为我们定义一个函数却从来没有直接调用它这一点感觉上有点奇怪所以有人称之为回调函数用来统称这种间接的调用关系。 回调函数可以被多线程异步执行。 彻底搞懂闭包 计算机中的闭包概念是从数学世界引入的在计算机程序语言中它也称为词法闭包、函数闭包。 闭包简单的、通用的定义是指函数引用一个词法变量在函数或语句块结束后(变量的名称消失)词法变量仍然对引用它的函数有效。在下一节还有关于闭包更严格的定义(来自wiki)。 看一个python示例函数f中嵌套了函数g并返回函数g def f(x):def g(y):return x yreturn g # 返回一个闭包有名称的函数(高阶函数的特性)# 将执行函数时返回的闭包函数赋值给变量(高阶函数的特性) a f(1)# 调用存储在变量中闭包函数 print (a(5))# 无需将闭包存储进临时变量直接一次性调用闭包函数 print( f(1)(5) ) # f(1)是闭包函数因为没有将其赋值给变量所以f(1)称为匿名闭包 上面的a是一个闭包它是函数g()的一个实例。f()的参数x可以被g访问在f()返回g函数后f()就退出了随之消失的是变量名x(注意是变量名称x变量的值在这里还不一定会消失)。当将闭包f(1)赋值给a后原来x指向的数据对象(即数值1)仍被a指向的闭包函数引用着所以x对应的值1在x消失后仍保存在内存中只有当名为a的闭包被消除后原来x指向的数值1才会消失。 闭包特性1对于返回的每个闭包g()来说不同的g()引用不同的x对应的数据对象。换句话说变量x对应的数据对象对每个闭包来说都是相互独立的 例如下面得到两个闭包这两个闭包中持有的自由变量虽然都引用相等的数值1但两个数值是不同数据对象这两个闭包也是相互独立的 af(1) bf(1) 闭包特性2对于某个闭包函数来说只要这不是一个匿名闭包那么闭包函数可以一直访问x对应的数据对象即使名称x已经消失 但是 af(1) # 有名称的闭包a将一直引用数值对象1 a(3) # 调用闭包函数a将返回134其中1是被a引用着的对象即使a(3)执行完了也不放开 a(3) # 再次调用函数a将返回4其中1和上面一条语句的1是同一个数据对象 f(1)(3) # 调用匿名的闭包函数数据对象1在f(1)(3)执行完就消失 f(1)(3) # 调用匿名的闭包函数和上面的匿名闭包是相互独立的 最重要的特性就在于上面执行的两次a(3)将词法变量的生命周期延长但却足够安全。 看下面perl程序中的闭包函数可以更直观地看到结果。 sub how_many { # 定义函数my $count2; # 词法变量$countreturn sub {print $count,\n}; # 返回一个匿名函数这是一个匿名闭包 }$refhow_many(); # 将闭包赋值给变量$refhow_many()-(); # (1)调用匿名闭包输出3 how_many()-(); # (2)调用匿名闭包输出3 $ref-(); # (3)调用命名闭包输出3 $ref-(); # (4)再次调用命名闭包输出4 上面将闭包赋值给$ref通过$ref去调用这个闭包则即使how_many中的$count在how_many()执行完就消失了但$ref指向的闭包函数仍然在引用这个变量所以多次调用$ref会不断修改$count的值所以上面(3)和(4)先输出3然后输出改变后的4。而上面(1)和(2)的输出都是3因为两个how_many()函数返回的是独立的匿名闭包在语句执行完后数据对象3就消失了。 闭包更严格的定义 注意严格定义的闭包和前面通俗定义的闭包结果上是不一样的通俗意义上的闭包并不一定符合严格意义上的闭包。 关于闭包更严格的定义是一段谁都看不懂的说明(来自wiki)。如下几个关键词我加粗显示了因为重要。 闭包是一种在支持一级函的编程语言中能够将词法作用域中的变量名称进行绑定的技术。在操作上闭包是一种用于保存函数和环境的记录。这个环境记录了一些关联性的映射将函数的每个自由变量与创建闭包时所绑定名称的值或引用相关联。通过闭包就算是在作用域外部调用函数也允许函数通过闭包拷贝他们的值或通过引用的方式去访问那些已经被捕获的变量。 我知道这段话谁都看不懂所以简而言之一下一个函数实例和一个环境结合起来就是闭包。这个所谓的环境决定了这个函数的特殊性决定了闭包的特性。 还是上面的python示例函数f中嵌套了函数g并返回函数g def f(x):def g(y):return x yreturn g # 返回一个闭包有名称的函数# 将执行函数时返回的闭包函数赋值给变量 a f(1) 上面的a是一个闭包它是函数g()的一个实例。f()的参数x可以被g访问对于g()来说这个x不是g()内部定义的也不是g()的参数所以这个x对于g来说是一个自由变量(free variable)。虽然g()中持有了自由变量但是g()函数自身不是闭包函数只有在g持有的自由变量x和传递给f()函数的x的值(即f(1)中的1)进行绑定的时候才会从g()创建一个闭包函数这表示闭包函数开始引用这个自由变量并且这个闭包一直持有这个变量的引用即使f()已经执行完毕了。然后在f()中return这个闭包函数因为这个闭包函数绑定了(引用)自由变量x这就是闭包函数所在的环境。 环境对闭包来说非常重要是区别普通函数和闭包的关键。如果返回的每个闭包不是独立持有属于自己的自由变量而是所有闭包都持有完全相同的自由变量那么闭包虽然仍可称为闭包但和普通函数却没有区别了。例如 def f(x):x3def g(y):return x yreturn ga f(1) b f(3) 在上面的示例中x虽然是自由变量但却在g()的定义之前就绑定了值(前文介绍过它称为bound variable)使得闭包a和闭包b持有的不再是自由变量而是值对象完全相同的绑定变量其值对象为3a和b这个时候其实没有任何区别(虽然它们是不同对象)。换句话说有了闭包a就完全没有必要再定义另一个功能上完全相同的闭包b。 在函数复用性的角度上来说这里的a和普通函数没有任何区别都只是简单地复用了函数体。而真正严格意义上的闭包除了复用函数体还复用它所在的环境。 但是这样一种情况对于通俗定义的闭包来说返回的g()也是一个闭包但在严格定义的闭包中这已经不算是闭包。 再看一个示例将自由变量x放在g()函数定义文本段的后面。 def f(y):return xyx1def g(z):x3return f(z)print(g(1)) # 输出2而不是4 首先要说明的是python在没有给任何作用域修饰符的时候实现的词法作用域规则所以上面return f(z)中的f()看见的是全局变量x(因为f()定义在全局文本段中)而不是g()中的x3。 回到闭包问题上。上面f()持有一个自由变量x这个f(z)的文本定义段是在全局文本段中它绑定的自由变量x是全局变量(声明并初始化为空或0)但是这个变量之后赋值为1了。对于g()中返回的每个f()所在的环境来说它持有的自由变量x一开始都是不确定的但是后来都确定为1了。这种情况也不能称之为闭包因为闭包是在f()对自由变量进行绑定时创建的而这个时候x已经是固定的值对象了。 回调函数、闭包和匿名函数 回调函数、闭包和匿名函数其实没有必然的关系但因为很多书上都将匿名函数和回调函数、闭包放在一起解释让人误以为回调函数、闭包需要通过匿名函数实现。实际上匿名函数只是一个有函数定义文本段却没有名称的函数而闭包则是一个函数的实例加上一个环境(严格意义上的定义)。 对于闭包和匿名函数来说仍然以python为例 def f(x):def g(y):return x yreturn g # 返回一个闭包有名称的函数def h(x):return lambda y: x y # 返回一个闭包匿名函数# 将执行函数时返回的闭包函数赋值给变量 a f(1) b h(1)# 调用存储在变量中闭包函数 print (a(5)) print (b(5)) 对于回调函数和匿名函数来说仍然以perl的find函数为例 #!/usr/bin/perl use File::Find;$callback sub {print $File::Find::name\n; }; # 创建一个匿名函数以及它的引用find( $callback,/tmp ); # 查找/tmp下的文件每查找到一个文件就执行一次$callback函数 匿名函数让闭包的实现更简洁所以很多时候返回的闭包函数就是一个匿名函数实例。
http://www.huolong8.cn/news/52090/

相关文章:

  • 做个网站要多少钱 一般云南省网站备案要求
  • 织梦网站上线可以做英文纵横字谜的网站
  • 有没有专门做布料的网站网站创建风格
  • nike网站建设方案网上销售网站建设
  • 投资理财网站建设规划书怎样建移动网站
  • 什么网站 是cms系统下载地址wordpress wp head
  • 创建电子商务网站的7个步骤企业网页设计与推广
  • 企业高端网站建设公司网站如何被收录
  • 广州网站建设找哪家网站后台管理系统需求
  • 库车县建设网站做电子元器件的网站
  • 临沭县住房和城乡建设局网站深圳品牌网站设计公司
  • 易云自助建站一直免费的服务器下载
  • 怎么用大淘客做网站东莞活动外包
  • 网站秒收录怎么做的有赞微商城小程序
  • 西安企业网站备案一般得多少天深圳新闻最新事件
  • 招标网站平台天津深圳网站开发定制
  • 游戏开发难还是网站开发难什么网站可以做任务领赏金
  • 上海自适应网站设计郑州网站建设那家好
  • 诸城盟族网站建设网站相关推荐怎么做
  • 网站网站建设平台注册公司是在哪个网站
  • 最新的购物网站 开广告公司叫什么名字好
  • 网站分析怎么做的万维网 网站到期
  • wordpress 导入html网站排名优化价格
  • 网站seo排名优化方法织梦门户网站源码下载
  • 网站制作的网站开发网站设计O2O平台优化
  • 网站访问统计js代码客户管理系统源代码
  • 鲜花网站建设论文网站建设找丿金手指排名
  • wordpress转换中文版怎样进行seo优化
  • 网站主导航设置问题wordpress 文章聚合
  • 手机网站微信登陆wordpress 移动app