免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3483 | 回复: 17
打印 上一主题 下一主题

pppk之Recipe1.2(1) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-08-17 20:13 |只看该作者 |倒序浏览
今天开始Recipe 1.2: 默认值的使用。准备分2天来完成发帖。
代码的checkout方法:

  1. svn checkout http://pppk.googlecode.com/svn/trunk/ pppk
复制代码
Recipe1.2的引用话是:
  1. 今天不知为什么我没写--果戈里
复制代码
据说,当他没写作灵感的时候,他就反复写这句话,直到又开始写作。

论坛徽章:
0
2 [报告]
发表于 2012-08-17 20:25 |只看该作者
本帖最后由 zhuyubei 于 2012-08-17 20:56 编辑

当然我今天得写。对于给一个变量或数组赋默认值。核心思路是这样的:
  1. use $sFirst if $sFirst is true, else $sSecond
复制代码
很好理解。但这牵涉到,什么会是true, 什么会是false。 在Perl以及Python,这会有些微妙
  1. my @aFirst = ( undef, 0, "0", 0.0, "0.0" , 00000, "00000", "", " ", 23, "32", [] );
  2. my $sSecond = "backup";

  3. # Pay attention to the values which are false
  4. foreach my $sIndex ( 0 .. $#aFirst ){
  5.         my $sFirst = $aFirst[ $sIndex ];       
  6.         # use $sFirst if $sFirst is true, else $sSecond
  7.         my $sDefaultValue = $sFirst || $sSecond;
  8.         if( $sFirst ){
  9.                 print "[ $sIndex ] I'm first: [$sDefaultValue]\n";
  10.         }
  11.         else{
  12.                 print "[ $sIndex ] I'm Second: [$sDefaultValue], first is  [$sFirst]\n";
  13.         }
  14. }
复制代码
在@aFirst里的值都会被if测试是True还是false。我们的常识是0, undef, ""一定是false。但这还不够,由于Perl是弱类型,字符串里含数字,可以被尝试进行数值化转换。所以要注意: 字符串"0"也是false。那0.0是不是false呢?它也是false.但要注意"0.0"又不是false。这要注意啊。另外00000是false, 但是"000000"又是true!
有些吭爹是吧。我特意在里面放了一个空数组的引用,它不是false。
希望有高手能对这样的现象给个好的解释。

论坛徽章:
0
3 [报告]
发表于 2012-08-17 20:36 |只看该作者
Perl里标量的赋默认值的语句如下。
  1. my $sDefaultValue = $sFirst || $sSecond;
复制代码
利用||的短路特性,如果第一个表达式是true的话,它就直接返回其值,如果不是true,就返回第二个值。

但在这样的情况下,由于0这样的值也被当作是false, 而它也许是数组里的一个你需要的下标。所以你可以采取另一种更严格的方式来判断其是不是false。也就是
  1. 用defined函数来判断,只有当变量是undef的时候它才是false
复制代码
按照这样的思路,我们可以用三元表达式来做这样的工作。
  1. my $sNotDefined = undef;
  2. my $sDefaultValue = defined( $sNotDefined ) ? $sNotDefined : $sSecond ;
  3. print "When using undef: $sDefaultValue\n";
复制代码
当然在标量环境下你也可以用 or 来代替 ||以获得更好的可读性。但是要注意操作符优先级的问题。
  1. my $sDir = $ARGV[ 0 ] or "/tmp"; # or: another form of ||
复制代码
最后一个例子是多个候选默认值的例子
  1. my $sUser = $ENV{ USER } or $ENV{ LOGNAME } or
  2.                  getlogin( ) or ( getpwuid( $< ) )[ 0 ] or
  3.                  "Unknown uid number $<";  
复制代码

论坛徽章:
2
CU大牛徽章
日期:2013-04-17 11:46:28CU大牛徽章
日期:2013-04-17 11:46:39
4 [报告]
发表于 2012-08-17 20:44 |只看该作者
学习学习...

论坛徽章:
0
5 [报告]
发表于 2012-08-17 20:51 |只看该作者
本帖最后由 zhuyubei 于 2012-08-17 20:58 编辑

轮到Python了。Python里没有 ||, 只有or
  1. value = a or b
复制代码
我们还是看看什么样的值是false,什么样得值是true
  1. firstlist = [ None, 0, "0", 0.0, "0.0", 00000, "00000", "", " ", 23, 32, [ ] ]
  2. second = "backup"

  3. # Pay attention to the values which are false
  4. for index in range(len(firstlist)):
  5.         # use first if first is true, else second
  6.         value = firstlist[ index ] or second
  7.         if firstlist[ index ]:
  8.                 print "print [ %d ] I'm first: [%s]" %( index, value )               
  9.         else:
  10.                 print "print [ %d ] I'm second: [%s], first is [%s]" %( index, value, firstlist[ index ] )
