是否有更高效的衬垫来根据条件初始化变量?

时间:2011-05-10 11:18:35

标签: python

atype变量可以通过一个班轮进行初始化吗?

def detect(dt,result):
    """ prints the type of date """
    atype = 'unknown'
    if 'greg' in result:
        atype = 'Gregorian'
    elif 'eth' in result:
        atype = 'Ethiopian'

    print '%s is in %s format.' % (dt,atype)

6 个答案:

答案 0 :(得分:4)

你可以使用一对条件表达式 - 根本不需要括号;就像Python知道1 + 2 + 3应该从左到右合理地完成,所以条件表达式可以用一个又一个子句写,而不用担心解释器会混淆。换行符和缩进对于可读性很重要,所以我通常会这样做:

atype = ('Gregorian' if 'greg' in result
         else 'Ethiopian' if 'eth' in result
         else 'unknown')

这种形式的缩进不仅是大多数编辑在任何情况下如果你在每个else之前按下“输入”而产生的缩进形式,但是当我稍后回来时它给我带来了很大的视觉感受并阅读我自己或其他人的代码 - 这毕竟是我们使用Python的一个重要原因,对吧? :)

编辑当然我意识到这只是一个单行内容,因为Python认为续行是一行代码;所以我想我的答案是你的程序对我来说似乎有点密集作为Python的一个物理系列,但如果写成一个逻辑行,我的眼睛效果很好Python!

编辑:还有一点需要注意:当然,我认识到我的代码段违反了PEP-8,后者说要继续与运营商联系 - 所以PEP-8会让我移动{{ 1}}直到前一行末尾的单词。我只能说这是我不同意的PEP-8规则之一,我经常打破它,因此我生成了更可读的代码。我认为我在这一点上与PEP-8的不同之处在于具有数学排版背景,并且正如Donald Knuth在TeXBook中强调的那样,“显示公式总是在二元运算和关系之前打破”(p。 195)。

答案 1 :(得分:2)

不确定这是否有意义且可读......

atype = 'Gregorian' if 'greg' in result else ('Ethiopian' if 'eth' in result else 'unknown')

答案 2 :(得分:1)

就个人而言,在论坛上,我建议

def detect(dt,result):
    """ prints the type of date """
    style = 'Gregorian' if 'greg' in result else\
            'Ethiopian' if 'eth'  in result else\
            'unknown'
    print '%s is in %s format.' % (dt,style)

在我的代码的秘密中,没有人会来看我是否尊重Python的禅,我会这样做:

def detect(dt,result):
    """ prints the type of date """
    print dt + ' is in %s format.'\
          % \
          'Gregorian' if 'greg' in result else\
          'Ethiopian' if 'eth'  in result else\
          'unknown'

我测量了执行的次数:第二次是在第一次

的89%的时间内运行

编辑1

我进行的测试最终并不能让我满意,因为将完成任务的程序(风格=等)与没有同等分配的程序进行比较是不公平的。 / p>

所以我再次测试,修改了代码。为了强调代码之间差异的影响,我添加了一些条件。

我单独运行了以下程序(以避免可能重新分配的对象的可能持久性而不必重新创建;我不确切地知道在内存和Python的对象模型中发生了什么,以及它是否可能事实上发生;但是当我测量执行时间时,我有时会观察到奇怪的现象。所以我不冒险,我将代码分开)

第一个程序

from time import clock

A=[]

for repeat in xrange(5000):
    def detect(dt,result):
        if 'greg' in result:
            h = '%s is in %s format.' % (dt,'Gregorian')
        elif 'eth' in result:
            h = '%s is in %s format.' % (dt,'Ethiopian')
        elif 'ame' in result:
            h = '%s is in %s format.' % (dt,'American')
        elif 'rus' in result:
            h = '%s is in %s format.' % (dt,'Russian')
        elif 'egyp' in result:
            h = '%s is in %s format.' % (dt,'Egyptian')
        else:
            h = '%s is in unknown format.' % dt

    te = clock()
    for i in xrange(10000):
        detect('zozo',' he is egyptolog')
    A.append(clock() - te)

print min(A)

