切尔斯基

冰河洗剑,绝塞传烽,江山如画雪初晴

李光磊ID:chelsea
134589次访问,排名575好友0人,关注者6
chelsea的文章
原创 38 篇
翻译 2 篇
转载 0 篇
评论 123 篇
切尔斯基的公告
质疑暂停, 发些以前的外传
最近评论
Jack:比喻很恰当,呵呵.
suxiaoguai:敏捷有好处也有短板:
==================
如果结对的双方没有类似的知识结构,效率一定不会高。这种情况下双方之间更多的是思想上的摩擦和相互学习,不是合作解决实际问题。结对需要长时间的前期投入才能开始起作用。
==================
这是个问题,所以敏捷一定需要有公司支持这个土壤。
另外团队的文化非常重要,
hachenzhonghua:结伴比较难。
这个对企业整体文化、管理能力要求比较高。
心胸坦荡的人并不多。落井下石的人却总是不缺
iceheart:你跟某人适合xp跟另外一些人不见得适合,某个项目适合xp另外的项目不见得适合,某些环境适合xp另外的不见得适合。

脱离了具体情况的空谈都是没有意义的争论
Eric:敏捷开发,纯粹扯淡!
前期开发者,写代码,写的很爽很惬意,进度相当快。
如果前期开发者离去,或者转投别的任务。
后期开发者,和同期的开发同伴,对已有的代码,简直牛啃南瓜,开不了头。
========================
这是质量控制体系有问题,没有code review?没有QA?没有相应的文档?
如果把前期的开发分成几……
文章分类
    收藏
      相册
      切尔分站
      切尔斯基的工作(RSS)
      切尔斯基的工具(RSS)
      切尔斯基的杂记(RSS)
      亲密爱人
      丸子(RSS)
      文学艺术
      芳村窝蛋(RSS)
      存档
      订阅我的博客
      XML聚合  FeedSky

      原创 The Python Programming Language Notes收藏

      新一篇: The C# Programming Language Notes II | 旧一篇: The SICP Notes

       

      刚看完Python手册中的Tutorial部分,以类C程序员的角度观察了一下Python,文中涉及的所有Python与Java,C++不同的地方都只有一个原因:Python不是Java或C++,就像bitflying说的:“However, *DO* we really need another dynamic language just like JAVA? As a scripting language, it's important for users to keep it simple, clean and easy to use. ”

      See Also: http://blog.csdn.net/chelsea/category/20285.aspx

       

      一. 语法

      1. 按名称调用,不是按类型调用

      Python在一切可能的地方弱化了类型:不能/无需声明函数返回值类型,不能/无需声明函数参数类型,对名称的查找/检查在运行时进行;这样的机制带来了几个后果:

      • 天生具有多态,virtual失去意义,因为不存在使用基类指针指向子类的情况

      • 类型退化为组织代码、保存状态的一种方式,“继承”退化为一种普通的代码复用的机制

      大部分情况下子类实际上将父类当作一个普通的类库来调用,而接口或者抽象基类几乎没有存在的理由;虽然Template Method之类的模式依然起作用,但在构建Framework方面,“继承”已不再重要如昔

      一个例子就是for迭代,只需按约定提供__iter__()返回定义有next()的对象,即可用于for value in XXX 形式的迭代语句中

      一个例外是Exception的继承,是因为try/except是少见的根据类型而不是名称来工作的,构建一个Exception的继承体系对于异常处理来说还是很方便的

       

       

      2. Tuple Anywhere

      牵强一点,Tuple几乎是传统的DTO(数据传输对象)模式在语言级别的直接支持;当然,这只是Tuple众多应用之一

      Tuple是Python基本数据结构之一,其思想十分简单,就是用一个单一的量来代表一堆任意数据松散的集合,其显而易见的一个用处就是在一次函数调用中返回多个值;

      在非单根结构,强类型的语言如C++中,是很难实现能够容纳任意多元素的Tuple的,标准库提供了一个退化的Tuple,std::pair<F,S>,只能容纳两个元素,boostloki提供了能够容纳最多两位数元素的Tuple,绝大多数情况下也够用了;

      或曰:在像Java这样的单根语言中,Tuple不就是Object[]吗?是的,如果Tuple仅限于容纳多个元素,它就是只读的Object[]

      然而,Python为Tuple配备了Automated Tuple Packing & Automated Sequence Unpacking (自动化的打包/拆包),使Tuple获得了及其方便和强大的表达能力 

      • 自动打包带来的表达能力举例:函数调用传递任意的参数个数,不需要你显式的把多个参数像其它语言那样弄到一个数组或集合里,你只需要把多个参数一个接一个的传递给函数即可,解释器会将参数自动打包为Tuple;C++的可变参数在这种以强类型著称的语言中显得那样格格不如,在各种Effective条款中被推荐避免使用;JavaSE 5.0 开始提供了类似的功能,虚拟机会将参数打包为数组 

      • 自动拆包带来的表达能力举例:同时获得Dictionary的Key和Value:for key, value in dict.iteritems(): 你不再需要像其它语言那样在循环体里再分别获得key和value 

      • 自动打包结合自动拆包带来的表达能力举例:不使用临时变量交换两个变量的值:a, b = b, a

      更多的时候,Tuple为其它的Python语法提供背后的支持

       

       

      3. Decorator:面向属性编程

      Python也有类似.Net的Attribute,Java的Annotation的机制,叫做Decorator,不过目前只能用于修饰function或method,不能用来修饰class;这类机制的用处不必多说,主要是用于正交的分离职责,最终各种运行时,平台,或者工具会将各种分离的职责合并成一个功能完整的可执行体;PEP 318给出的例子有:

      • 通用的参数和返回值检查

      • 通用的额外属性的注入

      • 通用的线程安全的保护

      • 类的singleton标记

      • ...

       

       

      4. 无可比拟的参数机制

      1. Pass object reference by value, hehe 

      2. 任意参数,避免了对参数个数的依赖,全面超越Unary,Binary的表达能力

      允许用一个参数占位符来表达运行时的多个参数,使Python可以写出不依赖参数个数的通用算法,将函数、过程、谓词区分为零元、一元、二元已经不像在其它语言中那样迫不得已

      比如说通用算法map,C++提供了map的一元形式:map(unary_functor, begin, end),那么如何使map适用于二元算子呢?通常有两种做法:

      • 一种是添加map的二元形式(在Java实现的Apache Common Functor中就是这么做的),局限在于三元、四元呢?

      • 一种是使用适配器,将二元函数适配为一元,如bind1st, bind2nd等,当参数不固定时要写出专用的适配器

      Python使你可以写出map的通用形式:

      def map(oper, *sqs): #simulate standard map()
          return [ oper( *[(sq[i]) for sq in sqs] ) for i in range(len(sqs[0]))]

      或者,使用内置的zip函数,更紧凑一点:

      def map(oper, *sqs): #another way to simulate standard map()
          return [ oper( *tuple ) for tuple in zip(*sqs) ]

      是的,这就是任意元都通吃的map,只有一行代码而已;我没有看过Python源代码,不知道真正的map是如何实现的

      测试一下:

      def testUnaryMap(self):
          self.assertEquals([1,2,3], map(math.ceil,   [0.6, 1.3, 2.4]) )

      def testBinaryMap(self):
          self.assertEquals([64,25,6], map(math.pow,   [4,5,6],     [3,2,1]) )
       

      ......
      ----------------------------------------------------------------------
      Ran 2 tests in 0.000s

      OK
       

      3. Keyword参数,避免了位置依赖,极大提高可读性,降低错误倾向

      参数不宜过多基本是普适的,但不是人人都遵守,在C++, Java中,如果参数比较多,又都是同一类型,对客户程序员来说简直就是恶梦,他要仔细核对参数的位置,不要将相同类型的参数弄颠倒了,编译器和IDE都帮不上什么忙;

      另一个不便之处就是无论你的函数声明、定义时参数的名字多么具有可读性和意义明显,编译之后就只剩类型信息了

      然而Python提供了期待已久的根据参数名字传递参数的特性,基本解决了前面两个问题,观察一下下面这行代码:

      pathCtrl = wx.TextCtrl(self, -1, "", (30, 50), (150, 20))

      你知道,或者说你记得住(30, 50),(150, 20)哪一对是位置,那一对是大小吗?再看下面这一行

      pathCtrl = wx.TextCtrl(self, -1, "", pos=(30, 50), size=(150, 20))

      真是清晰舒适啊

       

       

      5. 语法糖衣

      • for/else, while/else: 适用于方便的指定集合中所有元素都不满足某谓词时的行为

      传统代码

      Python的for/else

      int i = 0;

      for(; i < len; i++){

          if (xxx) break;

      }

      if (i == len) {

          ...

      }

      for x in range(n):
         if n % x == 0:
            print n, 'equals', x, '*', n/x
            break
      else:
         # loop fell through without finding a factor
         print n, 'is a prime number'

      • try/except/else,try/finally:适用于方便的指定“清理”行为

      这两组语句不可混合使用,给出的理由是当except子句和finally子句同时存在时逻辑上无法证明先执行哪个是普适的合理的,呵呵

      else子句当try块没有抛出异常时被执行

      finally则用于任何原因离开try块时执行,当然,断电除外

      • lambda

      在函数是一级公民的语言中,lambda是可有可无的

      善用是糖衣,滥用则是毒药,主要是影响可读性和可维护性

      • String Literals

      现在流行的语言几乎都提供了丰富的String处理函数,但如何方便的表达String literal, 很多语言却重视不够,尤其是对于转义字符和换行、空白的处理;

      即当字符串中需要转义的字符比较多或字符串很长需要换行时,如何使字符串依然能够方便直观的书写;C# 提供了 @,Python则提供了 r""" """,更为强大和方便

      输入

      print r"df'h'sf\"s\"f\
      \ns"

      print """df'h'sf"s"f
      \ns"""

      输出

      df'h'sf\"s\"f\
      \ns

      df'h'sf"s"f

      s
      (注意中间有个空行)

      总结一下:

       

      是否需要对'"至少其一转义

      是否需要行尾\连接下一行

      转义序列是否变成普通字面量

      r

      Yes

      Yes

      Yes

      """ """

      No

      No

      No

       

      • other

      list comprehension

      generator expression

      yield...

       

      二、运行时

      1. 函数是一等公民

      函数本身是一对象,称作function object

      可以用变量命名,可以提供给过程作为参数,可以由过程作为结果返回,可以包含在数据结构中
       

       

      2. 类本身是对象,一切数据类型都是对象

      与C++不同,在那里,类定义只存在于编译时,运行时只有实例化的对象;在Python中,类定义与类实例一样,都是对象,都在运行时平等的存在;事实上,Python所有数据类型都是对象;

      在类中定义的一切对象都叫做类的“属性”,包括数据和method对象等;有效的“属性”是类对象被创建时所声明的对象,但类对象和实例对象都可以动态增删“属性”,对增删之前的已经创建的实例或对象没有影响,只影响增删之后的代码

      类对象和实例对象都可以动态修改“属性”,即对属性重新赋值,对修改之前和之后创建的实例都有影响

      通俗一点讲就是类可以动态的随时增删成员,对成员重新赋值(包括将函数对象指向另外的函数体),因此可以在运行时动态调整、重新组装类的行为,实现诸如mixin之类灵活机制

       

       

      三. Python与软件工程

      1. Built-in Unit Test

      标准模块中包含doctest, unittest,test等用于进行各种测试

      其中doctest允许你将测试写在函数的注释中,这对于阅读代码的人理解函数的使用有很大的帮助

      unittest基本类似JUnit

       

      2. 访问控制

      不知为何Python没有提供像C++和Java那样的访问控制,无法控制在module中定义的function和class的可见性;class中定义的function和variable倒是可以通过不少于两个下划线的前缀和不多于一个下划线的后缀标明这是class“私有”的.

      在Python中文邮件列表问了一下,感觉至少有三种workaround:

       

      1, 对于class中打算私有的函数定义以两个下划线开头

      class SomeClass:
          def pub_func(self):
              self.__private_func()

          def __private_func(self):
              print 'impl'

      SomeClass().pub_func()

      SomeClass().__private_func() #AttributeError: SomeClass instance has no attribute '__private_func'
       

      2,对于module中打算私有的function或class,定义到单独的module中,在package的__init__.py中定义__all__,使其不包括这个单独的module

      并且不能在其它module的全局空间中import这个单独的module;例如,包结构:

      util\__init__.py

           \private.py

           \pub.py

      in util\__init__.py:

          __all__=["pub"]

      in util\private.py

          def private_func():
              print 'private'

      in util\pub.py

          def pub_func():

              import private

              private.private_func()

      客户代码:

      from util import *

      pub.pub_func()        #ok
      private.private_func() #NameError: name 'private' is not defined

      但如果客户from util import private 还是可以使用private module的

       

      3, 将打算私有的代码以可交互语言编写扩展,并以二进制提供

       

      以上方法都不尽如人意,基本上,问题是在Python中有没有访问控制的必要?什么情况下会有?如果有必要的话应该怎么控制呢?

      我不知道

      发表于 @ 2006年02月23日 10:58:00|评论(loading...)|收藏

      新一篇: The C# Programming Language Notes II | 旧一篇: The SICP Notes

      评论

      #Could 发表于2006-02-24 10:03:00  IP: 58.49.232.*
      python里面不存在真正的私有属性,也没有protected属性,这个是其最垃圾的地方,在py用户中也存在诸多争论。我曾经在邮件列表中问过此问题,结果那个问题回了一千多次,应该是我见过的回复次数最多的一个问题了。但是没有私有这其实也是python的特性决定的,任何对象在虚拟机里面都是一个c语言类型的结构(struct),对象的方法和属性都在一个字典里面,你可以通过对象的字典去查它有什么方法和属性,这样的好处就是可以在c/c++/delphi等语言里面通过同样的方式来潜入py代码,所以python可以和这些语言进行几乎100%的交互.既然什么东西都是在字典里面查出来的,所以你想隐藏也是隐藏不了的,所以说没有私有变量,这个是其优点决定的缺点.如果python要真正地支持私有,那这种语言就面目全非了。

      其实如果能够有真正的私有属性当然是有必要的,因为这个使得编程更加容易.但是python不行,你只能通过代码的风格来约束自己,比如说前面加两个下划线的是私有的,前面加一个下划线的是保护的.如果你自己的风格形成了,就和真正的私有变量是一样的。再说即使在c#/java里面,私有的东西也是可以通过反射机制一览无余的,所以100%的私有也未必真正的必要,有时候编码的风格习惯更为重要。

      当初我就是因为python没有私有属性这一垃圾特性曾一度地想放弃它,但是后来鉴于其优点,我还是一直用下去了,因为它和其它的语言有很好的交互性,ms的ironpython出了正式版以后应该会集成在visualstudio中,到时候有了一个无与伦比的集成环境,编码和调试都回更加方便,所以py大有前途。

      脚本语言有其不可替代的优点,和强类型语言互补,所以熟悉一门脚本语言对编程有很多大帮助,根据个人不同的喜好,可以选择一门自己喜欢的,比如说如果觉得私有很重要,可以选择ruby。
      #萧风 发表于2006-02-24 10:31:00  IP: 218.2.157.*
      python是有private属性的,不如楼上何以说没有?只不过python的自由和随意性,没有显式的加以说明罢了,可以参考下面的代码:

      class CPrivateDemo:
      def __init__(self):
      self.__private_var = 29
      self.public_var = 30

      if __name__ == "__main__":
      x = CPrivateDemo()
      print x.public_var
      print x.__private_var
      #杠杠杠 发表于2006-02-24 20:54:00  IP: 210.21.13.*
      print _CPrivateDemo__private_var
      #Jin Qing 发表于2006-08-02 14:02:00  IP: 218.83.58.*
      看个tutorial就有如此见识,真是功底深厚啊。

      看上面萧风的一段代码,试运行,出现错误:
      AttributeError: CPrivateDemo instance has no attribute '__private_var'

      是不是双下划开头的都是私有属性?
      我也是刚学,看tutorial不仔细,或都里面没有提到?

      现在正学着用XRCed呢。
      发表评论  


      登录
      Csdn Blog version 3.1a
      Copyright © 切尔斯基