复制代码
Python是个强类型的语言。字符串是不能隐式转成数字的。所以这里"0"是true. 0.0这里依旧是false. 不同的是,里面的一个空列表。虽然同样放得是引用,但是空列表在这里被当作是false! 这一点和Perl不一样。Perl的引用测试的时候想必类似于字符串。

同样,为了避免把0也当作是false. Python里面同样用None来作为Perl里的undef。你可以用is not None来判断是不是空的. 而且Python里没有三元表达式的。在Python里,它引入了这样的方式来作为三元表达式, a if a is not None esle b
  1. notdefined = None
  2. # use first if first is not a none value, else second
  3. # property and / or operator
  4. value = notdefined if notdefined is not None else second # From python 2.5
复制代码
其语句的意思几乎就和注释: use first if first is not a none value, else second一致。

另外对于Python2.5之前的版本。可以这样写
  1. value = notdefined is not None and notdefined or second  # Before python 2.5, not so readable
复制代码
我觉得可读性不很好。对于可读性不好的东西,我都有些抵触。这里它用了and 和 or的赋值特性。 对于and如果第一个是true,它就返回and后面的那个值,否则就返回第一个false。而对于or, 如果第一个是false,它就返回or里的第二个表达式的值,否则就返回第一个值。

而对于连续多个候选默认值的问题。Python也差不多。
  1. user = os.environ["USER"] or os.environ["LOGNAME"] or\
  2.        os.getlogin( ) or pwd.getpwuid( os.getuid() )[ 0 ] or\
  3.        "Unknown uid number %" % os.getuid();
  4. print "User:",user
复制代码
好了,今天就写到这里

论坛徽章:
0
6 [报告]
发表于 2012-08-17 20:55 |只看该作者
对于Perl来说,可能给变量默认值会更有用些。尤其是给一些函数传参数。如果参数不是很多,你又不想用hash来赋默认值的话,就可以用今天说的Recipe来给参数赋默认值。而Python的函数参数由于可以指定默认值,所以也许未必这么有用。

总之一句话,要是函数的参数需要给默认值,希望大家能记起这个Recipe。

论坛徽章:
46
15-16赛季CBA联赛之四川
日期:2018-03-27 11:59:132015年亚洲杯之沙特阿拉伯
日期:2015-04-11 17:31:45天蝎座
日期:2015-03-25 16:56:49双鱼座
日期:2015-03-25 16:56:30摩羯座
日期:2015-03-25 16:56:09巳蛇
日期:2015-03-25 16:55:30卯兔
日期:2015-03-25 16:54:29子鼠
日期:2015-03-25 16:53:59申猴
日期:2015-03-25 16:53:29寅虎
日期:2015-03-25 16:52:29羊年新春福章
日期:2015-03-25 16:51:212015亚冠之布里斯班狮吼
日期:2015-07-13 10:44:56
7 [报告]
发表于 2012-08-17 21:21 来自手机 |只看该作者
Truth and Falsehood
The number 0, the strings '0' and "" , the empty list () , and undef are all false in a boolean context. All other values are true. Negation of a true value by ! or not returns a special false value. When evaluated as a string it is treated as "" , but as a number, it is treated as 0. Most Perl operators that return true or false behave this way.

论坛徽章:
46
15-16赛季CBA联赛之四川
日期:2018-03-27 11:59:132015年亚洲杯之沙特阿拉伯
日期:2015-04-11 17:31:45天蝎座
日期:2015-03-25 16:56:49双鱼座
日期:2015-03-25 16:56:30摩羯座
日期:2015-03-25 16:56:09巳蛇
日期:2015-03-25 16:55:30卯兔
日期:2015-03-25 16:54:29子鼠
日期:2015-03-25 16:53:59申猴
日期:2015-03-25 16:53:29寅虎
日期:2015-03-25 16:52:29羊年新春福章
日期:2015-03-25 16:51:212015亚冠之布里斯班狮吼
日期:2015-07-13 10:44:56
8 [报告]
发表于 2012-08-17 21:25 来自手机 |只看该作者
希望再讲下perl的 //   defined-or

论坛徽章:
0
9 [报告]
发表于 2012-08-17 21:36 |只看该作者
谢谢版主大人的回复。我对not和!的特性又有了更好的理解。

的确Cookbook里是有//的,看来你很熟悉的,哈哈. 因为我的Perl版本是Perl5.8.8的,虽然可以use 5.9,不过我一直比较反感IT行业的升级更新之类的情况。当时就没加入这块内容。

不过既然您提到了,我还是马上更新下code, 把这块加进去吧!谢谢!

论坛徽章:
0
10 [报告]
发表于 2012-08-17 21:50 |只看该作者
我只知道现在用的比较多的方式应该是
  1. $var=$a // $b
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP