元旦刚过(1月3日), 就收到了Håkon Wium Lie博士的回信。他欣然同意让我翻译他的博士学位论文——Cascading Style Sheets。在作了一些准备后,今天正式启动这个翻译项目。
Håkon Wium Lie博士
Håkon Wium Lie出生于1965年7月26日,是土生土长的挪威人。现为Opera Software的CTO(Chief Technology Officer,首席技术官)。他的个人页面维基百科词条

1994年,Håkon Wium Lie提出了层叠样式表的概念,并于当年10月提交了他的样式表建议——Cascading HTML style sheets。1996年12月,他亲自主持并以他的建议为基础创建的Cascading Style Sheets, level 1,正式成为W3C的推荐标准。后来,几乎所有主要浏览器都实现了CSS。CSS的普及,结束了长达数年之久的“表现性HTML”的历史,开创了标准Web开发中结构、表现、行为分离的新时代。

1995年, Håkon Wium Lie针对测试Web浏览器在呈现HTML标记、CSS2.1样式、PNG图像数据URI方面的支持情况,提出了Acid2建议。该建议后来由Web标准组织开发并发布,成为判定新(版)浏览器对Web标准支持情况的一个重要依据。

另外,Håkon Wium Lie与另一位CSS标准的制定者Bert Bos合著的Cascading Style Sheets: Designing for the Web, 3rd Edition 2005年5月由Addison-Wesley Professional出版。也是学习CSS的一本优秀图书。这里还有一篇发表于A List Apart的他们合写的文章:Printing a Book with CSS: Boom!

总而言之,翻译这篇论文的想法由来已久了。原因很简单,这篇论文是Håkon Wium Lie在他提出CSS的建议10年后写就的,其中全面翔实地包含了大量与CSS及Web发展有关的珍贵资料,是研究和学习CSS不可多得的重要参考文献。翻译这篇论文的过程,也是学习和研究的过程。希望自己在翻译完这篇论文后,对CSS和Web的理解能上升到一个新的层次。

这篇论文的中文版链接是:

http://www.cn-cuckoo.com/css/thesis-of-Hakon-Wium-Lie/

相关静态页面是:

http://www.cn-cuckoo.com/the-page-of-translating-thesis-of-hakon-wium-lie

论文至少每月更新一次——很可能每周一次。恳请感兴趣的朋友在上面静态页面中指出论文翻译中存在的问题,并提供您的宝贵意见!

Python也支持闭包,但在Python3.0以前,闭包不能访问外部函数中的局部变量。Python3.0为此引入了nonlocal关键字,从而完善了闭包访问外部变量的机制。

在Python2.6中,如果像下面这样定义函数:


>>> def outerFun():
    outerVar = 0
    def innerFun():
        outerVar += 1
	print outerVar
    return innerFun

然后,调用outerFun返回的闭包,会导致错误:


>>> f = outerFun()
>>> f()

Traceback (most recent call last):
  File "<pyshell #15>", line 1, in <module>
    f()
  File "<pyshell #12>", line 4, in innerFun
    outerVar += 1
UnboundLocalError: local variable 'outerVar' referenced before assignment

把错误消息“UnboundLocalError: local variable ‘outerVar’ referenced before assignment”翻译成中文,就是“未绑定局部变量:引用局部变量’outerVar’之前没有赋值”。啥意思呢?在内部函数innerFun中,outerVar被Python解释器看成是内部函数innerFun中的局部变量,并不是我们认为的外部(函数outerFun中的)变量。即在innerFun中,outerVar只是一个尚未赋值的变量——尽管与外部的outerVar同名,因此不能执行加法计算。Python3.0以前的版本提供了global关键字,通过这个关键字能够在函数内部引用并重新绑定(修改)全局变量:


>>> x = 1
>>> def c():
	global x
	x += 1
	print x

>>> c()
2

查看全文 »

在Python中,把*和**放在函数定义和调用中的参数前面,可以实现位置参数与元组,以及关键字参数与字典之间的转换。这种转换在函数定义中称为收集参数(collect parameters),在函数调用中称为分散参数(distribute paramters)。在定义函数时使用*,表示把参数收集起来并转换为一个元组,以便函数内部操作元组。如果有如下函数定义:


def collect(*params):print params

