autodataming的个人博客分享 http://blog.sciencenet.cn/u/autodataming

博文

回调函数 callback 在perl中的表现

已有 2067 次阅读 2014-10-18 12:16 |个人分类:系统|系统分类:科研笔记

回调函数 callback perl中的表现

 

来自qqPERL学习交流   144539789;卖茶叶的perl高手 744891290

 

 

我稍微总结了下回调函数,callback,希望能帮助新手理解模块中的callback

 

回调函数的认识:

1回调函数是一个函数,其在脚本中只能以参数的形式进行传递。不被直接调用。在perl中有两种形式。

$funcrefer=sub {}; #引用

Sub xxx {}; \&xxx,#函数的引用取其地址

2回调函数存在的价值:

1>封装,掩藏内部细节,增加代码的灵活性.

所以回调函数多出现在模块当中

3我们需要知道回调函数作为参数,传递给了那个函数。

在这个函数中,给回调函数哪些参数

4主调函数调用回调函数的特性

自动执行。

当主调函数执行的时候就会触发回调函数。

完善主调函数的。

主调函数包含被调函数,只要主调函数可以主动调用,当调用主调函数的时候,被调函数被迫执行。

5 New 是构造函数,new只是个初始化,没有业务逻辑

不能认为是主调函数

如果乱码,请下载word文档

回调函数perl.docx



 

Example1

模块HTML::LinkExtor;

创建对象有3种方式

$p =HTML::LinkExtor->new

$p = HTML::LinkExtor->new($callback )

$p = HTML::LinkExtor->new( $callback, $base )

其中方法2,3使用到了回调函数。

我们需要了解回调函数自身的参数,

 

 

Script1

require HTML::LinkExtor;

$p =HTML::LinkExtor->new(\&cb, "http://www.perl.org/");

sub cb {

    my($tag,%links) = @_;

    print"$tag @{[%links]}\n";

}

$p->parse_file("index.html");

 

Script2

use LWP::UserAgent; use HTML::LinkExtor; use URI::URL;  $url="http://www.perl.org/"; # for instance $ua= LWP::UserAgent->new;  # Set up a callback that collect image links my@imgs=(); sub callback { my($tag,%attr)=@_; returnif$tag ne 'img'; # we only look closer at <img ...> push(@imgs,values%attr); }  # Make the parser. Unfortunately, we don't know the base yet # (it might be different from $url) $p= HTML::LinkExtor->new(\&callback);  # Request document and parse it as it arrives $res=$ua->request(HTTP::Request->new(GET =>$url), sub{$p->parse($_[0])});  # Expand all image URLs to absolute ones my$base=$res->base; @imgs=map{$_=url($_,$base)->abs;}@imgs;  # Print them out printjoin("\n",@imgs),"\n";

 

从案例给的2个脚本,我们可以看出cb 接受连个参数,一个tag,一个是hash

其中描述当中也中这样一段话

$p = HTML::LinkExtor->new( $callback, $base )

The constructor takes two optional arguments. The firstis a reference to a callback routine. It will be called as links are found. Ifa callback is not provided, then links are just accumulated internally and canbe retrieved by calling the $p->links() method.

The $base argument is an optional base URL used toabsolutize all URLs found. You need to have the URI module installed ifyou provide $base.

The callback is called with the lowercase tag name asfirst argument, and then all link attributes as separate key/value pairs. Allnon-link attributes are removed.

构建对象的时候有两个可选参数,其中第一个$callback是回调函数,它的作用是找到所有的链接。

如果没有提供回调函数,也就是方法1.这时候要想得到所有的链接可以通过$p->links()来获得。

第二个可选参数$base,目的是用于返回绝对链接。

 

回调函数接受的参数第一个参数是小写的tag的名字,第二个参数是hash,

Hash是这样子的一般情况是一个key和value,也有两个key-value的情况;

如:

if the element is:

<img border=0 src="pics/medium-sigils.gif"height=71 width=151

align=right lowsrc="pics/small-sigils.gif"alt="$@%">

 

 

 

The arguments to the callback will be:

('IMG', 'SRC' => '.../pics/medium-sigils.gif',

'LOWSRC' => '.../pics/small-sigils.gif', )

 

 

$p->links

Returns a list of all links found in the document. Thereturned values will be anonymous arrays with the following elements:

 [$tag, $attr=> $url1, $attr2 => $url2,...]

The $p->links method will also truncate the internallink list. This means that if the method is called twice without any parsingbetween them the second call will return an empty list.

Also note that $p->links will always be empty if acallback routine was provided when the HTML::LinkExtor was created.

如果单独构建HTML::LinkExtor,则主调函数中不包含回调函数。

只能通过这个方法来返回所有的链接$p->links;其实返回的链接恰恰是会调函数中的参数的总合。

 

由于$p->links 是直接修改links列表,所以只能操作一次。

所以如果提交了回调函数,这$p->links的值将为空。

 

我们已经了解了回调函数。

现在可以简单了解下主调函数。

特别注意:

 

new只是个初始化,构造函数,没有业务逻辑 ,不算主调函数。

 

 

 

 

 

 

 

 

 

从脚本1中我们可以知道主调函数是prase_file;

从脚本2中我们可以知道主调函数是prase。

 

在脚本2中我们发现,request也是主调函数,它的第二个参数是回调函数

$res=$ua->request(HTTP::Request->new(GET =>$url), sub{$p->parse($_[0])}); 要想读懂这段代码,我们又需要了解$_[0] 是什么含义?回到cpan LWP::UserAgent;的模块主页上,

$ua->request($request )

$ua->request( $request,$content_file )

$ua->request( $request, $content_cb )

$ua->request( $request, $content_cb, $read_size_hint )

我们可以发现request有4种形式,其中第3中形式是我们现在用的。

看到cb就知道是callback回调函数。

 

This method will dispatch the given $request object.Normally this will be an instance of the HTTP::Request class, butany object with a similar interface will do. The return value is a responseobject. See HTTP::Request and HTTP::Response for a description of the interface provided by these classes.

 

这个方法返回的是response对象。

 

The request() method will process redirects andauthentication responses transparently. This means that it may actually sendseveral simple requests via the simple_request() method described below.

The request methods described above; get(), head(),post() and mirror(), will all dispatch the request they build via this method.They are convenience methods that simply hides the creation of the requestobject for you.

里面实现的细节,包含http的4个方法。

The $content_file, $content_cb and $read_size_hint allcorrespond to options described with the get() method above.

回调函数$content_file和大小是可选参数,

且必须是get的方法适合才能用回调函数。

Prase参数的说明,是文本

$p->parse($string )

Parse $string as the chunk of the HTML document. Handlersinvoked should not attempt to modify the $string in-place until $p->parsereturns.

If an invoked event handler aborts parsing by calling$p->eof, then $p->parse() will return a FALSE value. Otherwise the returnvalue is a reference to the parser object ($p).

,我们可以推断出$_[0],代表的是文本的内容。

 

You are allowed to use a CODE reference as content in the request object passed in. The content function shouldreturn the content when called. The content can be returned in chunks. Thecontent function will be invoked repeatedly until it return an empty string tosignal that there is no more content.

 

 

Parse 中的参数是要要解析的完整内容

在解析的过程中,有一个事件函数,碰到link就调用回调函数。

直到解析到文件末尾。

 

补充一次性函数举例

#!/usr/bin/perl -w

 

 

use HTML::LinkExtor;

$p = HTML::LinkExtor->new;

$p->parse_file("index.html");

@aa=$p->links;

print join "\n",@{$aa[0]};

print"end\n";

@aa=$p->links;  #已经空了,只能使用一次

print join "\n",@{$aa[0]};

print "nothingn";

 

 

 

 

 

 

 




http://blog.sciencenet.cn/blog-950202-836680.html

上一篇:解决SCF不收敛问题的方法---XQC关键词的重要性
下一篇:pymol中python脚本运行方法 run 和@的区别

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备14006957 )

GMT+8, 2020-1-20 03:32

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部