我阅读了birdshome的在JavaScript中也玩变量类型强行转之后,在文章后面留言。也许我是表达不清楚,所以我想澄清一些情况,首先我反对使用“强制类型转换”这个词。 首先我们可以看C中间的强制类型转换,只能存在于基本类型之间,像整数可表示类型和浮点数类型之间,比如(int)2.45,这是可以的,但是他们和字符串之间都没有强制转换的可能,因为字符串实际是一个指针。因此不可能出现(char *)2.45就可以获得”2.45″这个字符串的情况,反之也不能。 而在C++中,我们可以创建一个类,并且重载强制转换操作,来完成这种情况,那么就必须要求有相应的对象,但是对于基本类型,这也是不可以的。 然后,因为JavaScript在对象模型上主要参考了Java,我们可以再参考一下Java的类型转换:在Java中,基本类型之间的强制转换也不是这样的,比如,整数要转换成字符串,必须使用Integer.toString()静态方法或者String.valueOf()静态方法,把字符串转换为整数,必须使用Integer.valueOf()。 可见,不能把JavaScript中的类型转换看作为“强制类型转换”。 在JavaScript中,Double类型和Int类型都是看作为Number对象,因此无论是typeof 1还是typeof 1.0,都是返回number。这样我们可以不用去管是Int还是Double类型,让JavaScript解释引擎内部去处理。 如果要把Number转换成String,可以使用Number的toString()方法,(象(1).toString()括号必须或者 1 .toString()空格必须,否则会编译出错,如果是变量则无需),或者调用String()函数,以及直接进行字符串连接(字符串变量或常量后直接进行“+”操作)这几种方法都会自动调用解释引擎内部的 NumberToString()函数,或者根据进制调用其它函数,基本类似。 如果要把String转换成Number,可以使用Number()函数,他会自动判断String中是整数还是浮点数,然后内部使用相应的数据类型,另外可以使用全局函数parseInt()和parseFloat(),他们根据你的要求进行转换。同样的,他们在解释引擎内部机制上是使用了 StringToNumber,StringToInt等等内部的函数。 而如果是Double转换成Int,必须使用Math.floor()函数(截尾取整)或者Math.round()(四舍五入)。使用parseInt只能增加运算量,先从Double到String再到Int Int转换成Double,无须考虑任何问题,直接把Int当成Double进行运算 注:Number、String函数是特殊的函数,在JS引擎中,他会自动判断是作为构造函数调用还是普通调用,所以既可以使用new关键字,也可以作为函数直接调用。 关于JS的参考手册,微软有一个CHM十分不错,指南、API参考都有,是Windows脚本技术,中文版,我在MSDN上下载的。而关于JS解释引擎的,我参考的是Netscape的Spidermonkey,现在由Mozilla组织维护。
在数据库中存储层次数据 作者:Gijs Van Tulder 翻译:ShiningRay @ NirvanaStudio 无论你要构建自己的论坛,在你的网站上发布消息还是书写自己的cms [1]程序,你都会遇到要在数据库中存储层次数据的情况。同时,除非你使用一种像XML [2]的数据库,否则关系数据库中的表都不是层次结构的,他们只是一个平坦的列表。所以你必须找到一种把层次数据库转化的方法。 存储树形结构是一个很常见的问题,他有好几种解决方案。主要有两种方法:邻接列表模型和改进前序遍历树算法 在本文中,我们将探讨这两种保存层次数据的方法。我将举一个在线食品店树形图的例子。这个食品店通过类别、颜色和品种来组织食品。树形图如下: 本文包含了一些代码的例子来演示如何保存和获取数据。我选择PHP [3]来写例子,因为我常用这个语言,而且很多人也都使用或者知道这个语言。你可以很方便地把它们翻译成你自己用的语言。 邻接列表模型(The Adjacency List Model) 我们要尝试的第一个——也是最优美的——方法称为“邻接列表模型”或称为“递归方法”。它是一个很优雅的方法因为你只需要一个简单的方法来在你的树中进行迭代。在我们的食品店中,邻接列表的表格如下: 如你所见,对每个节点保存一个“父”节点。我们可以看到“Pear [4]”是“Green”的一个子节点,而后者又是“Fruit”的子节点,如此类推。根节点,“Food”,则他的父节点没有值。为了简单,我只用了“title”值来标识每个节点。当然,在实际的数据库中,你要使用数字的ID。 显示树 现在我们已经把树放入数据库中了,得写一个显示函数了。这个函数将从根节点开始——没有父节点的节点——同时要显示这个节点所有的子节点。对于这些子节点,函数也要获取并显示这个子节点的子节点。然后,对于他们的子节点,函数还要再显示所有的子节点,然后依次类推。 也许你已经注意到了,这种函数的描述,有一种普遍的模式。我们可以简单地只写一个函数,用来获得特定节点的子节点。这个函数然后要对每个子节点调用自身来再次显示他们的子节点。这就是“递归”机制,因此称这种方法叫“递归方法”。 <?php // $parent 是我们要查看的子节点的父节点 // $level 会随着我们深入树的结构而不断增加, // 用来显示一个清晰的缩进格式 function display_children($parent, $level) { // 获取$parent的全部子节点 $result = mysql_query(‘SELECT title FROM tree ‘. ‘WHERE parent=”‘.$parent.’”;’); // 显示每个节点 while ($row = mysql_fetch_array($result)) { [...]
翻译:ShiningRay @ NirvanaStudio 原文地址:http://wiki.ciaweb.net/yawiki/index.php?area=DB_Table 什么是 DB_Table? DB_Table 是一个用于访问数据库表的面向对象接口。作为一个PEAR DB类的一个 包装,它提供了一些帮助你构建自动的创建、插入、更新和选择功能的方法。同时还有利用 HTML_QuickForm 自动构建输入表单的方法。 DB_Table提供了什么? DB_Table 提供了: 一个嵌在类属性中的模式描述系统,包括: 列定义 索引定义 标准查询 创建HTML_QuickForm元素的属性 从描述的模式自动创建表 一个抽象的API这样即便你改变了数据库后台也不需要改变你的PHP调用。这套API扩展了PEAR DB的功能,同时包含: 用于根据预定义的SQL查询来获取一个结果数组的select() 方法 用于根据预定义的SQL查询来获取一个PEAR DB_Result 对象的selectResult() 方法 create(), insert(), update(), 和 delete() 方法 自动模式检验 根据描述的表模式进行插入和更新字段时的自动检验 时间和日期数据类型抽象,覆盖了数据库的原始数据类型 … 即使你更改了数据库的后端,也无需修改你的查询。 不需要通过类型转换方法来改变查询的值。 当你插入或者更新列时,DB_Table 根据DB_Table 数据类型自动检验数据(datatype automatically (对所有的数据类型: integer, string,等等.). 根据描述的模式自动创建HTML_QuickForm元素,利用以下方法: getForm() 获取整个表单对象,有HTML_QuickForm元素和规则。 getFormGroup() 获取一组HTML_QuickForm元素。 getFormElement() 获取单一的HTML_QuickForm元素 [...]
隐喻 XP隐喻 (metaphor)必须能帮助你用可以理解的语言描述你的系统。 为了达到这个目的,我们可以在XP< /span>Web的“隐喻”一节中列出所有的隐喻术语。这些术语由一个名字/标题和他的解释组成。 “超描述” 通常作为“超描述”的东西现在是一个称为“文本模式”的一个大的功能特性。 如果在隐喻中定义了一个词,把{ 和}放在词的两边,就可以把它变成“超词”…… 注意你可以用词的复数形式(“words”可以找到“word”定义)。 事实上,搜索定义有三个级别: 搜索词的实际定义 如果没有结果,查找包含该词的那个词的定义。 最后,查找词的定义中包含该词的。 要获得更多的关于模式和如何修改的信息,看这里. 例子 参照只包含两个词的隐喻的例子,同时你注意第一个“连接”到了第二个。 尝试点击“senses”连接在第一个词的描述中,应该会出现一个弹出窗口连接到第二个词…… 同时,通过点击“修改”,注意这个连接只会基于这个词的复数形式(用括号括出)。
ShiningRay @ NirvanaStudio 安装 安装 XP Web 确保你已经拥有mysql(或者其他数据库,请在配置中指定)和一个可以运行PHP4或PHP5脚本的Web服务器(和相应的PHP库!如:如果要连接postgresql数据库必须启用php_pgsql扩展)。 [ 下载 ] the latest version of the tool (XPWeb.tgz 或者 XPWeb.zip). [ 解压 ] (unzip 或者 ungzip 和 untar) 文档. 把目录中的XPWeb 目录放到那个可以运行PHP和数据库的网络服务器的目录中。 你也许想在配置文件里[ 配置 ] 一些参数,例如数据库名称,登录名和密码 , 注意:配置十分重要,包括负载因子和其他参数,必须在初始化/更新数据库之前完成…… You should do this in a [ 本地配置] 你只要新建一个 [ Config_local.inc.php ] 文件,并把它放到XPWeb的根目录下 -和Config.inc.php同一位置- 并且将你要“本地化”的设置从 Config.inc.php 中复制过来。 你在本地进行的设置会覆盖默认的设置,那些没有放在本地文件中的设置就会设为默认。 [...]
Doc 文档部分包括四个很相似的子部分: 模型(modeling) 与模型相关的连接 Doc文档 其他文档文件 Javadoc Javadocs… 够明确了吧? 目录(Directories) 你希望被显示以便直接显示并访问其中的文件而不需要添加指定文档。 这些连接都在项目部分中定义. 注意如果项目的这些部分中只有一个连接被定义了,点击“Doc”标签会默认直接打开它。 再次点击“Doc”标签会把你带回“通常”的文档部分,显示所有的子部分。 打开 / 下载文档 – 所有这些文档都要遵守同一个原则: 文档会在一个框架页中打开,同时如果Web浏览器支持它的格式,它就会在页面中打开。 如果你知道浏览器不支持文档的格式,最好在新的窗口中打开(同时它可能会弹出一个对话框让你下载这个文档) 目录 目录十分特殊。 这是一种无需一个个手工添加文档就可以访问文档的方法。 层次结构可以通过点击子目录来打开。 注意:配置目录的时候要小心,因为如果层次很复杂的话页面显示会要用很长时间。 只能够选择本地的目录。 这里有一个View目录的例子 (一些按钮被禁止了).
作者:Phillip J. Eby. 翻译:ShiningRay @ NirvanaStudio 原文地址:http://dirtsimple.org/2004/12/python-is-not-java.html 我最近正在看一个基于wxPython的GUI应用程序,大概45.5KLOC的样子,但我没有计算它用到的库的大小(如Twisted)。代码是由那些对Python相对生疏的Java的开发者写的,所以程序有很严重的性能问题(如三十秒的启动时间)。我在检查代码的时候发现他们写了很多对Java有意义但是对Python却很恐怖的东西。并不是因为“Python比Java慢”,而是因为在Python中有更方便的方法去完成同样的目标,甚至在Java中不可能的事情。 所以,可悲的事就是这些可怜人事倍功半,产生了很多很多不需要写的代码,从而比相应合乎Python习惯的写法慢得多得多。我们来看一些例子: 在Java中一个静态的方法(static)不能翻译成一个Python的类方法(classmethod)。哦,当然,多多少少他最终产生类似的效果,但类方法的目的实际上是做了一些通常在Java中不可能的事(如继承一个非默认的构造函数)。Java静态方法的习惯翻译通常是一个模块级函数,而不是一个类方法或静态方法(staticmethod)。(同时静态封闭(final)字段应该翻译成模块级常量。) 这并不是一个性能上的问题,但是一个Python程序员要用像这些类似Java习惯的代码的话,可能就会被在该输入Foo.someFunction时却要输入Foo.Foo.someMethod这种情况给惹毛了。但是请注意:调用一个类方法将会比调用一个静态方法和函数要多一部分额外的内存。 啊,那些Foo.Bar.Baz也不是省油的。在Java中,这些点分割的名称是由编译器去查找的,所以运行时根本无所谓你有多少点。在Python中,每次运行时都要查找,所以每个点都要计算在内。(Python中一定要记住这点,“平铺比嵌套好”,尽管比起性能,他和“可读性”和“简单就是美”更靠近。) 要用switch语句?Python翻译将是一个哈希表,不是一堆if-then语句。用一堆if-then在Java中也不是switch语句,如果有字符串参与了呢?他其实是一个哈希表。CPython字典实现用了性能最佳—在我们宇宙中目前所知道的—的哈希表的实现之一。你自己所写的代码也不会比这个再好了,除非你是Guido、Tim Peters和Raymond Hettinger的“私生子”——还是遗传增强了的。 XML不是答案。它也不是一个问题。要在正则表达式上解释Jamie Zawinski,“一些人,当遇到一个问题的时候,就想‘我知道,我要用XML’那这个时候,他们就有两个问题了。” 和Java比,这是一个不同的情况。因为比起Java代码,XML是轻巧而且有弹性的。但比起Python的代码来,XML就是一个船锚,一个绊脚石。在Python中,XML是用来做交换,而不是你的核心功能,因为你不需要这么做。在Java中,XML可能是你的大救星因为他让你实现了特定领域的语言并“不通过编码”提高了你的应用程序的适应性。在Java中,避免编码是一个很大的优势,因为编码意味着重新编译。但在Python中,更常见的是,写代码比写XML更方便简单。同时Python处理代码要远远比处理XML快。(不仅仅是这个,你必须书XML处理代码,同时Python自身就已经为你准备好了。) 如果你是一个Java程序员,对于你是否要在你的Python核心应用中使用XML作为一部分,不要相信你的本能。如果你不是因为信息交互的原因去实现一个已经存在的XML标准或是建立某种导入、导出格式或者建立某种XML编辑器或处理工具,那么就不要这么做。一次也别。甚至连想都不要想。现在,扔掉那个XML模式把你的手解放吧!如果你的应用程序或者平台要被Python开发者使用,他们只会感谢你不要在他们的工作量中添加使用XML的负担。 (这里唯一的例外是如果你的受众的的确确,确确实实需要XML,出于某种奇怪的理由。像,他们拒绝学习Python并只对你使用了XML而付钱给你,或者你打算给他们一个编辑XML的GUI,同时这个写XML的GUI呢是另一个人写的,同时你得到免费使用的权利。还有一些很少见的架构上的原因需要用到XML。相信我,他们不会出现在你的程序中。如果有疑问,对一个资深的Python开发员解释你的用例。或者,如果你脸皮厚的话,试试向一个Lisp程序解释你的程序为什么要用XML!) Getter和setter是坏蛋。坏蛋,魔鬼!Python对象不是Java Bean。不要写什么getter和setter,然后还把它们包装在“属性”里面。它直到你能证明你需要比一个简单访问复杂一点的功能时才有意义,否则,不要写getter和setter。它们是CPU时间的浪费,更要紧的是,它们还是程序员宝贵时间的极大浪费。不仅仅对于写代码和测试的人,对于那些要阅读和理解它们的人也是。 在Java中,你必须使用getter和setter因为公共字段不允许你以后改变想法再去使用getter和setter。在Python中,这样做很傻,因为你可以以一个普通特性开始并可以在任何时间改变你的想法,而不用影响到这个类的任何客户。所以不要写getter和setter。 代码重复在Java中常常是一个不得不要的魔鬼,你必须经常一遍一遍写同一个方法而只有一点点的变化(通常是因为静态类型约束)。在Python中这样做是没有必要的也是不值得的(除了极少数一些特定的场合需要内联一些要求性能的函数)。如果你发现自己一遍一遍在写同样的代码而且变化很少,你就需要去学一下闭包。他们并不是真的很可怕。 这就是你要做的。你写了一个包含了函数的函数。这里内部的函数就是你要一遍遍写的函数的模版,但是在里面加入了针对不同情况的函数要使用变量。外部的函数需要刚刚提高的那种变量作为参数,并且将内部的函数作为结果返回。然后,每次你要写另一种略微不同的函数的时候,你只要调用这个外部的函数,并且把返回值赋给你要让“重复”函数出现的名字。现在,如果你需要改变这个工作方式,你只要改变一个地方:这个模版。 在我所看过的应用程序/平台中,只有一个很微不足道的程序使用了这个技术之后可以去掉数百行重复代码。事实上,自从开发者使用了特别的样板文件来为这平台开发插件,这会节省很多很多第三方开发人员的代码,同时也使那些程序员要学习的东西简化了。 这只是Java->Python思维方式转变的冰山一角而已,现在我可以让他转变成正确的而不用钻研这个程序的细节。本质上,如果你曾经用过一段时间Java,而且对Python比较陌生,不要太相信自己的本能。你的本能已经为Java调节,而不是Python。向后退一步,最重要的,不要写这么多代码了。 要这样做,让自己觉得更加需要Python。假装好像Python是可以做任何你想做的魔棒,却让你无须动一个手指。问一下,“Python是怎样解决我的问题的?”还有“Python语言的哪个特点和我的问题最相似?”你绝对会惊讶于你需要的东西其实已经有了某种固定形式。事实上,这种现象实在是太普遍了,甚至在很有经验的Python程序员中也会出现,以至于Python社区中给这种现象起了个名字。我们称之为“GUIDO的时间机器”,因为有时候看上去得到我们所需要的东西好像只有他知道的一种方法,但当我们自己知道了就不一样了。 所以,如果你不能感到你在使用Python时至少比用Java要多出10倍的生产力,!(同时如果你还怀念你的Java IDE,考虑一下这种可能性:因为你写的Python程序比他所需要的要复杂得多) 附录:(翻译自此篇文章的评论) 确实,哈希表==字典。举个最简单的例子,从Python 标准库中检出“pickle”和“copy”模块,这两个模块会从字典中查找类型并调用相应的函数。另一个有些诡异的例子是范型函数,我已经在最近的Blog中写了一下。 关于闭包的例子,我这里给出一个很笨的例子。假设你要写很多这样的函数: def addOne(x): return x+1def addTwo(x): return x+2 然后你可以这样写: def makeAdder(addend):… def add_it(x): return x+addend… return add_it 并且这样使用: addOne = makeAdder(1)addTwo = [...]