Categories

Links

留个纪念

今天是6月1日 ,离5月7日我正式使用python开发应用快一个月了,因为做的是python应用,跨平台是一个主要目标,因此,将开发环境转到ubuntu 也接近一周。

要说有什么感想,实际上很多,但可能都不成熟,随便说几点

1. 速度
速度是个相对的概念,java快还是python快,.net 快还是python快,大家可能都有结论。但实际上使用wxPython,界面实际的呈现却是非常的快。这也是我使用python开发这个应用的主要原因。其实,一个框架或应用的层次越少,它就越快。
2. 设计
没有完美的设计我想大家都清楚,不应该追求它大家也清楚。但实际上呢?没有一个架构师能躲开这点。环境造人,你用java能不用spring,hibernate吗?能不考虑domain driven还是transaction script吗?.net 也是如此,有许多事情会干扰你做真正的事情,什么事情,应用,客户要看到真正的应用,而不是你的夸夸其谈。 如果你在python或是ruby那种环境,这点你可能会比较轻松的绕过去。 但是,虽然动态语言实用为第一,但也是同样模式和设计,只不过方式不同而已,更直接了当。 这也是我下面要讲的一点。
3. 玩票和实际使用是不同的
学什么要像什么,玩票性质的不会给你带来语言的真正感受,像python或是ruby那样思考是不容易的,你要时刻检讨,我真的需要工厂吗?真的需要接口吗? 每种语言用久了,会有一些习惯思维,比方说vb,它总是在外部操作对象,而不是直接继承,在class内部做些事情。同样,java,.net 用多了,凡事必先构造类,其实很多事情方法就可以解决,如果不需要保存上下文变量,不需要用继承达到重用,方法可以简单的解决很多问题。


4. ubuntu 对windows 未来会有很大的冲击,不管你作不作linux下开发,你应该安装一个。
5. ide 不是必需的,其实,在好多年前,don box 用emacs 做演示时就想用emacs ,不过,到今天才算真正的拿来用开发。
6. 动态语言的高效有时是假象。你可以像以前开发asp一样的开发,写代码,运行它,但实际上,这样做是很低效的,动态语言有太多的输入错误,你必须为自己找到一种快速修正的途径,像单元测试或是一些脚本。在这里,单元测试变得真正的重要。否则,你会花费比静态语言更多的时间在修正输入错误上。

[2007-06-01 23:04:00 | Author:jiangjianxiao ] [] 2 comments

今天被wx.DateTime郁闷了

由于DatePickerCtrl必须使用wx.DateTime,所以要将datetime.datetime格式转换为wx.DateTime,使用的是Set方法,结果发现某些日期就出错,如2007-3-31日,跟踪了一下,发现其是用GetNumberOfDaysInMonth(int month, int year=Inv_Year, int cal=Gregorian)的方法获得某年某月的总日数,结果

wx.DateTime.GetNumberOfDaysInMonth(3,2007),结果返回的不是31而是30,奇怪了,bug???

无法了,过了一小时,忽然灵机一动,会不会是用0表示的 1月啊,输入wx.DateTime.GetNumberOfDaysInMonth(2,2007),返回了31,正确.

看来这里,动态语言也要用上类型判断了,没办法,重新写了一个类

class MyDatePickerCtrl(wx.DatePickerCtrl):
    def __init__(self,parent,id=wx.ID_ANY,default=wx.DateTime.Now()):
        super(MyDatePickerCtrl,self).__init__(parent,id)
        self.default=default
    def SetValue(self,value):
        if value is None and not self.default is None:
            super(MyDatePickerCtrl,self).SetValue(self.default)
        else:
            #todo 忽略毫秒
            if isinstance(value,datetime.datetime):
                super(MyDatePickerCtrl,self).SetValue(wx.DateTime().Set(value.day,value.month-1,value.year,value.hour,value.minute,value.second,0))
            elif isinstance(value,wx.DateTime):
                super(MyDatePickerCtrl,self).SetValue(value)

[2007-05-29 11:57:21 | Author:jiangjianxiao ] [] 1 comments

ipod video 游戏被破解

试着运行了一下,效果还真是不错,如果环境许可,还是购买正版吧

http://www.91apple.com/viewthread.php?tid=37855&extra=page%3D1

[2007-05-25 08:28:37 | Author:jiangjianxiao ] [] 1 comments

python 笔记 -threadlocal

ThreadLocal是很多设计模式的实现的基础,典型的如 Unit of work.在python 2.4以前,没有对thread local的直接支持,不过可以使用thread.get_ident()获得当前线程的id值,然后用以下方式模拟

来自sqlalchemy
class ThreadLocal(object):
    """An object in which attribute access occurs only within the context of the current thread."""

    def __init__(self):
        self.__dict__['_tdict'] = {}

    def __delattr__(self, key):
        try:
            del self._tdict["%d_%s" % (thread.get_ident(), key)]
        except KeyError:
            raise AttributeError(key)

    def __getattr__(self, key):
        try:
            return self._tdict["%d_%s" % (thread.get_ident(), key)]
        except KeyError:
            raise AttributeError(key)

    def __setattr__(self, key, value):
        self._tdict["%d_%s" % (thread.get_ident(), key)] = value        

ThreadLocal创建一个_tdict 属性dict,然后根据thrad.get_ident()的值创建线程相关的dict,通过__setattr__和__getattr__,你可以按如下调用 

 

response=ThreadLocal()
response.id=1
response.name='xxx'

像id,name这些值都是 threadlocal的

在Python 2.4后,你可以直接使用threading.local来返回一个thread local的对象,如

response=threading.local()
response.id=1

下面这段代码效果是一样的

response=thread._local()
response.id=1


print response.name
del(response.id)

[2007-05-23 09:43:33 | Author:jiangjianxiao ] [] 1 comments

map, filter, list comprehensions

map 和filter都是对一个列表进行操作,它依次取出列表中元素,然后将其传给map/filter的第一个参数(那是一个函数),最后返回一个列表

两者的不同是
map 是取这个函数的返回值,然后追加到map函数的返回值列表中

filter 则是根据这个函数返回值是True或是False,将 这个列表中的元素 追加到filter函数的返回值列表

 


>>> map(lambda x: x.startswith('visual'),['visual basic','visual c++','java','python'])
[True, True, False, False]
>>> filter(lambda x: x.startswith('visual'),['visual basic','visual c++','java','python'])
['visual basic', 'visual c++']

关于map/filter 存在着从下个版本去除的趋势,因为其不直观,替代的就是list comprehensions


filter 的 listcomprehensions写法

>>> [item for item in ['visual basic','visual c++','java','python'] if item.startswith('visual')]
['visual basic', 'visual c++']

map的listcomprehensions写法,就是要把原来函数的表示式提前

>>> [item.startswith('visual') for item in ['visual basic','visual c++','java','python']]
[True, True, False, False]


但list comprehensions 的功能还不仅于此,它可以迭代多个列表,进行多个判断

如取出一个列表中的那些元素同时存在于另外两个列表
a=[3,6,7]
b=[7,9,10,6]
c=[6,5,3]

[item for item in a if item in b   if item in c]


下面是一段实际的代码,binding对象有个对其它对象的一个方法引用(getter),如果这个引用存在,则执行这个方法(getter()获取值),刚开始用python时通常会这样写
    def _collect(self):
         record={}
         for binding in self.bindings:
             if binding.getter:
                 record[binding.property_name]=binding.getter()
         return record
但实际上可以写成
    def _collect(self):
        return dict([(binding.property_name,binding.getter()) for binding in self.bindings
if binding.getter])

深入
通常,列表是常见的可迭代对象,但tuple或是dict都是(默认对dict迭代其keys(),你可以可以显式的使用keys(),values()或是items()函数),由于filter的语义,它会返回被迭代对象的实际类型如

>>> filter(lambda x: x%2==0,(2,3,4,5))
(2, 4)
>>>

接下去,试着用()来代替list comprehensions的[],会得到什么?
>>> a= (x for x in [1,2,3] if x%2==0)
>>> a.next()
2
>>> type(a)
<type 'generator'>
>>>

因为a 是个generator ,所以可以用如下内置函数,如

sum(x for x in [1,2,3])  # 6
max(x for x in [1,2,3])             # 3
min(x for x in [1,2,3])            # 1

可用的还有all,any   版本2.5
enumerator  版本2.3 返回enumerate 对象,可以用for in 处理
list 转换为list
set 转换为set
sorted 排序
zip 返回一个tuple的list

参考: list comprehensions http://www.python.org/dev/peps/pep-0202/
注: 这里列表指可迭代的对象,通常是list对象

[2007-05-21 09:18:22 | Author:jiangjianxiao ] [] 1 comments

Total 91 Display 31 of 35
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Powered by Google App Engine