则说明这个函数可以接收多个参数,如:


collect(1,2,3) #<em> (1,2,3)</em>

可见,在函数collect中,params是一个元组。“既然需要元组,就直接传入元组不行吗?”事实上,也许在函数体中确实是处理可枚举的元组更方便一些,但提供元组参数则不一定比提供多个参数更方便。因此,定义时使用*就可以将传入的多个参数转换为元组。

在调用函数时使用*,表示传入的参数应该是一个需要分散的元组。即,函数定义中使用的应该是分散这个元组后得到的单个元素,如:


def distribute(x,y,z): print x,y,z
distribute(*(1,2,3)) # <em>1,2,3</em>

可见,此时传递给distribute函数的是分散(1,2,3)后得到的3个元素,相当于直接调用distribute(1,2,3)。

那么,既然distribute(*(1,2,3))与distribute(1,2,3)等价,何苦“先把参数放到元组中,再使用*将元组拆分为单个元素”呢?答案是,参数可能来自某个函数的返回值,而该值是元组,不是单个元素,因此调用时需要使用*将元组分散为单个元素。

总而言之,只要记住一条就行了:如果函数定义中使用了*,那么调用函数时,可以传入前置*的元组,也可以直接传入多个参数。

同样,关键字参数与字典之间的转换也是如此,只不过是使用**来实现的。复述一遍上面的结论:如果函数定义中使用了**(表示会把接收到的多个关键字参数转换为字典),那么调用函数时,可以传入前置**的字典(表示先将字典分散为多个关键字参数,然后再传入这些关键字参数),也可以直接传入多个关键字参数。

本质上讲,*和**就是两个转换运算符,分别用于实现多个参数与元组、字典间的转换。而支持这种转换的目的,就是为了增强代码在操作数据时的灵活性,或者所谓的表达能力。

如果在调用函数时,参数的位置决定参数的值,那么这种参数就是位置参数;如果参数的名称(关键字)决定参数的值,则这种参数就是关键字参数。例如,定义下面两个函数:


def hello_1(greeting, name): print '%s, %s!' % (greeting, name)
def hello_2(name, greeting): print '%s, %s!' % (name, greeting)

在调用这两个函数时,如果使用位置参数(即以参数位置决定参数值),则会有如下结果:


>>> hello_1('Hello', 'world')
Hello, world!
>>> hello_2('Hello', 'world')
Hello, world!

由此可以看出参数的名称并不重要,重要的参数的位置。但有时候,在参数较多时,记住参数位置比较困难。这时,就可以在传递参数(实参)时,使用定义时使用的参数(形参)名。例如:


>>> hello_1(greeting='Hello', name='world')
Hello, world!

而且,此时参数的位置已经不重要了:


>>> hello_1( name='world',greeting='Hello')
Hello, world! # 结果仍然相同。

但是,参数的名称却很重要:


>>> hello_2(greeting='Hello', name='world')
world, Hello!

关键字参数最大的好处,就是能够清楚地知道每个参数的角色。比如,单纯看下面这个函数调用:


>>> store('Mr. Brainsample', 10, 20, 13, 5)

如果不知道函数定义,恐怕除编写这行代码的人之外,谁也搞不清传递的这5个参数各自有什么用途,表示什么意思。如果使用关键字参数的话,问题就简单多了:


>>> store(patient='Mr. Brainsample', hour=10, minute=20, day=13, month=5)

当然,使用位置参数可以减少一些输入量,使用关键字参数的输入量要多一些。也可以说它们各有所长。但是,令关键字参数更具竞争优势的,则是可以通过它在定义函数时设置参数的默认值。例如:


def hello_3(greeting='Hello', name='world'): print '%s, %s!' % (greeting, name)

如果使用关键字参数设置了参数的默认值,那么调用函数时,可以不提供参数、只提供部分参数,或者提供全部参数:


>>> hello_3()
Hello, world!
>>> hello_3('Greetings')
Greetings, world!
>>> hello_3('Greetings', 'universe')
Greetings, universe!

啰嗦一点:位置参数和关键字参数可以组合使用,而唯一的要求就是位置参数必须出现在前面。混合使用位置和关键字参数的情形,通常是要求用户提供少量强制性参数和较多带默认值的可选参数的情形。例如,如果上面的hello函数要求用户必须提供一个名字(name),而问候语(greeting)和标点符号(punctuation)都是可选的,则可以这样来定义:


def hello_4(name, greeting='Hello', punctuation='!'): print '%s, %s%s' % (greeting, name, punctuation)

调用这个函数的方式有很多:


>>> hello_4('Mars')
Hello, Mars!
>>> hello_4('Mars', 'Howdy')
Howdy, Mars!
>>> hello_4('Mars', 'Howdy', '...')
Howdy, Mars...
>>> hello_4('Mars', punctuation='.')
Hello, Mars.
>>> hello_4('Mars', greeting='Top of the morning to ya')
Top of the morning to ya, Mars!
>>> hello_4()
Traceback (most recent call last):
File "<pyshell#64>", line 1, in ?
hello_4()
TypeError: hello_4() takes at least 1 argument (0 given)

如果函数定义中也为name指定默认值的话,最后一次调用就不会报错了。

Attention: We found a regression in the rc3 release that breaks datepicker in Internet Explorer. The issue has now been resolved with the rc4 release – please do not download the rc3 release anymore. We apologize for the inconvenience.

注意:rc3在IE中存在一个严重问题。rc4已经解决了这个问题。

按:jQuery UI 1.6rc3发布标志着jQuery UI 1.6接近封版。jQuery UI 1.6将于2009年1月14日随同jQuery 1.3一起发布。

昨天,jQuery UI Team负责人Paul Bakaus同学激动不已地宣布,1.6发版前的最后一个版本——jQuery UI 1.6rc3发布了。在过去忙碌的几个月中,设计方法、规范、代码基都经历了很大变化。也就是说,rc3并非rc2的简单的bug修正版,而是一套完全不同的代码。在新的交互设计方法的指导下,UI团队重新构建了许多部件的基础代码,也多次重构了相关部件,最终实现了更理想的观感效果。

jQuery UI 1.6rc3中显著的变化包括:

  • 翻新”日期选取器和滑动条(Datepicker and slider refresh)

为了适用新的主题(皮肤),对日期选取器作了必要调整:删除了一些选项,默认禁用了changeMonth和changeYear方法,引入了新方法showButtonPanel。具体细节近期将在相关标签(ticket)中公布。

滚动条也经过了重构。把’axis’选项改为了’orientation’、删除了’handle’和’handles’选项、为突出’step’而删除了’steps’和’stepping’、为突出’value’(选项和方法)而删除了’startValue’和’moveTo’,等等。滚动条规范页面包含更详细的说明。

UI团队将针对最终版本提供详细的兼容性信息和升级方案,以确保平稳过渡。

  • “检修”拖放逻辑(Drag & Drop logic overhaul)

完全重新设计了拖放及可排序部件的定位、交叉逻辑,并通过200多个自动测试用例测试了几乎全部可能出现的情形(即各种滚动偏移及位置值)。在此基础上,修正了至少30种定位错误的情形(即未包含滚动、提示条置顶等)。

  • 全新的部件设计(New widget designs)

jQuery UI 1.6rc3中所有部件的外观焕然一新。这既是新交互设计(Interaction Design)团队汗水的结晶,也得益于新jQuery UI CSS框架的支持。每个部件的标记和CSS都经过了重新搭配,从而构成了最整洁也最富弹性的解决方案。

  • CSS框架(CSS Framework)

jQuery UI 1.6rc3基于全新的CSS框架构建。这个新CSS框架不仅支持jQuery UI的内置插件,也支持用户开发的自定义插件。这个框架专门针对用户界面开发,而非整页布局的开发。其中包含各种常用的UI实用方法、状态、容器及图标的API,可以通过jQuery UI ThemeRoller调用。要了解这个框架的完整API,请参考:http://jqueryui.pbwiki.com/jQuery-UI-CSS-Framework(如果无法访问这个网址,使用Firefox的用户可以安装gladder扩展。然后,选择“通过代理访问”。)

  • 主题卷轴v2(Themeroller v2)!
  • 主题卷轴v2(——是不是受到2008北京奥运会开幕式中巨辐卷轴的启发呢?roller译为“滚筒”感觉不合适,不信可以看看人家那个“卷轴”图标。) 查看全文 »