第二个程序

from time import clock

B=[]

for repeat in xrange(5000):


def detect(dt,result):
    x  = '%s is in %s format.' % (dt,'Gregorian' if 'greg' in result else\
                                  'Ethiopian' if 'eth'  in result else\
                                  'American' if 'ame'  in result else\
                                  'Russian' if 'rus'  in result else\
                                  'Egyptian' if 'egyp'  in result else\
                                  'unknown')

te = clock()
for i in xrange(10000):
    detect('zozo',' he is egyptolog')
B.append(clock() - te)

print min(B)

第三个程序

from time import clock

C = []

for repeat in xrange(1000):
    def detect(dt,result):
        y = dt + ' is in %s format.'\
            % \
            'Gregorian' if 'greg' in result else\
            'Ethiopian' if 'eth'  in result else\
            'American' if 'ame'  in result else\
            'Russian' if 'rus'  in result else\
            'Egyptian' if 'egyp'  in result else\
            'unknown'

    te = clock()
    for i in xrange(10000):
        detect('zozo',' he is egyptolog')
    C.append(clock() - te)

print min(C)

我获得了

  

0.0198832秒

     

0,019962秒

     

0,012664秒

结论:

  • 使用if-elif-else条件编写代码的方式与if-else-else-else连续条件之间没有区别。

    然后,即使第二种方式并不比德尔南认为的那么残酷,但是它的立即可理解性稍差,所以我终于发现第一种写作方式比第二种方式更好,因为它具有完美的可读性,而且没有松动任何数量的表现。

    if-else-else的使用很有趣,并且在某些情况下是唯一的解决方案,当不可能使用if-elif-else时,例如列表解析或编写lambda函数。

    < / LI>
  • 这一次,我的代码以另外两次执行时间的64%运行。有待检查的条件越多,我的代码就越快

    如果有人担心性能问题,可以使用此解决方案。如果没有,if-elif-else条件的连续性对我来说是最好的选择。

编辑2

@eat,

假设有一百万个元素的列表,就像这个

li = [('greg','Gregorian'),('eth','Ethiopian')]

已使用cPickle以序列化格式记录。然后代码将是:

import cPickle  

with open('trynewline.txt','r') as f:
    li = cPickle.load(f)

def detect(dt,result):
    for a,b in li:
        if a in result:
            return '%s is in %s format.' % (dt,b)
        else:
            return '%s is in unknown format.' % dt

import cPickle  

with open('trynewline.txt','r') as f:
    li = cPickle.load(f)

def detect(dt,result):
    ha = [ b for a,b in li if a in result]
    y = dt + ' is in %s format.'\
        % (ha[0] if ha else 'unknown')

这就是全部。无论如何, li 中包含的数据必须来自某个地方。它可以自动生成;或者它是手动生产的。如果它是手动生成的并且没有人在我之前创建,我将不得不自己手动编写一百万个条件。如果是你必须编写代码,你也会这样做。我看不出你怎么用你的字典来避免它。

答案 3 :(得分:0)

是的,Python的变量范围与其他编程语言略有不同。 所以,

if 'greg' in result:
    atype = 'Gregorian' 

print(atype)

会做得很好。还

if 'greg' in result: atype = 'Gregorian'
print(atype)

可行,除非它是一个Python shell(你必须执行整个脚本)

但无论如何,进行非常长的,依赖于条件的变量初始化是一种不好的做法。

答案 4 :(得分:0)

实际上很奇怪但是..这只是一种不同的方式来做它。我认为它更容易扩展,但我想有更好的方法;)

import operator as op
import functools as fc

atype = {'greg':'Gregorian', 'eth':'Ethiopian'}.get(filter(fc.partial(op.contains, ('greg', 'eth')), res)[0], 'unknown')

答案 5 :(得分:0)

虽然设置一个字典有一个单独的行,但这里有一个单行(为了便于阅读而分为两行):

typemap = {'greg': 'Gregorian', 'eth': 'Ethiopian'}

atype = ([typemap[frag] for frag in typemap if frag in result][0]
         if any(frag in result for frag in typemap) else 'unknown')